Committed by
Gerrit Code Review
[ONOS-1264] Add IPv6 unit test for ProxyArpManager
Change-Id: I1d4ec1f06508bd1bf1d54b299b0ae4ac1d5482d9
Showing
1 changed file
with
387 additions
and
8 deletions
... | @@ -21,11 +21,19 @@ import org.junit.Before; | ... | @@ -21,11 +21,19 @@ import org.junit.Before; |
21 | import org.junit.Test; | 21 | import org.junit.Test; |
22 | import org.onlab.packet.ARP; | 22 | import org.onlab.packet.ARP; |
23 | import org.onlab.packet.Ethernet; | 23 | import org.onlab.packet.Ethernet; |
24 | +import org.onlab.packet.ICMP6; | ||
25 | +import org.onlab.packet.IPacket; | ||
26 | +import org.onlab.packet.IPv6; | ||
24 | import org.onlab.packet.Ip4Address; | 27 | import org.onlab.packet.Ip4Address; |
25 | import org.onlab.packet.Ip4Prefix; | 28 | import org.onlab.packet.Ip4Prefix; |
29 | +import org.onlab.packet.Ip6Address; | ||
30 | +import org.onlab.packet.Ip6Prefix; | ||
26 | import org.onlab.packet.IpPrefix; | 31 | import org.onlab.packet.IpPrefix; |
27 | import org.onlab.packet.MacAddress; | 32 | import org.onlab.packet.MacAddress; |
28 | import org.onlab.packet.VlanId; | 33 | import org.onlab.packet.VlanId; |
34 | +import org.onlab.packet.ndp.NeighborAdvertisement; | ||
35 | +import org.onlab.packet.ndp.NeighborDiscoveryOptions; | ||
36 | +import org.onlab.packet.ndp.NeighborSolicitation; | ||
29 | import org.onosproject.incubator.net.intf.Interface; | 37 | import org.onosproject.incubator.net.intf.Interface; |
30 | import org.onosproject.incubator.net.intf.InterfaceService; | 38 | import org.onosproject.incubator.net.intf.InterfaceService; |
31 | import org.onosproject.net.ConnectPoint; | 39 | import org.onosproject.net.ConnectPoint; |
... | @@ -66,9 +74,13 @@ import static org.easymock.EasyMock.anyObject; | ... | @@ -66,9 +74,13 @@ import static org.easymock.EasyMock.anyObject; |
66 | import static org.easymock.EasyMock.createMock; | 74 | import static org.easymock.EasyMock.createMock; |
67 | import static org.easymock.EasyMock.expect; | 75 | import static org.easymock.EasyMock.expect; |
68 | import static org.easymock.EasyMock.replay; | 76 | import static org.easymock.EasyMock.replay; |
77 | +import static org.hamcrest.Matchers.anyOf; | ||
78 | +import static org.hamcrest.Matchers.is; | ||
69 | import static org.junit.Assert.assertArrayEquals; | 79 | import static org.junit.Assert.assertArrayEquals; |
70 | import static org.junit.Assert.assertEquals; | 80 | import static org.junit.Assert.assertEquals; |
71 | import static org.junit.Assert.assertFalse; | 81 | import static org.junit.Assert.assertFalse; |
82 | +import static org.junit.Assert.assertNotNull; | ||
83 | +import static org.junit.Assert.assertThat; | ||
72 | import static org.junit.Assert.assertTrue; | 84 | import static org.junit.Assert.assertTrue; |
73 | 85 | ||
74 | /** | 86 | /** |
... | @@ -83,6 +95,8 @@ public class ProxyArpManagerTest { | ... | @@ -83,6 +95,8 @@ public class ProxyArpManagerTest { |
83 | 95 | ||
84 | private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1"); | 96 | private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1"); |
85 | private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2"); | 97 | private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2"); |
98 | + private static final Ip6Address IP3 = Ip6Address.valueOf("1000::1"); | ||
99 | + private static final Ip6Address IP4 = Ip6Address.valueOf("1000::2"); | ||
86 | 100 | ||
87 | private static final ProviderId PID = new ProviderId("of", "foo"); | 101 | private static final ProviderId PID = new ProviderId("of", "foo"); |
88 | 102 | ||
... | @@ -90,8 +104,14 @@ public class ProxyArpManagerTest { | ... | @@ -90,8 +104,14 @@ public class ProxyArpManagerTest { |
90 | private static final VlanId VLAN2 = VlanId.vlanId((short) 2); | 104 | private static final VlanId VLAN2 = VlanId.vlanId((short) 2); |
91 | private static final MacAddress MAC1 = MacAddress.valueOf("00:00:11:00:00:01"); | 105 | private static final MacAddress MAC1 = MacAddress.valueOf("00:00:11:00:00:01"); |
92 | private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02"); | 106 | private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02"); |
107 | + private static final MacAddress MAC3 = MacAddress.valueOf("00:00:33:00:00:03"); | ||
108 | + private static final MacAddress MAC4 = MacAddress.valueOf("00:00:44:00:00:04"); | ||
109 | + private static final MacAddress SOLICITED_MAC3 = MacAddress.valueOf("33:33:FF:00:00:01"); | ||
93 | private static final HostId HID1 = HostId.hostId(MAC1, VLAN1); | 110 | private static final HostId HID1 = HostId.hostId(MAC1, VLAN1); |
94 | private static final HostId HID2 = HostId.hostId(MAC2, VLAN1); | 111 | private static final HostId HID2 = HostId.hostId(MAC2, VLAN1); |
112 | + private static final HostId HID3 = HostId.hostId(MAC3, VLAN1); | ||
113 | + private static final HostId HID4 = HostId.hostId(MAC4, VLAN1); | ||
114 | + private static final HostId SOLICITED_HID3 = HostId.hostId(SOLICITED_MAC3, VLAN1); | ||
95 | 115 | ||
96 | private static final DeviceId DID1 = getDeviceId(1); | 116 | private static final DeviceId DID1 = getDeviceId(1); |
97 | private static final DeviceId DID2 = getDeviceId(2); | 117 | private static final DeviceId DID2 = getDeviceId(2); |
... | @@ -222,21 +242,29 @@ public class ProxyArpManagerTest { | ... | @@ -222,21 +242,29 @@ public class ProxyArpManagerTest { |
222 | 242 | ||
223 | for (int i = 1; i <= NUM_ADDRESS_PORTS; i++) { | 243 | for (int i = 1; i <= NUM_ADDRESS_PORTS; i++) { |
224 | ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1); | 244 | ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1); |
225 | - Ip4Prefix prefix1 = | 245 | + |
226 | - Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24"); | 246 | + // Interface address for IPv4 |
227 | - Ip4Address addr1 = | 247 | + Ip4Prefix prefix1 = Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24"); |
228 | - Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1"); | 248 | + Ip4Address addr1 = Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1"); |
229 | Ip4Prefix prefix2 = Ip4Prefix.valueOf("10.0." + (2 * i) + ".0/24"); | 249 | Ip4Prefix prefix2 = Ip4Prefix.valueOf("10.0." + (2 * i) + ".0/24"); |
230 | Ip4Address addr2 = Ip4Address.valueOf("10.0." + (2 * i) + ".1"); | 250 | Ip4Address addr2 = Ip4Address.valueOf("10.0." + (2 * i) + ".1"); |
231 | InterfaceIpAddress ia1 = new InterfaceIpAddress(addr1, prefix1); | 251 | InterfaceIpAddress ia1 = new InterfaceIpAddress(addr1, prefix1); |
232 | InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2); | 252 | InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2); |
233 | - Interface intf1 = new Interface(cp, Sets.newHashSet(ia1), | 253 | + |
254 | + // Interface address for IPv6 | ||
255 | + Ip6Prefix prefix3 = Ip6Prefix.valueOf((2 * i - 1) + "000::0/64"); | ||
256 | + Ip6Address addr3 = Ip6Address.valueOf((2 * i - 1) + "000::1"); | ||
257 | + Ip6Prefix prefix4 = Ip6Prefix.valueOf((2 * i) + "000::0/64"); | ||
258 | + Ip6Address addr4 = Ip6Address.valueOf((2 * i) + "000::1"); | ||
259 | + InterfaceIpAddress ia3 = new InterfaceIpAddress(addr3, prefix3); | ||
260 | + InterfaceIpAddress ia4 = new InterfaceIpAddress(addr4, prefix4); | ||
261 | + | ||
262 | + Interface intf1 = new Interface(cp, Sets.newHashSet(ia1, ia3), | ||
234 | MacAddress.valueOf(2 * i - 1), | 263 | MacAddress.valueOf(2 * i - 1), |
235 | VlanId.vlanId((short) 1)); | 264 | VlanId.vlanId((short) 1)); |
236 | - Interface intf2 = new Interface(cp, Sets.newHashSet(ia2), | 265 | + Interface intf2 = new Interface(cp, Sets.newHashSet(ia2, ia4), |
237 | MacAddress.valueOf(2 * i), | 266 | MacAddress.valueOf(2 * i), |
238 | VlanId.NONE); | 267 | VlanId.NONE); |
239 | - | ||
240 | interfaces.add(intf1); | 268 | interfaces.add(intf1); |
241 | interfaces.add(intf2); | 269 | interfaces.add(intf2); |
242 | 270 | ||
... | @@ -321,6 +349,41 @@ public class ProxyArpManagerTest { | ... | @@ -321,6 +349,41 @@ public class ProxyArpManagerTest { |
321 | 349 | ||
322 | /** | 350 | /** |
323 | * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the | 351 | * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the |
352 | + * destination host is known. | ||
353 | + * Verifies the correct NDP reply is sent out the correct port. | ||
354 | + */ | ||
355 | + @Test | ||
356 | + public void testReplyKnownIpv6() { | ||
357 | + //Set the return value of isEdgePoint from the edgemanager. | ||
358 | + isEdgePointReturn = true; | ||
359 | + | ||
360 | + Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(4), | ||
361 | + Collections.singleton(IP3)); | ||
362 | + | ||
363 | + Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5), | ||
364 | + Collections.singleton(IP4)); | ||
365 | + | ||
366 | + expect(hostService.getHostsByIp(IP3)) | ||
367 | + .andReturn(Collections.singleton(replyer)); | ||
368 | + expect(hostService.getHost(HID4)).andReturn(requestor); | ||
369 | + | ||
370 | + replay(hostService); | ||
371 | + replay(interfaceService); | ||
372 | + | ||
373 | + Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, | ||
374 | + MAC4, SOLICITED_MAC3, | ||
375 | + IP4, IP3); | ||
376 | + | ||
377 | + proxyArp.reply(ndpRequest, getLocation(5)); | ||
378 | + | ||
379 | + assertEquals(1, packetService.packets.size()); | ||
380 | + Ethernet ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT, | ||
381 | + MAC3, MAC4, IP3, IP4); | ||
382 | + verifyPacketOut(ndpReply, getLocation(5), packetService.packets.get(0)); | ||
383 | + } | ||
384 | + | ||
385 | + /** | ||
386 | + * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the | ||
324 | * destination host is not known. | 387 | * destination host is not known. |
325 | * Verifies the ARP request is flooded out the correct edge ports. | 388 | * Verifies the ARP request is flooded out the correct edge ports. |
326 | */ | 389 | */ |
... | @@ -337,7 +400,6 @@ public class ProxyArpManagerTest { | ... | @@ -337,7 +400,6 @@ public class ProxyArpManagerTest { |
337 | .andReturn(Collections.emptySet()); | 400 | .andReturn(Collections.emptySet()); |
338 | expect(hostService.getHost(HID2)).andReturn(requestor); | 401 | expect(hostService.getHost(HID2)).andReturn(requestor); |
339 | 402 | ||
340 | - | ||
341 | replay(hostService); | 403 | replay(hostService); |
342 | replay(interfaceService); | 404 | replay(interfaceService); |
343 | 405 | ||
... | @@ -355,6 +417,41 @@ public class ProxyArpManagerTest { | ... | @@ -355,6 +417,41 @@ public class ProxyArpManagerTest { |
355 | 417 | ||
356 | /** | 418 | /** |
357 | * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the | 419 | * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the |
420 | + * destination host is not known. | ||
421 | + * Verifies the NDP request is flooded out the correct edge ports. | ||
422 | + */ | ||
423 | + @Test | ||
424 | + public void testReplyUnknownIpv6() { | ||
425 | + isEdgePointReturn = true; | ||
426 | + | ||
427 | + Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5), | ||
428 | + Collections.singleton(IP4)); | ||
429 | + | ||
430 | + expect(hostService.getHostsByIp(IP3)) | ||
431 | + .andReturn(Collections.emptySet()); | ||
432 | + expect(interfaceService.getInterfacesByIp(IP4)) | ||
433 | + .andReturn(Collections.emptySet()); | ||
434 | + expect(hostService.getHost(HID4)).andReturn(requestor); | ||
435 | + | ||
436 | + replay(hostService); | ||
437 | + replay(interfaceService); | ||
438 | + | ||
439 | + Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, | ||
440 | + MAC4, SOLICITED_MAC3, | ||
441 | + IP4, IP3); | ||
442 | + | ||
443 | + //Setup the set of edge ports to be used in the reply method | ||
444 | + getEdgePointsNoArg = Lists.newLinkedList(); | ||
445 | + getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1))); | ||
446 | + getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1))); | ||
447 | + | ||
448 | + proxyArp.reply(ndpRequest, getLocation(6)); | ||
449 | + | ||
450 | + verifyFlood(ndpRequest); | ||
451 | + } | ||
452 | + | ||
453 | + /** | ||
454 | + * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the | ||
358 | * destination host is known for that IP address, but is not on the same | 455 | * destination host is known for that IP address, but is not on the same |
359 | * VLAN as the source host. | 456 | * VLAN as the source host. |
360 | * Verifies the ARP request is flooded out the correct edge ports. | 457 | * Verifies the ARP request is flooded out the correct edge ports. |
... | @@ -388,6 +485,46 @@ public class ProxyArpManagerTest { | ... | @@ -388,6 +485,46 @@ public class ProxyArpManagerTest { |
388 | verifyFlood(arpRequest); | 485 | verifyFlood(arpRequest); |
389 | } | 486 | } |
390 | 487 | ||
488 | + /** | ||
489 | + * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the | ||
490 | + * destination host is known for that IP address, but is not on the same | ||
491 | + * VLAN as the source host. | ||
492 | + * Verifies the NDP request is flooded out the correct edge ports. | ||
493 | + */ | ||
494 | + @Test | ||
495 | + public void testReplyDifferentVlanIpv6() { | ||
496 | + | ||
497 | + Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN2, getLocation(4), | ||
498 | + Collections.singleton(IP3)); | ||
499 | + | ||
500 | + Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5), | ||
501 | + Collections.singleton(IP4)); | ||
502 | + | ||
503 | + expect(hostService.getHostsByIp(IP3)) | ||
504 | + .andReturn(Collections.singleton(replyer)); | ||
505 | + expect(interfaceService.getInterfacesByIp(IP4)) | ||
506 | + .andReturn(Collections.emptySet()); | ||
507 | + expect(hostService.getHost(HID4)).andReturn(requestor); | ||
508 | + | ||
509 | + replay(hostService); | ||
510 | + replay(interfaceService); | ||
511 | + | ||
512 | + Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, | ||
513 | + MAC4, SOLICITED_MAC3, | ||
514 | + IP4, IP3); | ||
515 | + | ||
516 | + //Setup for flood test | ||
517 | + getEdgePointsNoArg = Lists.newLinkedList(); | ||
518 | + getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1))); | ||
519 | + getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1))); | ||
520 | + proxyArp.reply(ndpRequest, getLocation(6)); | ||
521 | + | ||
522 | + verifyFlood(ndpRequest); | ||
523 | + } | ||
524 | + | ||
525 | + /** | ||
526 | + * Test ARP request from external network to an internal host. | ||
527 | + */ | ||
391 | @Test | 528 | @Test |
392 | public void testReplyToRequestForUs() { | 529 | public void testReplyToRequestForUs() { |
393 | Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254"); | 530 | Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254"); |
... | @@ -422,6 +559,63 @@ public class ProxyArpManagerTest { | ... | @@ -422,6 +559,63 @@ public class ProxyArpManagerTest { |
422 | verifyPacketOut(arpReply, LOC1, packetService.packets.get(0)); | 559 | verifyPacketOut(arpReply, LOC1, packetService.packets.get(0)); |
423 | } | 560 | } |
424 | 561 | ||
562 | + /** | ||
563 | + * Test NDP request from external network to an internal host. | ||
564 | + */ | ||
565 | + @Test | ||
566 | + public void testReplyToRequestForUsIpv6() { | ||
567 | + Ip6Address theirIp = Ip6Address.valueOf("1000::ffff"); | ||
568 | + Ip6Address ourFirstIp = Ip6Address.valueOf("1000::1"); | ||
569 | + Ip6Address ourSecondIp = Ip6Address.valueOf("2000::1"); | ||
570 | + MacAddress firstMac = MacAddress.valueOf(1L); | ||
571 | + MacAddress secondMac = MacAddress.valueOf(2L); | ||
572 | + | ||
573 | + Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1, | ||
574 | + Collections.singleton(theirIp)); | ||
575 | + | ||
576 | + expect(hostService.getHost(HID2)).andReturn(requestor); | ||
577 | + expect(hostService.getHostsByIp(ourFirstIp)) | ||
578 | + .andReturn(Collections.singleton(requestor)); | ||
579 | + replay(hostService); | ||
580 | + replay(interfaceService); | ||
581 | + | ||
582 | + Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, | ||
583 | + MAC2, | ||
584 | + MacAddress.valueOf("33:33:ff:00:00:01"), | ||
585 | + theirIp, | ||
586 | + ourFirstIp); | ||
587 | + isEdgePointReturn = true; | ||
588 | + proxyArp.reply(ndpRequest, LOC1); | ||
589 | + assertEquals(1, packetService.packets.size()); | ||
590 | + | ||
591 | + Ethernet ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT, | ||
592 | + firstMac, | ||
593 | + MAC2, | ||
594 | + ourFirstIp, | ||
595 | + theirIp); | ||
596 | + verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0)); | ||
597 | + | ||
598 | + // Test a request for the second address on that port | ||
599 | + packetService.packets.clear(); | ||
600 | + ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, | ||
601 | + MAC2, | ||
602 | + MacAddress.valueOf("33:33:ff:00:00:01"), | ||
603 | + theirIp, | ||
604 | + ourSecondIp); | ||
605 | + proxyArp.reply(ndpRequest, LOC1); | ||
606 | + assertEquals(1, packetService.packets.size()); | ||
607 | + | ||
608 | + ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT, | ||
609 | + secondMac, | ||
610 | + MAC2, | ||
611 | + ourSecondIp, | ||
612 | + theirIp); | ||
613 | + verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0)); | ||
614 | + } | ||
615 | + | ||
616 | + /** | ||
617 | + * Request for a valid external IPv4 address but coming in the wrong port. | ||
618 | + */ | ||
425 | @Test | 619 | @Test |
426 | public void testReplyExternalPortBadRequest() { | 620 | public void testReplyExternalPortBadRequest() { |
427 | replay(hostService); // no further host service expectations | 621 | replay(hostService); // no further host service expectations |
... | @@ -442,6 +636,38 @@ public class ProxyArpManagerTest { | ... | @@ -442,6 +636,38 @@ public class ProxyArpManagerTest { |
442 | assertEquals(0, packetService.packets.size()); | 636 | assertEquals(0, packetService.packets.size()); |
443 | } | 637 | } |
444 | 638 | ||
639 | + /** | ||
640 | + * Request for a valid external IPv6 address but coming in the wrong port. | ||
641 | + */ | ||
642 | + @Test | ||
643 | + public void testReplyExternalPortBadRequestIpv6() { | ||
644 | + replay(hostService); // no further host service expectations | ||
645 | + replay(interfaceService); | ||
646 | + | ||
647 | + Ip6Address theirIp = Ip6Address.valueOf("1000::ffff"); | ||
648 | + | ||
649 | + Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, | ||
650 | + MAC1, | ||
651 | + MacAddress.valueOf("33:33:ff:00:00:01"), | ||
652 | + theirIp, | ||
653 | + Ip6Address.valueOf("3000::1")); | ||
654 | + proxyArp.reply(ndpRequest, LOC1); | ||
655 | + assertEquals(0, packetService.packets.size()); | ||
656 | + | ||
657 | + // Request for a valid internal IP address but coming in an external port | ||
658 | + packetService.packets.clear(); | ||
659 | + ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, | ||
660 | + MAC1, | ||
661 | + MacAddress.valueOf("33:33:ff:00:00:01"), | ||
662 | + theirIp, | ||
663 | + IP3); | ||
664 | + proxyArp.reply(ndpRequest, LOC1); | ||
665 | + assertEquals(0, packetService.packets.size()); | ||
666 | + } | ||
667 | + | ||
668 | + /** | ||
669 | + * Test ARP request from internal network to an external host. | ||
670 | + */ | ||
445 | @Test | 671 | @Test |
446 | public void testReplyToRequestFromUs() { | 672 | public void testReplyToRequestFromUs() { |
447 | Ip4Address ourIp = Ip4Address.valueOf("10.0.1.1"); | 673 | Ip4Address ourIp = Ip4Address.valueOf("10.0.1.1"); |
... | @@ -474,6 +700,48 @@ public class ProxyArpManagerTest { | ... | @@ -474,6 +700,48 @@ public class ProxyArpManagerTest { |
474 | } | 700 | } |
475 | 701 | ||
476 | /** | 702 | /** |
703 | + * Test NDP request from internal network to an external host. | ||
704 | + */ | ||
705 | + @Test | ||
706 | + public void testReplyToRequestFromUsIpv6() { | ||
707 | + Ip6Address ourIp = Ip6Address.valueOf("1000::1"); | ||
708 | + MacAddress ourMac = MacAddress.valueOf(1L); | ||
709 | + Ip6Address theirIp = Ip6Address.valueOf("1000::100"); | ||
710 | + | ||
711 | + expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet()); | ||
712 | + expect(interfaceService.getInterfacesByIp(ourIp)) | ||
713 | + .andReturn(Collections.singleton(new Interface(getLocation(1), | ||
714 | + Collections.singleton(new InterfaceIpAddress( | ||
715 | + ourIp, | ||
716 | + IpPrefix.valueOf("1000::1/64"))), | ||
717 | + ourMac, | ||
718 | + VLAN1))); | ||
719 | + expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null); | ||
720 | + replay(hostService); | ||
721 | + replay(interfaceService); | ||
722 | + | ||
723 | + // This is a request from something inside our network (like a BGP | ||
724 | + // daemon) to an external host. | ||
725 | + Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, | ||
726 | + ourMac, | ||
727 | + MacAddress.valueOf("33:33:ff:00:00:01"), | ||
728 | + ourIp, | ||
729 | + theirIp); | ||
730 | + | ||
731 | + //Ensure the packet is allowed through (it is not to an internal port) | ||
732 | + isEdgePointReturn = true; | ||
733 | + | ||
734 | + proxyArp.reply(ndpRequest, getLocation(5)); | ||
735 | + assertEquals(1, packetService.packets.size()); | ||
736 | + verifyPacketOut(ndpRequest, getLocation(1), packetService.packets.get(0)); | ||
737 | + | ||
738 | + // The same request from a random external port should fail | ||
739 | + packetService.packets.clear(); | ||
740 | + proxyArp.reply(ndpRequest, getLocation(2)); | ||
741 | + assertEquals(0, packetService.packets.size()); | ||
742 | + } | ||
743 | + | ||
744 | + /** | ||
477 | * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the | 745 | * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the |
478 | * destination host is known. | 746 | * destination host is known. |
479 | * Verifies the correct ARP request is sent out the correct port. | 747 | * Verifies the correct ARP request is sent out the correct port. |
... | @@ -502,6 +770,35 @@ public class ProxyArpManagerTest { | ... | @@ -502,6 +770,35 @@ public class ProxyArpManagerTest { |
502 | 770 | ||
503 | /** | 771 | /** |
504 | * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the | 772 | * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the |
773 | + * destination host is known. | ||
774 | + * Verifies the correct ARP request is sent out the correct port. | ||
775 | + */ | ||
776 | + @Test | ||
777 | + public void testForwardToHostIpv6() { | ||
778 | + Host host1 = new DefaultHost(PID, HID3, MAC3, VLAN1, LOC1, | ||
779 | + Collections.singleton(IP3)); | ||
780 | + Host host2 = new DefaultHost(PID, HID4, MAC4, VLAN1, LOC2, | ||
781 | + Collections.singleton(IP4)); | ||
782 | + | ||
783 | + expect(hostService.getHost(SOLICITED_HID3)).andReturn(host1); | ||
784 | + expect(hostService.getHost(HID4)).andReturn(host2); | ||
785 | + replay(hostService); | ||
786 | + replay(interfaceService); | ||
787 | + | ||
788 | + Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, | ||
789 | + MAC4, SOLICITED_MAC3, | ||
790 | + IP4, IP3); | ||
791 | + | ||
792 | + proxyArp.forward(ndpRequest, LOC2); | ||
793 | + | ||
794 | + assertEquals(1, packetService.packets.size()); | ||
795 | + OutboundPacket packet = packetService.packets.get(0); | ||
796 | + | ||
797 | + verifyPacketOut(ndpRequest, LOC1, packet); | ||
798 | + } | ||
799 | + | ||
800 | + /** | ||
801 | + * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the | ||
505 | * destination host is not known. | 802 | * destination host is not known. |
506 | * Verifies the correct ARP request is flooded out the correct edge ports. | 803 | * Verifies the correct ARP request is flooded out the correct edge ports. |
507 | */ | 804 | */ |
... | @@ -526,6 +823,33 @@ public class ProxyArpManagerTest { | ... | @@ -526,6 +823,33 @@ public class ProxyArpManagerTest { |
526 | } | 823 | } |
527 | 824 | ||
528 | /** | 825 | /** |
826 | + * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the | ||
827 | + * destination host is not known. | ||
828 | + * Verifies the correct NDP request is flooded out the correct edge ports. | ||
829 | + */ | ||
830 | + @Test | ||
831 | + public void testForwardFloodIpv6() { | ||
832 | + expect(hostService.getHost(SOLICITED_HID3)).andReturn(null); | ||
833 | + replay(hostService); | ||
834 | + replay(interfaceService); | ||
835 | + | ||
836 | + Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, | ||
837 | + MAC4, SOLICITED_MAC3, | ||
838 | + IP4, IP3); | ||
839 | + | ||
840 | + //populate the list of edges when so that when forward hits flood in the manager it contains the values | ||
841 | + //that should continue on | ||
842 | + getEdgePointsNoArg = Lists.newLinkedList(); | ||
843 | + getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("3"), PortNumber.portNumber(1))); | ||
844 | + getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1))); | ||
845 | + getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1))); | ||
846 | + | ||
847 | + proxyArp.forward(ndpRequest, getLocation(6)); | ||
848 | + | ||
849 | + verifyFlood(ndpRequest); | ||
850 | + } | ||
851 | + | ||
852 | + /** | ||
529 | * Verifies that the given packet was flooded out all available edge ports, | 853 | * Verifies that the given packet was flooded out all available edge ports, |
530 | * except for the input port. | 854 | * except for the input port. |
531 | * | 855 | * |
... | @@ -626,6 +950,61 @@ public class ProxyArpManagerTest { | ... | @@ -626,6 +950,61 @@ public class ProxyArpManagerTest { |
626 | } | 950 | } |
627 | 951 | ||
628 | /** | 952 | /** |
953 | + * Builds an NDP packet with the given parameters. | ||
954 | + * | ||
955 | + * @param type NeighborSolicitation or NeighborAdvertisement | ||
956 | + * @param srcMac source MAC address | ||
957 | + * @param dstMac destination MAC address, or null if this is a request | ||
958 | + * @param srcIp source IP address | ||
959 | + * @param dstIp destination IP address | ||
960 | + * @return the NDP packet | ||
961 | + */ | ||
962 | + private Ethernet buildNDP(byte type, MacAddress srcMac, MacAddress dstMac, | ||
963 | + Ip6Address srcIp, Ip6Address dstIp) { | ||
964 | + assertThat(type, anyOf( | ||
965 | + is(ICMP6.NEIGHBOR_SOLICITATION), | ||
966 | + is(ICMP6.NEIGHBOR_ADVERTISEMENT) | ||
967 | + )); | ||
968 | + assertNotNull(srcMac); | ||
969 | + assertNotNull(dstMac); | ||
970 | + assertNotNull(srcIp); | ||
971 | + assertNotNull(dstIp); | ||
972 | + | ||
973 | + IPacket ndp; | ||
974 | + if (type == ICMP6.NEIGHBOR_SOLICITATION) { | ||
975 | + ndp = new NeighborSolicitation().setTargetAddress(dstIp.toOctets()); | ||
976 | + } else { | ||
977 | + ndp = new NeighborAdvertisement() | ||
978 | + .setSolicitedFlag((byte) 1) | ||
979 | + .setOverrideFlag((byte) 1) | ||
980 | + .setTargetAddress(srcIp.toOctets()) | ||
981 | + .addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, | ||
982 | + srcMac.toBytes()); | ||
983 | + } | ||
984 | + | ||
985 | + ICMP6 icmp6 = new ICMP6(); | ||
986 | + icmp6.setIcmpType(type); | ||
987 | + icmp6.setIcmpCode((byte) 0); | ||
988 | + icmp6.setPayload(ndp); | ||
989 | + | ||
990 | + IPv6 ipv6 = new IPv6(); | ||
991 | + ipv6.setDestinationAddress(dstIp.toOctets()); | ||
992 | + ipv6.setSourceAddress(srcIp.toOctets()); | ||
993 | + ipv6.setNextHeader(IPv6.PROTOCOL_ICMP6); | ||
994 | + ipv6.setHopLimit((byte) 255); | ||
995 | + ipv6.setPayload(icmp6); | ||
996 | + | ||
997 | + Ethernet eth = new Ethernet(); | ||
998 | + eth.setDestinationMACAddress(dstMac); | ||
999 | + eth.setSourceMACAddress(srcMac); | ||
1000 | + eth.setEtherType(Ethernet.TYPE_IPV6); | ||
1001 | + eth.setVlanID(VLAN1.toShort()); | ||
1002 | + eth.setPayload(ipv6); | ||
1003 | + | ||
1004 | + return eth; | ||
1005 | + } | ||
1006 | + | ||
1007 | + /** | ||
629 | * Test PacketService implementation that simply stores OutboundPackets | 1008 | * Test PacketService implementation that simply stores OutboundPackets |
630 | * passed to {@link #emit(OutboundPacket)} for later verification. | 1009 | * passed to {@link #emit(OutboundPacket)} for later verification. |
631 | */ | 1010 | */ | ... | ... |
-
Please register or login to post a comment