Jonathan Hart
Committed by Gerrit Code Review

Don't flood ARP packets out the port they came in on.

Also renamed ProxyArpService#known(Ip4Address) to
ProxyArpService#isKnown(Ip4Address)

Fixes ONOS-722.

Change-Id: I136c65e58693926e87b822cb0f4ec1c4ba0e3780
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
15 */ 15 */
16 package org.onosproject.net.proxyarp; 16 package org.onosproject.net.proxyarp;
17 17
18 -import org.onosproject.net.ConnectPoint;
19 -import org.onosproject.net.packet.PacketContext;
20 import org.onlab.packet.Ethernet; 18 import org.onlab.packet.Ethernet;
21 import org.onlab.packet.Ip4Address; 19 import org.onlab.packet.Ip4Address;
20 +import org.onosproject.net.ConnectPoint;
21 +import org.onosproject.net.packet.PacketContext;
22 22
23 /** 23 /**
24 * Service for processing arp requests on behalf of applications. 24 * Service for processing arp requests on behalf of applications.
...@@ -32,7 +32,7 @@ public interface ProxyArpService { ...@@ -32,7 +32,7 @@ public interface ProxyArpService {
32 * @param addr an IPv4 address 32 * @param addr an IPv4 address
33 * @return true if know, false otherwise 33 * @return true if know, false otherwise
34 */ 34 */
35 - boolean known(Ip4Address addr); 35 + boolean isKnown(Ip4Address addr);
36 36
37 /** 37 /**
38 * Sends a reply for a given request. If the host is not known then the arp 38 * Sends a reply for a given request. If the host is not known then the arp
...@@ -48,8 +48,9 @@ public interface ProxyArpService { ...@@ -48,8 +48,9 @@ public interface ProxyArpService {
48 * destination is not known. 48 * destination is not known.
49 * 49 *
50 * @param eth an ethernet frame containing an ARP request. 50 * @param eth an ethernet frame containing an ARP request.
51 + * @param inPort the port the request was received on
51 */ 52 */
52 - void forward(Ethernet eth); 53 + void forward(Ethernet eth, ConnectPoint inPort);
53 54
54 /** 55 /**
55 * Handles a arp packet. 56 * Handles a arp packet.
......
...@@ -116,7 +116,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -116,7 +116,7 @@ public class ProxyArpManager implements ProxyArpService {
116 } 116 }
117 117
118 @Override 118 @Override
119 - public boolean known(Ip4Address addr) { 119 + public boolean isKnown(Ip4Address addr) {
120 checkNotNull(addr, MAC_ADDR_NULL); 120 checkNotNull(addr, MAC_ADDR_NULL);
121 Set<Host> hosts = hostService.getHostsByIp(addr); 121 Set<Host> hosts = hostService.getHostsByIp(addr);
122 return !hosts.isEmpty(); 122 return !hosts.isEmpty();
...@@ -189,7 +189,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -189,7 +189,7 @@ public class ProxyArpManager implements ProxyArpService {
189 } 189 }
190 190
191 if (src == null || dst == null) { 191 if (src == null || dst == null) {
192 - flood(eth); 192 + flood(eth, inPort);
193 return; 193 return;
194 } 194 }
195 195
...@@ -263,7 +263,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -263,7 +263,7 @@ public class ProxyArpManager implements ProxyArpService {
263 } 263 }
264 264
265 @Override 265 @Override
266 - public void forward(Ethernet eth) { 266 + public void forward(Ethernet eth, ConnectPoint inPort) {
267 checkNotNull(eth, REQUEST_NULL); 267 checkNotNull(eth, REQUEST_NULL);
268 checkArgument(eth.getEtherType() == Ethernet.TYPE_ARP, 268 checkArgument(eth.getEtherType() == Ethernet.TYPE_ARP,
269 REQUEST_NOT_ARP); 269 REQUEST_NOT_ARP);
...@@ -274,7 +274,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -274,7 +274,7 @@ public class ProxyArpManager implements ProxyArpService {
274 VlanId.vlanId(eth.getVlanID()))); 274 VlanId.vlanId(eth.getVlanID())));
275 275
276 if (h == null) { 276 if (h == null) {
277 - flood(eth); 277 + flood(eth, inPort);
278 } else { 278 } else {
279 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder(); 279 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
280 builder.setOutput(h.location().port()); 280 builder.setOutput(h.location().port());
...@@ -291,7 +291,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -291,7 +291,7 @@ public class ProxyArpManager implements ProxyArpService {
291 if (ethPkt != null && ethPkt.getEtherType() == Ethernet.TYPE_ARP) { 291 if (ethPkt != null && ethPkt.getEtherType() == Ethernet.TYPE_ARP) {
292 ARP arp = (ARP) ethPkt.getPayload(); 292 ARP arp = (ARP) ethPkt.getPayload();
293 if (arp.getOpCode() == ARP.OP_REPLY) { 293 if (arp.getOpCode() == ARP.OP_REPLY) {
294 - forward(ethPkt); 294 + forward(ethPkt, context.inPacket().receivedFrom());
295 } else if (arp.getOpCode() == ARP.OP_REQUEST) { 295 } else if (arp.getOpCode() == ARP.OP_REQUEST) {
296 reply(ethPkt, context.inPacket().receivedFrom()); 296 reply(ethPkt, context.inPacket().receivedFrom());
297 } 297 }
...@@ -305,14 +305,14 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -305,14 +305,14 @@ public class ProxyArpManager implements ProxyArpService {
305 * Flood the arp request at all edges in the network. 305 * Flood the arp request at all edges in the network.
306 * @param request the arp request. 306 * @param request the arp request.
307 */ 307 */
308 - private void flood(Ethernet request) { 308 + private void flood(Ethernet request, ConnectPoint inPort) {
309 TrafficTreatment.Builder builder = null; 309 TrafficTreatment.Builder builder = null;
310 ByteBuffer buf = ByteBuffer.wrap(request.serialize()); 310 ByteBuffer buf = ByteBuffer.wrap(request.serialize());
311 311
312 synchronized (externalPorts) { 312 synchronized (externalPorts) {
313 for (Entry<Device, PortNumber> entry : externalPorts.entries()) { 313 for (Entry<Device, PortNumber> entry : externalPorts.entries()) {
314 ConnectPoint cp = new ConnectPoint(entry.getKey().id(), entry.getValue()); 314 ConnectPoint cp = new ConnectPoint(entry.getKey().id(), entry.getValue());
315 - if (isOutsidePort(cp)) { 315 + if (isOutsidePort(cp) || cp.equals(inPort)) {
316 continue; 316 continue;
317 } 317 }
318 318
......
...@@ -239,7 +239,7 @@ public class ProxyArpManagerTest { ...@@ -239,7 +239,7 @@ public class ProxyArpManagerTest {
239 } 239 }
240 240
241 /** 241 /**
242 - * Tests {@link ProxyArpManager#known(Ip4Address)} in the case where the 242 + * Tests {@link ProxyArpManager#isKnown(Ip4Address)} in the case where the
243 * IP address is not known. 243 * IP address is not known.
244 * Verifies the method returns false. 244 * Verifies the method returns false.
245 */ 245 */
...@@ -248,11 +248,11 @@ public class ProxyArpManagerTest { ...@@ -248,11 +248,11 @@ public class ProxyArpManagerTest {
248 expect(hostService.getHostsByIp(IP1)).andReturn(Collections.<Host>emptySet()); 248 expect(hostService.getHostsByIp(IP1)).andReturn(Collections.<Host>emptySet());
249 replay(hostService); 249 replay(hostService);
250 250
251 - assertFalse(proxyArp.known(IP1)); 251 + assertFalse(proxyArp.isKnown(IP1));
252 } 252 }
253 253
254 /** 254 /**
255 - * Tests {@link ProxyArpManager#known(Ip4Address)} in the case where the 255 + * Tests {@link ProxyArpManager#isKnown(Ip4Address)} in the case where the
256 * IP address is known. 256 * IP address is known.
257 * Verifies the method returns true. 257 * Verifies the method returns true.
258 */ 258 */
...@@ -265,7 +265,7 @@ public class ProxyArpManagerTest { ...@@ -265,7 +265,7 @@ public class ProxyArpManagerTest {
265 .andReturn(Sets.newHashSet(host1, host2)); 265 .andReturn(Sets.newHashSet(host1, host2));
266 replay(hostService); 266 replay(hostService);
267 267
268 - assertTrue(proxyArp.known(IP1)); 268 + assertTrue(proxyArp.isKnown(IP1));
269 } 269 }
270 270
271 /** 271 /**
...@@ -314,7 +314,7 @@ public class ProxyArpManagerTest { ...@@ -314,7 +314,7 @@ public class ProxyArpManagerTest {
314 314
315 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1); 315 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1);
316 316
317 - proxyArp.reply(arpRequest, getLocation(5)); 317 + proxyArp.reply(arpRequest, getLocation(6));
318 318
319 verifyFlood(arpRequest); 319 verifyFlood(arpRequest);
320 } 320 }
...@@ -341,7 +341,7 @@ public class ProxyArpManagerTest { ...@@ -341,7 +341,7 @@ public class ProxyArpManagerTest {
341 341
342 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1); 342 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1);
343 343
344 - proxyArp.reply(arpRequest, getLocation(5)); 344 + proxyArp.reply(arpRequest, getLocation(6));
345 345
346 verifyFlood(arpRequest); 346 verifyFlood(arpRequest);
347 } 347 }
...@@ -435,7 +435,7 @@ public class ProxyArpManagerTest { ...@@ -435,7 +435,7 @@ public class ProxyArpManagerTest {
435 435
436 Ethernet arpRequest = buildArp(ARP.OP_REPLY, MAC2, MAC1, IP2, IP1); 436 Ethernet arpRequest = buildArp(ARP.OP_REPLY, MAC2, MAC1, IP2, IP1);
437 437
438 - proxyArp.forward(arpRequest); 438 + proxyArp.forward(arpRequest, LOC2);
439 439
440 assertEquals(1, packetService.packets.size()); 440 assertEquals(1, packetService.packets.size());
441 OutboundPacket packet = packetService.packets.get(0); 441 OutboundPacket packet = packetService.packets.get(0);
...@@ -455,18 +455,20 @@ public class ProxyArpManagerTest { ...@@ -455,18 +455,20 @@ public class ProxyArpManagerTest {
455 455
456 Ethernet arpRequest = buildArp(ARP.OP_REPLY, MAC2, MAC1, IP2, IP1); 456 Ethernet arpRequest = buildArp(ARP.OP_REPLY, MAC2, MAC1, IP2, IP1);
457 457
458 - proxyArp.forward(arpRequest); 458 + proxyArp.forward(arpRequest, getLocation(6));
459 459
460 verifyFlood(arpRequest); 460 verifyFlood(arpRequest);
461 } 461 }
462 462
463 /** 463 /**
464 - * Verifies that the given packet was flooded out all available edge ports. 464 + * Verifies that the given packet was flooded out all available edge ports,
465 + * except for the input port.
465 * 466 *
466 * @param packet the packet that was expected to be flooded 467 * @param packet the packet that was expected to be flooded
467 */ 468 */
468 private void verifyFlood(Ethernet packet) { 469 private void verifyFlood(Ethernet packet) {
469 - assertEquals(NUM_FLOOD_PORTS, packetService.packets.size()); 470 + // There should be 1 less than NUM_FLOOD_PORTS; the inPort should be excluded.
471 + assertEquals(NUM_FLOOD_PORTS - 1, packetService.packets.size());
470 472
471 Collections.sort(packetService.packets, 473 Collections.sort(packetService.packets,
472 new Comparator<OutboundPacket>() { 474 new Comparator<OutboundPacket>() {
...@@ -476,7 +478,8 @@ public class ProxyArpManagerTest { ...@@ -476,7 +478,8 @@ public class ProxyArpManagerTest {
476 } 478 }
477 }); 479 });
478 480
479 - for (int i = 0; i < NUM_FLOOD_PORTS; i++) { 481 +
482 + for (int i = 0; i < NUM_FLOOD_PORTS - 1; i++) {
480 ConnectPoint cp = new ConnectPoint(getDeviceId(NUM_ADDRESS_PORTS + i + 1), 483 ConnectPoint cp = new ConnectPoint(getDeviceId(NUM_ADDRESS_PORTS + i + 1),
481 PortNumber.portNumber(1)); 484 PortNumber.portNumber(1));
482 485
......