5 from socket import AF_INET, AF_INET6, inet_pton
7 from framework import tag_fixme_vpp_workers
8 from framework import VppTestCase, VppTestRunner
9 from vpp_neighbor import VppNeighbor, find_nbr
10 from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
11 VppIpTable, DpoProto, FibPathType, VppIpInterfaceAddress
12 from vpp_papi import VppEnum
13 from vpp_ip import VppIpPuntRedirect
16 from scapy.packet import Raw
17 from scapy.layers.l2 import Ether, ARP, Dot1Q
18 from scapy.layers.inet import IP, UDP, TCP
19 from scapy.layers.inet6 import IPv6
20 from scapy.contrib.mpls import MPLS
21 from scapy.layers.inet6 import IPv6
26 # not exported by scapy, so redefined here
27 arp_opts = {"who-has": 1, "is-at": 2}
30 class ARPTestCase(VppTestCase):
35 super(ARPTestCase, cls).setUpClass()
38 def tearDownClass(cls):
39 super(ARPTestCase, cls).tearDownClass()
42 super(ARPTestCase, self).setUp()
44 # create 3 pg interfaces
45 self.create_pg_interfaces(range(4))
47 # pg0 configured with ip4 and 6 addresses used for input
48 # pg1 configured with ip4 and 6 addresses used for output
49 # pg2 is unnumbered to pg0
50 for i in self.pg_interfaces:
55 self.pg0.resolve_arp()
60 # pg3 in a different VRF
61 self.tbl = VppIpTable(self, 1)
62 self.tbl.add_vpp_config()
64 self.pg3.set_table_ip4(1)
68 self.pg0.unconfig_ip4()
69 self.pg0.unconfig_ip6()
71 self.pg1.unconfig_ip4()
72 self.pg1.unconfig_ip6()
74 self.pg3.unconfig_ip4()
75 self.pg3.set_table_ip4(0)
77 for i in self.pg_interfaces:
80 super(ARPTestCase, self).tearDown()
82 def verify_arp_req(self, rx, smac, sip, dip):
84 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
85 self.assertEqual(ether.src, smac)
86 self.assertEqual(ether.type, 0x0806)
89 self.assertEqual(arp.hwtype, 1)
90 self.assertEqual(arp.ptype, 0x800)
91 self.assertEqual(arp.hwlen, 6)
92 self.assertEqual(arp.plen, 4)
93 self.assertEqual(arp.op, arp_opts["who-has"])
94 self.assertEqual(arp.hwsrc, smac)
95 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
96 self.assertEqual(arp.psrc, sip)
97 self.assertEqual(arp.pdst, dip)
99 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
101 self.assertEqual(ether.dst, dmac)
102 self.assertEqual(ether.src, smac)
103 self.assertEqual(ether.type, 0x0806)
106 self.assertEqual(arp.hwtype, 1)
107 self.assertEqual(arp.ptype, 0x800)
108 self.assertEqual(arp.hwlen, 6)
109 self.assertEqual(arp.plen, 4)
110 self.assertEqual(arp.op, arp_opts["is-at"])
111 self.assertEqual(arp.hwsrc, smac)
112 self.assertEqual(arp.hwdst, dmac)
113 self.assertEqual(arp.psrc, sip)
114 self.assertEqual(arp.pdst, dip)
116 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
118 self.assertEqual(ether.dst, dmac)
119 self.assertEqual(ether.src, smac)
122 self.assertEqual(arp.hwtype, 1)
123 self.assertEqual(arp.ptype, 0x800)
124 self.assertEqual(arp.hwlen, 6)
125 self.assertEqual(arp.plen, 4)
126 self.assertEqual(arp.op, arp_opts["is-at"])
127 self.assertNotEqual(arp.hwsrc, smac)
128 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
129 "00:00:5E:00:01" in arp.hwsrc)
130 self.assertEqual(arp.hwdst, dmac)
131 self.assertEqual(arp.psrc, sip)
132 self.assertEqual(arp.pdst, dip)
134 def verify_ip(self, rx, smac, dmac, sip, dip):
136 self.assertEqual(ether.dst, dmac)
137 self.assertEqual(ether.src, smac)
138 self.assertEqual(ether.type, 0x0800)
141 self.assertEqual(ip.src, sip)
142 self.assertEqual(ip.dst, dip)
144 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
146 self.assertEqual(ether.dst, dmac)
147 self.assertEqual(ether.src, smac)
148 self.assertEqual(ether.type, 0x8847)
151 self.assertTrue(mpls.label, label)
154 self.assertEqual(ip.src, sip)
155 self.assertEqual(ip.dst, dip)
161 # Generate some hosts on the LAN
163 self.pg1.generate_remote_hosts(11)
167 # - all neighbour events
168 # - all neighbor events on pg1
169 # - neighbor events for host[1] on pg1
171 self.vapi.want_ip_neighbor_events(enable=1,
173 self.vapi.want_ip_neighbor_events(enable=1,
175 sw_if_index=self.pg1.sw_if_index)
176 self.vapi.want_ip_neighbor_events(enable=1,
178 sw_if_index=self.pg1.sw_if_index,
179 ip=self.pg1.remote_hosts[1].ip4)
181 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
184 # Send IP traffic to one of these unresolved hosts.
185 # expect the generation of an ARP request
187 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
188 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
189 UDP(sport=1234, dport=1234) /
192 self.pg0.add_stream(p)
193 self.pg_enable_capture(self.pg_interfaces)
196 rx = self.pg1.get_capture(1)
198 self.verify_arp_req(rx[0],
201 self.pg1._remote_hosts[1].ip4)
204 # And a dynamic ARP entry for host 1
206 dyn_arp = VppNeighbor(self,
207 self.pg1.sw_if_index,
208 self.pg1.remote_hosts[1].mac,
209 self.pg1.remote_hosts[1].ip4)
210 dyn_arp.add_vpp_config()
211 self.assertTrue(dyn_arp.query_vpp_config())
213 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
215 # this matches all of the listnerers
216 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
219 self.assertEqual(str(e.neighbor.ip_address),
220 self.pg1.remote_hosts[1].ip4)
223 # now we expect IP traffic forwarded
225 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
226 IP(src=self.pg0.remote_ip4,
227 dst=self.pg1._remote_hosts[1].ip4) /
228 UDP(sport=1234, dport=1234) /
231 self.pg0.add_stream(dyn_p)
232 self.pg_enable_capture(self.pg_interfaces)
235 rx = self.pg1.get_capture(1)
237 self.verify_ip(rx[0],
239 self.pg1.remote_hosts[1].mac,
241 self.pg1._remote_hosts[1].ip4)
244 # And a Static ARP entry for host 2
246 static_arp = VppNeighbor(self,
247 self.pg1.sw_if_index,
248 self.pg1.remote_hosts[2].mac,
249 self.pg1.remote_hosts[2].ip4,
251 static_arp.add_vpp_config()
252 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
255 self.assertEqual(str(e.neighbor.ip_address),
256 self.pg1.remote_hosts[2].ip4)
258 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
259 IP(src=self.pg0.remote_ip4,
260 dst=self.pg1._remote_hosts[2].ip4) /
261 UDP(sport=1234, dport=1234) /
264 self.pg0.add_stream(static_p)
265 self.pg_enable_capture(self.pg_interfaces)
268 rx = self.pg1.get_capture(1)
270 self.verify_ip(rx[0],
272 self.pg1.remote_hosts[2].mac,
274 self.pg1._remote_hosts[2].ip4)
277 # remove all the listeners
279 self.vapi.want_ip_neighbor_events(enable=0,
281 self.vapi.want_ip_neighbor_events(enable=0,
283 sw_if_index=self.pg1.sw_if_index)
284 self.vapi.want_ip_neighbor_events(enable=0,
286 sw_if_index=self.pg1.sw_if_index,
287 ip=self.pg1.remote_hosts[1].ip4)
290 # flap the link. dynamic ARPs get flush, statics don't
292 self.pg1.admin_down()
295 self.pg0.add_stream(static_p)
296 self.pg_enable_capture(self.pg_interfaces)
298 rx = self.pg1.get_capture(1)
300 self.verify_ip(rx[0],
302 self.pg1.remote_hosts[2].mac,
304 self.pg1._remote_hosts[2].ip4)
306 self.pg0.add_stream(dyn_p)
307 self.pg_enable_capture(self.pg_interfaces)
310 rx = self.pg1.get_capture(1)
311 self.verify_arp_req(rx[0],
314 self.pg1._remote_hosts[1].ip4)
316 self.assertFalse(dyn_arp.query_vpp_config())
317 self.assertTrue(static_arp.query_vpp_config())
319 # Send an ARP request from one of the so-far unlearned remote hosts
321 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
322 src=self.pg1._remote_hosts[3].mac) /
324 hwsrc=self.pg1._remote_hosts[3].mac,
325 pdst=self.pg1.local_ip4,
326 psrc=self.pg1._remote_hosts[3].ip4))
328 self.pg1.add_stream(p)
329 self.pg_enable_capture(self.pg_interfaces)
332 rx = self.pg1.get_capture(1)
333 self.verify_arp_resp(rx[0],
335 self.pg1._remote_hosts[3].mac,
337 self.pg1._remote_hosts[3].ip4)
340 # VPP should have learned the mapping for the remote host
342 self.assertTrue(find_nbr(self,
343 self.pg1.sw_if_index,
344 self.pg1._remote_hosts[3].ip4))
346 # Fire in an ARP request before the interface becomes IP enabled
348 self.pg2.generate_remote_hosts(4)
350 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
352 hwsrc=self.pg2.remote_mac,
353 pdst=self.pg1.local_ip4,
354 psrc=self.pg2.remote_hosts[3].ip4))
355 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
358 hwsrc=self.pg2.remote_mac,
359 pdst=self.pg1.local_ip4,
360 psrc=self.pg2.remote_hosts[3].ip4))
361 self.send_and_assert_no_replies(self.pg2, p,
362 "interface not IP enabled")
365 # Make pg2 un-numbered to pg1
367 self.pg2.set_unnumbered(self.pg1.sw_if_index)
370 # test the unnumbered dump both by all interfaces and just the enabled
373 unnum = self.vapi.ip_unnumbered_dump()
374 self.assertTrue(len(unnum))
375 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
376 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
377 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
378 self.assertTrue(len(unnum))
379 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
380 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
383 # We should respond to ARP requests for the unnumbered to address
384 # once an attached route to the source is known
386 self.send_and_assert_no_replies(
388 "ARP req for unnumbered address - no source")
390 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
391 [VppRoutePath("0.0.0.0",
392 self.pg2.sw_if_index)])
393 attached_host.add_vpp_config()
395 self.pg2.add_stream(p)
396 self.pg_enable_capture(self.pg_interfaces)
399 rx = self.pg2.get_capture(1)
400 self.verify_arp_resp(rx[0],
404 self.pg2.remote_hosts[3].ip4)
406 self.pg2.add_stream(pt)
407 self.pg_enable_capture(self.pg_interfaces)
410 rx = self.pg2.get_capture(1)
411 self.verify_arp_resp(rx[0],
415 self.pg2.remote_hosts[3].ip4)
418 # A neighbor entry that has no associated FIB-entry
420 arp_no_fib = VppNeighbor(self,
421 self.pg1.sw_if_index,
422 self.pg1.remote_hosts[4].mac,
423 self.pg1.remote_hosts[4].ip4,
425 arp_no_fib.add_vpp_config()
428 # check we have the neighbor, but no route
430 self.assertTrue(find_nbr(self,
431 self.pg1.sw_if_index,
432 self.pg1._remote_hosts[4].ip4))
433 self.assertFalse(find_route(self,
434 self.pg1._remote_hosts[4].ip4,
437 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
438 # from within pg1's subnet
440 arp_unnum = VppNeighbor(self,
441 self.pg2.sw_if_index,
442 self.pg1.remote_hosts[5].mac,
443 self.pg1.remote_hosts[5].ip4)
444 arp_unnum.add_vpp_config()
446 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
447 IP(src=self.pg0.remote_ip4,
448 dst=self.pg1._remote_hosts[5].ip4) /
449 UDP(sport=1234, dport=1234) /
452 self.pg0.add_stream(p)
453 self.pg_enable_capture(self.pg_interfaces)
456 rx = self.pg2.get_capture(1)
458 self.verify_ip(rx[0],
460 self.pg1.remote_hosts[5].mac,
462 self.pg1._remote_hosts[5].ip4)
465 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
466 # with the unnumbered interface's address as the source
468 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
470 hwsrc=self.pg2.remote_mac,
471 pdst=self.pg1.local_ip4,
472 psrc=self.pg1.remote_hosts[6].ip4))
474 self.pg2.add_stream(p)
475 self.pg_enable_capture(self.pg_interfaces)
478 rx = self.pg2.get_capture(1)
479 self.verify_arp_resp(rx[0],
483 self.pg1.remote_hosts[6].ip4)
486 # An attached host route out of pg2 for an undiscovered hosts generates
487 # an ARP request with the unnumbered address as the source
489 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
490 [VppRoutePath("0.0.0.0",
491 self.pg2.sw_if_index)])
492 att_unnum.add_vpp_config()
494 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
495 IP(src=self.pg0.remote_ip4,
496 dst=self.pg1._remote_hosts[7].ip4) /
497 UDP(sport=1234, dport=1234) /
500 self.pg0.add_stream(p)
501 self.pg_enable_capture(self.pg_interfaces)
504 rx = self.pg2.get_capture(1)
506 self.verify_arp_req(rx[0],
509 self.pg1._remote_hosts[7].ip4)
511 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
513 hwsrc=self.pg2.remote_mac,
514 pdst=self.pg1.local_ip4,
515 psrc=self.pg1.remote_hosts[7].ip4))
517 self.pg2.add_stream(p)
518 self.pg_enable_capture(self.pg_interfaces)
521 rx = self.pg2.get_capture(1)
522 self.verify_arp_resp(rx[0],
526 self.pg1.remote_hosts[7].ip4)
529 # An attached host route as yet unresolved out of pg2 for an
530 # undiscovered host, an ARP requests begets a response.
532 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
533 [VppRoutePath("0.0.0.0",
534 self.pg2.sw_if_index)])
535 att_unnum1.add_vpp_config()
537 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
539 hwsrc=self.pg2.remote_mac,
540 pdst=self.pg1.local_ip4,
541 psrc=self.pg1.remote_hosts[8].ip4))
543 self.pg2.add_stream(p)
544 self.pg_enable_capture(self.pg_interfaces)
547 rx = self.pg2.get_capture(1)
548 self.verify_arp_resp(rx[0],
552 self.pg1.remote_hosts[8].ip4)
555 # Send an ARP request from one of the so-far unlearned remote hosts
558 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
559 src=self.pg1._remote_hosts[9].mac) /
562 hwsrc=self.pg1._remote_hosts[9].mac,
563 pdst=self.pg1.local_ip4,
564 psrc=self.pg1._remote_hosts[9].ip4))
566 self.pg1.add_stream(p)
567 self.pg_enable_capture(self.pg_interfaces)
570 rx = self.pg1.get_capture(1)
571 self.verify_arp_resp(rx[0],
573 self.pg1._remote_hosts[9].mac,
575 self.pg1._remote_hosts[9].ip4)
578 # Add a hierarchy of routes for a host in the sub-net.
579 # Should still get an ARP resp since the cover is attached
581 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
583 hwsrc=self.pg1.remote_mac,
584 pdst=self.pg1.local_ip4,
585 psrc=self.pg1.remote_hosts[10].ip4))
587 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
588 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
589 self.pg1.sw_if_index)])
592 self.pg1.add_stream(p)
593 self.pg_enable_capture(self.pg_interfaces)
595 rx = self.pg1.get_capture(1)
596 self.verify_arp_resp(rx[0],
600 self.pg1.remote_hosts[10].ip4)
602 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
603 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
604 self.pg1.sw_if_index)])
607 self.pg1.add_stream(p)
608 self.pg_enable_capture(self.pg_interfaces)
610 rx = self.pg1.get_capture(1)
611 self.verify_arp_resp(rx[0],
615 self.pg1.remote_hosts[10].ip4)
618 # add an ARP entry that's not on the sub-net and so whose
619 # adj-fib fails the refinement check. then send an ARP request
622 a1 = VppNeighbor(self,
623 self.pg0.sw_if_index,
628 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
630 hwsrc=self.pg0.remote_mac,
631 psrc="100.100.100.50",
632 pdst=self.pg0.remote_ip4))
633 self.send_and_assert_no_replies(self.pg0, p,
634 "ARP req for from failed adj-fib")
638 # 1 - don't respond to ARP request for address not within the
639 # interface's sub-net
640 # 1b - nor within the unnumbered subnet
641 # 1c - nor within the subnet of a different interface
643 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
645 hwsrc=self.pg0.remote_mac,
647 psrc=self.pg0.remote_ip4))
648 self.send_and_assert_no_replies(self.pg0, p,
649 "ARP req for non-local destination")
650 self.assertFalse(find_nbr(self,
651 self.pg0.sw_if_index,
654 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
656 hwsrc=self.pg2.remote_mac,
658 psrc=self.pg1.remote_hosts[7].ip4))
659 self.send_and_assert_no_replies(
661 "ARP req for non-local destination - unnum")
663 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
665 hwsrc=self.pg0.remote_mac,
666 pdst=self.pg1.local_ip4,
667 psrc=self.pg1.remote_ip4))
668 self.send_and_assert_no_replies(self.pg0, p,
669 "ARP req diff sub-net")
670 self.assertFalse(find_nbr(self,
671 self.pg0.sw_if_index,
672 self.pg1.remote_ip4))
675 # 2 - don't respond to ARP request from an address not within the
676 # interface's sub-net
677 # 2b - to a proxied address
678 # 2c - not within a different interface's sub-net
679 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
681 hwsrc=self.pg0.remote_mac,
683 pdst=self.pg0.local_ip4))
684 self.send_and_assert_no_replies(self.pg0, p,
685 "ARP req for non-local source")
686 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
688 hwsrc=self.pg2.remote_mac,
690 pdst=self.pg0.local_ip4))
691 self.send_and_assert_no_replies(
693 "ARP req for non-local source - unnum")
694 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
696 hwsrc=self.pg0.remote_mac,
697 psrc=self.pg1.remote_ip4,
698 pdst=self.pg0.local_ip4))
699 self.send_and_assert_no_replies(self.pg0, p,
700 "ARP req for non-local source 2c")
703 # 3 - don't respond to ARP request from an address that belongs to
706 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
708 hwsrc=self.pg0.remote_mac,
709 psrc=self.pg0.local_ip4,
710 pdst=self.pg0.local_ip4))
711 self.send_and_assert_no_replies(self.pg0, p,
712 "ARP req for non-local source")
715 # 4 - don't respond to ARP requests that has mac source different
716 # from ARP request HW source
718 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
720 hwsrc="00:00:00:DE:AD:BE",
721 psrc=self.pg0.remote_ip4,
722 pdst=self.pg0.local_ip4))
723 self.send_and_assert_no_replies(self.pg0, p,
724 "ARP req for non-local source")
727 # 5 - don't respond to ARP requests for address within the
728 # interface's sub-net but not the interface's address
730 self.pg0.generate_remote_hosts(2)
731 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
733 hwsrc=self.pg0.remote_mac,
734 psrc=self.pg0.remote_hosts[0].ip4,
735 pdst=self.pg0.remote_hosts[1].ip4))
736 self.send_and_assert_no_replies(self.pg0, p,
737 "ARP req for non-local destination")
742 static_arp.remove_vpp_config()
743 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
745 # need this to flush the adj-fibs
746 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
747 self.pg2.admin_down()
748 self.pg1.admin_down()
750 def test_proxy_mirror_arp(self):
751 """ Interface Mirror Proxy ARP """
754 # When VPP has an interface whose address is also applied to a TAP
755 # interface on the host, then VPP's TAP interface will be unnumbered
756 # to the 'real' interface and do proxy ARP from the host.
757 # the curious aspect of this setup is that ARP requests from the host
758 # will come from the VPP's own address.
760 self.pg0.generate_remote_hosts(2)
762 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
763 dst="ff:ff:ff:ff:ff:ff") /
765 hwsrc=self.pg2.remote_mac,
766 pdst=self.pg0.remote_hosts[1].ip4,
767 psrc=self.pg0.local_ip4))
770 # Configure Proxy ARP for the subnet on PG0addresses on pg0
772 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
773 'low': self.pg0._local_ip4_subnet,
774 'hi': self.pg0._local_ip4_bcast},
777 # Make pg2 un-numbered to pg0
779 self.pg2.set_unnumbered(self.pg0.sw_if_index)
782 # Enable pg2 for proxy ARP
784 self.pg2.set_proxy_arp()
787 # Send the ARP request with an originating address that
788 # is VPP's own address
790 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
791 self.verify_arp_resp(rx[0],
794 self.pg0.remote_hosts[1].ip4,
798 # validate we have not learned an ARP entry as a result of this
800 self.assertFalse(find_nbr(self,
801 self.pg2.sw_if_index,
805 # setup a punt redirect so packets from the uplink go to the tap
807 redirect = VppIpPuntRedirect(self, self.pg0.sw_if_index,
808 self.pg2.sw_if_index, self.pg0.local_ip4)
809 redirect.add_vpp_config()
811 p_tcp = (Ether(src=self.pg0.remote_mac,
812 dst=self.pg0.local_mac,) /
813 IP(src=self.pg0.remote_ip4,
814 dst=self.pg0.local_ip4) /
815 TCP(sport=80, dport=80) /
817 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
819 # there's no ARP entry so this is an ARP req
820 self.assertTrue(rx[0].haslayer(ARP))
822 # and ARP entry for VPP's pg0 address on the host interface
823 n1 = VppNeighbor(self,
824 self.pg2.sw_if_index,
827 is_no_fib_entry=True).add_vpp_config()
828 # now the packets shold forward
829 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
830 self.assertFalse(rx[0].haslayer(ARP))
831 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
834 # flush the neighbor cache on the uplink
836 af = VppEnum.vl_api_address_family_t
837 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
839 # ensure we can still resolve the ARPs on the uplink
840 self.pg0.resolve_arp()
842 self.assertTrue(find_nbr(self,
843 self.pg0.sw_if_index,
844 self.pg0.remote_ip4))
849 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
850 'low': self.pg0._local_ip4_subnet,
851 'hi': self.pg0._local_ip4_bcast},
853 redirect.remove_vpp_config()
855 def test_proxy_arp(self):
858 self.pg1.generate_remote_hosts(2)
861 # Proxy ARP request packets for each interface
863 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
864 dst="ff:ff:ff:ff:ff:ff") /
866 hwsrc=self.pg0.remote_mac,
868 psrc=self.pg0.remote_ip4))
869 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
870 dst="ff:ff:ff:ff:ff:ff") /
873 hwsrc=self.pg0.remote_mac,
875 psrc=self.pg0.remote_ip4))
876 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
877 dst="ff:ff:ff:ff:ff:ff") /
879 hwsrc=self.pg1.remote_mac,
881 psrc=self.pg1.remote_ip4))
882 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
883 dst="ff:ff:ff:ff:ff:ff") /
885 hwsrc=self.pg2.remote_mac,
887 psrc=self.pg1.remote_hosts[1].ip4))
888 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
889 dst="ff:ff:ff:ff:ff:ff") /
891 hwsrc=self.pg3.remote_mac,
893 psrc=self.pg3.remote_ip4))
896 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
898 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
900 'hi': "10.10.10.124"},
904 # No responses are sent when the interfaces are not enabled for proxy
907 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
908 "ARP req from unconfigured interface")
909 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
910 "ARP req from unconfigured interface")
913 # Make pg2 un-numbered to pg1
916 self.pg2.set_unnumbered(self.pg1.sw_if_index)
918 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
919 "ARP req from unnumbered interface")
922 # Enable each interface to reply to proxy ARPs
924 for i in self.pg_interfaces:
928 # Now each of the interfaces should reply to a request to a proxied
931 self.pg0.add_stream(arp_req_pg0)
932 self.pg_enable_capture(self.pg_interfaces)
935 rx = self.pg0.get_capture(1)
936 self.verify_arp_resp(rx[0],
942 self.pg0.add_stream(arp_req_pg0_tagged)
943 self.pg_enable_capture(self.pg_interfaces)
946 rx = self.pg0.get_capture(1)
947 self.verify_arp_resp(rx[0],
953 self.pg1.add_stream(arp_req_pg1)
954 self.pg_enable_capture(self.pg_interfaces)
957 rx = self.pg1.get_capture(1)
958 self.verify_arp_resp(rx[0],
964 self.pg2.add_stream(arp_req_pg2)
965 self.pg_enable_capture(self.pg_interfaces)
968 rx = self.pg2.get_capture(1)
969 self.verify_arp_resp(rx[0],
973 self.pg1.remote_hosts[1].ip4)
976 # A request for an address out of the configured range
978 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
979 dst="ff:ff:ff:ff:ff:ff") /
981 hwsrc=self.pg1.remote_mac,
983 psrc=self.pg1.remote_ip4))
984 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
985 "ARP req out of range HI")
986 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
987 dst="ff:ff:ff:ff:ff:ff") /
989 hwsrc=self.pg1.remote_mac,
991 psrc=self.pg1.remote_ip4))
992 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
993 "ARP req out of range Low")
996 # Request for an address in the proxy range but from an interface
999 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
1000 "ARP req from different VRF")
1003 # Disable Each interface for proxy ARP
1004 # - expect none to respond
1006 for i in self.pg_interfaces:
1009 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
1010 "ARP req from disable")
1011 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
1012 "ARP req from disable")
1013 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
1014 "ARP req from disable")
1017 # clean up on interface 2
1019 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
1021 def test_mpls(self):
1025 # Interface 2 does not yet have ip4 config
1027 self.pg2.config_ip4()
1028 self.pg2.generate_remote_hosts(2)
1031 # Add a route with out going label via an ARP unresolved next-hop
1033 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1034 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
1035 self.pg2.sw_if_index,
1037 ip_10_0_0_1.add_vpp_config()
1040 # packets should generate an ARP request
1042 p = (Ether(src=self.pg0.remote_mac,
1043 dst=self.pg0.local_mac) /
1044 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
1045 UDP(sport=1234, dport=1234) /
1048 self.pg0.add_stream(p)
1049 self.pg_enable_capture(self.pg_interfaces)
1052 rx = self.pg2.get_capture(1)
1053 self.verify_arp_req(rx[0],
1056 self.pg2._remote_hosts[1].ip4)
1059 # now resolve the neighbours
1061 self.pg2.configure_ipv4_neighbors()
1064 # Now packet should be properly MPLS encapped.
1065 # This verifies that MPLS link-type adjacencies are completed
1066 # when the ARP entry resolves
1068 self.pg0.add_stream(p)
1069 self.pg_enable_capture(self.pg_interfaces)
1072 rx = self.pg2.get_capture(1)
1073 self.verify_ip_o_mpls(rx[0],
1075 self.pg2.remote_hosts[1].mac,
1077 self.pg0.remote_ip4,
1079 self.pg2.unconfig_ip4()
1081 def test_arp_vrrp(self):
1082 """ ARP reply with VRRP virtual src hw addr """
1085 # IP packet destined for pg1 remote host arrives on pg0 resulting
1086 # in an ARP request for the address of the remote host on pg1
1088 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1089 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1090 UDP(sport=1234, dport=1234) /
1093 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
1095 self.verify_arp_req(rx1[0],
1098 self.pg1.remote_ip4)
1101 # ARP reply for address of pg1 remote host arrives on pg1 with
1102 # the hw src addr set to a value in the VRRP IPv4 range of
1105 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1106 ARP(op="is-at", hwdst=self.pg1.local_mac,
1107 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1108 psrc=self.pg1.remote_ip4))
1110 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1113 # IP packet destined for pg1 remote host arrives on pg0 again.
1114 # VPP should have an ARP entry for that address now and the packet
1115 # should be sent out pg1.
1117 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
1119 self.verify_ip(rx1[0],
1121 "00:00:5e:00:01:09",
1122 self.pg0.remote_ip4,
1123 self.pg1.remote_ip4)
1125 self.pg1.admin_down()
1128 def test_arp_duplicates(self):
1129 """ ARP Duplicates"""
1132 # Generate some hosts on the LAN
1134 self.pg1.generate_remote_hosts(3)
1137 # Add host 1 on pg1 and pg2
1139 arp_pg1 = VppNeighbor(self,
1140 self.pg1.sw_if_index,
1141 self.pg1.remote_hosts[1].mac,
1142 self.pg1.remote_hosts[1].ip4)
1143 arp_pg1.add_vpp_config()
1144 arp_pg2 = VppNeighbor(self,
1145 self.pg2.sw_if_index,
1146 self.pg2.remote_mac,
1147 self.pg1.remote_hosts[1].ip4)
1148 arp_pg2.add_vpp_config()
1151 # IP packet destined for pg1 remote host arrives on pg1 again.
1153 p = (Ether(dst=self.pg0.local_mac,
1154 src=self.pg0.remote_mac) /
1155 IP(src=self.pg0.remote_ip4,
1156 dst=self.pg1.remote_hosts[1].ip4) /
1157 UDP(sport=1234, dport=1234) /
1160 self.pg0.add_stream(p)
1161 self.pg_enable_capture(self.pg_interfaces)
1164 rx1 = self.pg1.get_capture(1)
1166 self.verify_ip(rx1[0],
1168 self.pg1.remote_hosts[1].mac,
1169 self.pg0.remote_ip4,
1170 self.pg1.remote_hosts[1].ip4)
1173 # remove the duplicate on pg1
1174 # packet stream should generate ARPs out of pg1
1176 arp_pg1.remove_vpp_config()
1178 self.pg0.add_stream(p)
1179 self.pg_enable_capture(self.pg_interfaces)
1182 rx1 = self.pg1.get_capture(1)
1184 self.verify_arp_req(rx1[0],
1187 self.pg1.remote_hosts[1].ip4)
1192 arp_pg1.add_vpp_config()
1194 self.pg0.add_stream(p)
1195 self.pg_enable_capture(self.pg_interfaces)
1198 rx1 = self.pg1.get_capture(1)
1200 self.verify_ip(rx1[0],
1202 self.pg1.remote_hosts[1].mac,
1203 self.pg0.remote_ip4,
1204 self.pg1.remote_hosts[1].ip4)
1206 def test_arp_static(self):
1208 self.pg2.generate_remote_hosts(3)
1211 # Add a static ARP entry
1213 static_arp = VppNeighbor(self,
1214 self.pg2.sw_if_index,
1215 self.pg2.remote_hosts[1].mac,
1216 self.pg2.remote_hosts[1].ip4,
1218 static_arp.add_vpp_config()
1221 # Add the connected prefix to the interface
1223 self.pg2.config_ip4()
1226 # We should now find the adj-fib
1228 self.assertTrue(find_nbr(self,
1229 self.pg2.sw_if_index,
1230 self.pg2.remote_hosts[1].ip4,
1232 self.assertTrue(find_route(self,
1233 self.pg2.remote_hosts[1].ip4,
1237 # remove the connected
1239 self.pg2.unconfig_ip4()
1242 # put the interface into table 1
1244 self.pg2.set_table_ip4(1)
1247 # configure the same connected and expect to find the
1248 # adj fib in the new table
1250 self.pg2.config_ip4()
1251 self.assertTrue(find_route(self,
1252 self.pg2.remote_hosts[1].ip4,
1259 self.pg2.unconfig_ip4()
1260 static_arp.remove_vpp_config()
1261 self.pg2.set_table_ip4(0)
1263 def test_arp_static_replace_dynamic_same_mac(self):
1264 """ ARP Static can replace Dynamic (same mac) """
1265 self.pg2.generate_remote_hosts(1)
1267 dyn_arp = VppNeighbor(self,
1268 self.pg2.sw_if_index,
1269 self.pg2.remote_hosts[0].mac,
1270 self.pg2.remote_hosts[0].ip4)
1271 static_arp = VppNeighbor(self,
1272 self.pg2.sw_if_index,
1273 self.pg2.remote_hosts[0].mac,
1274 self.pg2.remote_hosts[0].ip4,
1278 # Add a dynamic ARP entry
1280 dyn_arp.add_vpp_config()
1283 # We should find the dynamic nbr
1285 self.assertFalse(find_nbr(self,
1286 self.pg2.sw_if_index,
1287 self.pg2.remote_hosts[0].ip4,
1289 self.assertTrue(find_nbr(self,
1290 self.pg2.sw_if_index,
1291 self.pg2.remote_hosts[0].ip4,
1293 mac=self.pg2.remote_hosts[0].mac))
1296 # Add a static ARP entry with the same mac
1298 static_arp.add_vpp_config()
1301 # We should now find the static nbr with the same mac
1303 self.assertFalse(find_nbr(self,
1304 self.pg2.sw_if_index,
1305 self.pg2.remote_hosts[0].ip4,
1307 self.assertTrue(find_nbr(self,
1308 self.pg2.sw_if_index,
1309 self.pg2.remote_hosts[0].ip4,
1311 mac=self.pg2.remote_hosts[0].mac))
1316 static_arp.remove_vpp_config()
1318 def test_arp_static_replace_dynamic_diff_mac(self):
1319 """ ARP Static can replace Dynamic (diff mac) """
1320 self.pg2.generate_remote_hosts(2)
1322 dyn_arp = VppNeighbor(self,
1323 self.pg2.sw_if_index,
1324 self.pg2.remote_hosts[0].mac,
1325 self.pg2.remote_hosts[0].ip4)
1326 static_arp = VppNeighbor(self,
1327 self.pg2.sw_if_index,
1328 self.pg2.remote_hosts[1].mac,
1329 self.pg2.remote_hosts[0].ip4,
1333 # Add a dynamic ARP entry
1335 dyn_arp.add_vpp_config()
1338 # We should find the dynamic nbr
1340 self.assertFalse(find_nbr(self,
1341 self.pg2.sw_if_index,
1342 self.pg2.remote_hosts[0].ip4,
1344 self.assertTrue(find_nbr(self,
1345 self.pg2.sw_if_index,
1346 self.pg2.remote_hosts[0].ip4,
1348 mac=self.pg2.remote_hosts[0].mac))
1351 # Add a static ARP entry with a changed mac
1353 static_arp.add_vpp_config()
1356 # We should now find the static nbr with a changed mac
1358 self.assertFalse(find_nbr(self,
1359 self.pg2.sw_if_index,
1360 self.pg2.remote_hosts[0].ip4,
1362 self.assertTrue(find_nbr(self,
1363 self.pg2.sw_if_index,
1364 self.pg2.remote_hosts[0].ip4,
1366 mac=self.pg2.remote_hosts[1].mac))
1371 static_arp.remove_vpp_config()
1373 def test_arp_incomplete(self):
1374 """ ARP Incomplete"""
1375 self.pg1.generate_remote_hosts(4)
1377 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1378 IP(src=self.pg0.remote_ip4,
1379 dst=self.pg1.remote_hosts[1].ip4) /
1380 UDP(sport=1234, dport=1234) /
1382 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1383 IP(src=self.pg0.remote_ip4,
1384 dst=self.pg1.remote_hosts[2].ip4) /
1385 UDP(sport=1234, dport=1234) /
1387 p2 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1388 IP(src=self.pg0.remote_ip4,
1390 UDP(sport=1234, dport=1234) /
1394 # a packet to an unresolved destination generates an ARP request
1396 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1397 self.verify_arp_req(rx[0],
1400 self.pg1._remote_hosts[1].ip4)
1403 # add a neighbour for remote host 1
1405 static_arp = VppNeighbor(self,
1406 self.pg1.sw_if_index,
1407 self.pg1.remote_hosts[1].mac,
1408 self.pg1.remote_hosts[1].ip4,
1410 static_arp.add_vpp_config()
1413 # add a route through remote host 3 hence we get an incomplete
1415 VppIpRoute(self, "1.1.1.1", 32,
1416 [VppRoutePath(self.pg1.remote_hosts[3].ip4,
1417 self.pg1.sw_if_index)]).add_vpp_config()
1418 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
1419 self.verify_arp_req(rx[0],
1422 self.pg1._remote_hosts[3].ip4)
1425 # change the interface's MAC
1427 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1428 "00:00:00:33:33:33")
1431 # now ARP requests come from the new source mac
1433 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1434 self.verify_arp_req(rx[0],
1435 "00:00:00:33:33:33",
1437 self.pg1._remote_hosts[2].ip4)
1438 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
1439 self.verify_arp_req(rx[0],
1440 "00:00:00:33:33:33",
1442 self.pg1._remote_hosts[3].ip4)
1445 # packets to the resolved host also have the new source mac
1447 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1448 self.verify_ip(rx[0],
1449 "00:00:00:33:33:33",
1450 self.pg1.remote_hosts[1].mac,
1451 self.pg0.remote_ip4,
1452 self.pg1.remote_hosts[1].ip4)
1455 # set the mac address on the interface that does not have a
1456 # configured subnet and thus no glean
1458 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1459 "00:00:00:33:33:33")
1461 def test_garp(self):
1465 # Generate some hosts on the LAN
1467 self.pg1.generate_remote_hosts(4)
1468 self.pg2.generate_remote_hosts(4)
1473 arp = VppNeighbor(self,
1474 self.pg1.sw_if_index,
1475 self.pg1.remote_hosts[1].mac,
1476 self.pg1.remote_hosts[1].ip4)
1477 arp.add_vpp_config()
1479 self.assertTrue(find_nbr(self,
1480 self.pg1.sw_if_index,
1481 self.pg1.remote_hosts[1].ip4,
1482 mac=self.pg1.remote_hosts[1].mac))
1485 # Send a GARP (request) to swap the host 1's address to that of host 2
1487 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1488 src=self.pg1.remote_hosts[2].mac) /
1490 hwdst=self.pg1.local_mac,
1491 hwsrc=self.pg1.remote_hosts[2].mac,
1492 pdst=self.pg1.remote_hosts[1].ip4,
1493 psrc=self.pg1.remote_hosts[1].ip4))
1495 self.pg1.add_stream(p1)
1496 self.pg_enable_capture(self.pg_interfaces)
1499 self.assertTrue(find_nbr(self,
1500 self.pg1.sw_if_index,
1501 self.pg1.remote_hosts[1].ip4,
1502 mac=self.pg1.remote_hosts[2].mac))
1505 # Send a GARP (reply) to swap the host 1's address to that of host 3
1507 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1508 src=self.pg1.remote_hosts[3].mac) /
1510 hwdst=self.pg1.local_mac,
1511 hwsrc=self.pg1.remote_hosts[3].mac,
1512 pdst=self.pg1.remote_hosts[1].ip4,
1513 psrc=self.pg1.remote_hosts[1].ip4))
1515 self.pg1.add_stream(p1)
1516 self.pg_enable_capture(self.pg_interfaces)
1519 self.assertTrue(find_nbr(self,
1520 self.pg1.sw_if_index,
1521 self.pg1.remote_hosts[1].ip4,
1522 mac=self.pg1.remote_hosts[3].mac))
1525 # GARPs (request nor replies) for host we don't know yet
1526 # don't result in new neighbour entries
1528 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1529 src=self.pg1.remote_hosts[3].mac) /
1531 hwdst=self.pg1.local_mac,
1532 hwsrc=self.pg1.remote_hosts[3].mac,
1533 pdst=self.pg1.remote_hosts[2].ip4,
1534 psrc=self.pg1.remote_hosts[2].ip4))
1536 self.pg1.add_stream(p1)
1537 self.pg_enable_capture(self.pg_interfaces)
1540 self.assertFalse(find_nbr(self,
1541 self.pg1.sw_if_index,
1542 self.pg1.remote_hosts[2].ip4))
1544 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1545 src=self.pg1.remote_hosts[3].mac) /
1547 hwdst=self.pg1.local_mac,
1548 hwsrc=self.pg1.remote_hosts[3].mac,
1549 pdst=self.pg1.remote_hosts[2].ip4,
1550 psrc=self.pg1.remote_hosts[2].ip4))
1552 self.pg1.add_stream(p1)
1553 self.pg_enable_capture(self.pg_interfaces)
1556 self.assertFalse(find_nbr(self,
1557 self.pg1.sw_if_index,
1558 self.pg1.remote_hosts[2].ip4))
1561 # IP address in different subnets are not learnt
1563 self.pg2.configure_ipv4_neighbors()
1565 for op in ["is-at", "who-has"]:
1566 p1 = [(Ether(dst="ff:ff:ff:ff:ff:ff",
1567 src=self.pg2.remote_hosts[1].mac) /
1569 hwdst=self.pg2.local_mac,
1570 hwsrc=self.pg2.remote_hosts[1].mac,
1571 pdst=self.pg2.remote_hosts[1].ip4,
1572 psrc=self.pg2.remote_hosts[1].ip4)),
1573 (Ether(dst="ff:ff:ff:ff:ff:ff",
1574 src=self.pg2.remote_hosts[1].mac) /
1576 hwdst="ff:ff:ff:ff:ff:ff",
1577 hwsrc=self.pg2.remote_hosts[1].mac,
1578 pdst=self.pg2.remote_hosts[1].ip4,
1579 psrc=self.pg2.remote_hosts[1].ip4))]
1581 self.send_and_assert_no_replies(self.pg1, p1)
1582 self.assertFalse(find_nbr(self,
1583 self.pg1.sw_if_index,
1584 self.pg2.remote_hosts[1].ip4))
1586 # they are all dropped because the subnet's don't match
1587 self.assertEqual(4, self.statistics.get_err_counter(
1588 "/err/arp-reply/IP4 destination address not local to subnet"))
1590 def test_arp_incomplete2(self):
1591 """ Incomplete Entries """
1594 # ensure that we throttle the ARP and ND requests
1596 self.pg0.generate_remote_hosts(2)
1601 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1602 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
1603 self.pg0.sw_if_index)])
1604 ip_10_0_0_1.add_vpp_config()
1606 p1 = (Ether(dst=self.pg1.local_mac,
1607 src=self.pg1.remote_mac) /
1608 IP(src=self.pg1.remote_ip4,
1610 UDP(sport=1234, dport=1234) /
1613 self.pg1.add_stream(p1 * 257)
1614 self.pg_enable_capture(self.pg_interfaces)
1616 rx = self.pg0._get_capture(1)
1619 # how many we get is going to be dependent on the time for packet
1620 # processing but it should be small
1622 self.assertLess(len(rx), 64)
1627 ip_10_1 = VppIpRoute(self, "10::1", 128,
1628 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1629 self.pg0.sw_if_index,
1630 proto=DpoProto.DPO_PROTO_IP6)])
1631 ip_10_1.add_vpp_config()
1633 p1 = (Ether(dst=self.pg1.local_mac,
1634 src=self.pg1.remote_mac) /
1635 IPv6(src=self.pg1.remote_ip6,
1637 UDP(sport=1234, dport=1234) /
1640 self.pg1.add_stream(p1 * 257)
1641 self.pg_enable_capture(self.pg_interfaces)
1643 rx = self.pg0._get_capture(1)
1646 # how many we get is going to be dependent on the time for packet
1647 # processing but it should be small
1649 self.assertLess(len(rx), 64)
1651 def test_arp_forus(self):
1652 """ ARP for for-us """
1655 # Test that VPP responds with ARP requests to addresses that
1656 # are connected and local routes.
1657 # Use one of the 'remote' addresses in the subnet as a local address
1658 # The intention of this route is that it then acts like a secondary
1659 # address added to an interface
1661 self.pg0.generate_remote_hosts(2)
1664 self, self.pg0.remote_hosts[1].ip4, 32,
1665 [VppRoutePath("0.0.0.0",
1666 self.pg0.sw_if_index,
1667 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
1668 forus.add_vpp_config()
1670 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1671 src=self.pg0.remote_mac) /
1673 hwdst=self.pg0.local_mac,
1674 hwsrc=self.pg0.remote_mac,
1675 pdst=self.pg0.remote_hosts[1].ip4,
1676 psrc=self.pg0.remote_ip4))
1678 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1680 self.verify_arp_resp(rx[0],
1682 self.pg0.remote_mac,
1683 self.pg0.remote_hosts[1].ip4,
1684 self.pg0.remote_ip4)
1686 def test_arp_table_swap(self):
1688 # Generate some hosts on the LAN
1691 self.pg1.generate_remote_hosts(N_NBRS)
1693 for n in range(N_NBRS):
1694 # a route thru each neighbour
1695 VppIpRoute(self, "10.0.0.%d" % n, 32,
1696 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1697 self.pg1.sw_if_index)]).add_vpp_config()
1699 # resolve each neighbour
1700 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1701 ARP(op="is-at", hwdst=self.pg1.local_mac,
1702 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1703 psrc=self.pg1.remote_hosts[n].ip4))
1705 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1707 self.logger.info(self.vapi.cli("sh ip neighbors"))
1710 # swap the table pg1 is in
1712 table = VppIpTable(self, 100).add_vpp_config()
1714 self.pg1.unconfig_ip4()
1715 self.pg1.set_table_ip4(100)
1716 self.pg1.config_ip4()
1719 # all neighbours are cleared
1721 for n in range(N_NBRS):
1722 self.assertFalse(find_nbr(self,
1723 self.pg1.sw_if_index,
1724 self.pg1.remote_hosts[n].ip4))
1727 # packets to all neighbours generate ARP requests
1729 for n in range(N_NBRS):
1730 # a route thru each neighbour
1731 VppIpRoute(self, "10.0.0.%d" % n, 32,
1732 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1733 self.pg1.sw_if_index)],
1734 table_id=100).add_vpp_config()
1736 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1737 dst=self.pg1.local_mac) /
1738 IP(src=self.pg1.remote_hosts[n].ip4,
1739 dst="10.0.0.%d" % n) /
1741 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1743 self.verify_arp_req(rx,
1746 self.pg1.remote_hosts[n].ip4)
1748 self.pg1.unconfig_ip4()
1749 self.pg1.set_table_ip4(0)
1751 def test_glean_src_select(self):
1752 """ Multi Connecteds """
1755 # configure multiple connected subnets on an interface
1756 # and ensure that ARP requests for hosts on those subnets
1757 # pick up the correct source address
1759 conn1 = VppIpInterfaceAddress(self, self.pg1,
1760 "10.0.0.1", 24).add_vpp_config()
1761 conn2 = VppIpInterfaceAddress(self, self.pg1,
1762 "10.0.1.1", 24).add_vpp_config()
1764 p1 = (Ether(src=self.pg0.remote_mac,
1765 dst=self.pg0.local_mac) /
1766 IP(src=self.pg1.remote_ip4,
1770 rxs = self.send_and_expect(self.pg0, [p1], self.pg1)
1772 self.verify_arp_req(rx,
1777 p2 = (Ether(src=self.pg0.remote_mac,
1778 dst=self.pg0.local_mac) /
1779 IP(src=self.pg1.remote_ip4,
1783 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1785 self.verify_arp_req(rx,
1791 # add a local address in the same subnet
1792 # the source addresses are equivalent. VPP happens to
1793 # choose the last one that was added
1794 conn3 = VppIpInterfaceAddress(self, self.pg1,
1795 "10.0.1.2", 24).add_vpp_config()
1797 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1799 self.verify_arp_req(rx,
1807 conn3.remove_vpp_config()
1808 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1810 self.verify_arp_req(rx,
1816 # add back, this time remove the first one
1818 conn3 = VppIpInterfaceAddress(self, self.pg1,
1819 "10.0.1.2", 24).add_vpp_config()
1821 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1823 self.verify_arp_req(rx,
1828 conn1.remove_vpp_config()
1829 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1831 self.verify_arp_req(rx,
1836 # apply a connected prefix to an interface in a different table
1837 VppIpRoute(self, "10.0.1.0", 24,
1838 [VppRoutePath("0.0.0.0",
1839 self.pg1.sw_if_index)],
1840 table_id=1).add_vpp_config()
1842 rxs = self.send_and_expect(self.pg3, [p2], self.pg1)
1844 self.verify_arp_req(rx,
1850 conn3.remove_vpp_config()
1851 conn2.remove_vpp_config()
1854 @tag_fixme_vpp_workers
1855 class NeighborStatsTestCase(VppTestCase):
1856 """ ARP/ND Counters """
1859 def setUpClass(cls):
1860 super(NeighborStatsTestCase, cls).setUpClass()
1863 def tearDownClass(cls):
1864 super(NeighborStatsTestCase, cls).tearDownClass()
1867 super(NeighborStatsTestCase, self).setUp()
1869 self.create_pg_interfaces(range(2))
1871 # pg0 configured with ip4 and 6 addresses used for input
1872 # pg1 configured with ip4 and 6 addresses used for output
1873 # pg2 is unnumbered to pg0
1874 for i in self.pg_interfaces:
1882 super(NeighborStatsTestCase, self).tearDown()
1884 for i in self.pg_interfaces:
1889 def test_arp_stats(self):
1890 """ ARP Counters """
1892 self.vapi.cli("adj counters enable")
1893 self.pg1.generate_remote_hosts(2)
1895 arp1 = VppNeighbor(self,
1896 self.pg1.sw_if_index,
1897 self.pg1.remote_hosts[0].mac,
1898 self.pg1.remote_hosts[0].ip4)
1899 arp1.add_vpp_config()
1900 arp2 = VppNeighbor(self,
1901 self.pg1.sw_if_index,
1902 self.pg1.remote_hosts[1].mac,
1903 self.pg1.remote_hosts[1].ip4)
1904 arp2.add_vpp_config()
1906 p1 = (Ether(dst=self.pg0.local_mac,
1907 src=self.pg0.remote_mac) /
1908 IP(src=self.pg0.remote_ip4,
1909 dst=self.pg1.remote_hosts[0].ip4) /
1910 UDP(sport=1234, dport=1234) /
1912 p2 = (Ether(dst=self.pg0.local_mac,
1913 src=self.pg0.remote_mac) /
1914 IP(src=self.pg0.remote_ip4,
1915 dst=self.pg1.remote_hosts[1].ip4) /
1916 UDP(sport=1234, dport=1234) /
1919 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1920 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
1922 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1923 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
1925 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1926 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
1928 def test_nd_stats(self):
1931 self.vapi.cli("adj counters enable")
1932 self.pg0.generate_remote_hosts(3)
1934 nd1 = VppNeighbor(self,
1935 self.pg0.sw_if_index,
1936 self.pg0.remote_hosts[1].mac,
1937 self.pg0.remote_hosts[1].ip6)
1938 nd1.add_vpp_config()
1939 nd2 = VppNeighbor(self,
1940 self.pg0.sw_if_index,
1941 self.pg0.remote_hosts[2].mac,
1942 self.pg0.remote_hosts[2].ip6)
1943 nd2.add_vpp_config()
1945 p1 = (Ether(dst=self.pg1.local_mac,
1946 src=self.pg1.remote_mac) /
1947 IPv6(src=self.pg1.remote_ip6,
1948 dst=self.pg0.remote_hosts[1].ip6) /
1949 UDP(sport=1234, dport=1234) /
1951 p2 = (Ether(dst=self.pg1.local_mac,
1952 src=self.pg1.remote_mac) /
1953 IPv6(src=self.pg1.remote_ip6,
1954 dst=self.pg0.remote_hosts[2].ip6) /
1955 UDP(sport=1234, dport=1234) /
1958 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1959 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1961 self.assertEqual(16, nd1.get_stats()['packets'])
1962 self.assertEqual(16, nd2.get_stats()['packets'])
1964 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1965 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
1968 class NeighborAgeTestCase(VppTestCase):
1969 """ ARP/ND Aging """
1972 def setUpClass(cls):
1973 super(NeighborAgeTestCase, cls).setUpClass()
1976 def tearDownClass(cls):
1977 super(NeighborAgeTestCase, cls).tearDownClass()
1980 super(NeighborAgeTestCase, self).setUp()
1982 self.create_pg_interfaces(range(1))
1984 # pg0 configured with ip4 and 6 addresses used for input
1985 # pg1 configured with ip4 and 6 addresses used for output
1986 # pg2 is unnumbered to pg0
1987 for i in self.pg_interfaces:
1995 super(NeighborAgeTestCase, self).tearDown()
1997 for i in self.pg_interfaces:
2002 def wait_for_no_nbr(self, intf, address,
2003 n_tries=50, s_time=1):
2005 if not find_nbr(self, intf, address):
2007 n_tries = n_tries - 1
2012 def verify_arp_req(self, rx, smac, sip, dip):
2014 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2015 self.assertEqual(ether.src, smac)
2018 self.assertEqual(arp.hwtype, 1)
2019 self.assertEqual(arp.ptype, 0x800)
2020 self.assertEqual(arp.hwlen, 6)
2021 self.assertEqual(arp.plen, 4)
2022 self.assertEqual(arp.op, arp_opts["who-has"])
2023 self.assertEqual(arp.hwsrc, smac)
2024 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2025 self.assertEqual(arp.psrc, sip)
2026 self.assertEqual(arp.pdst, dip)
2029 """ Aging/Recycle """
2031 self.vapi.cli("set logging unthrottle 0")
2032 self.vapi.cli("set logging size %d" % 0xffff)
2034 self.pg0.generate_remote_hosts(201)
2036 vaf = VppEnum.vl_api_address_family_t
2039 # start listening on all interfaces
2041 self.pg_enable_capture(self.pg_interfaces)
2044 # Set the neighbor configuration:
2049 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2054 self.vapi.cli("sh ip neighbor-config")
2056 # add the 198 neighbours that should pass (-1 for one created in setup)
2057 for ii in range(200):
2059 self.pg0.sw_if_index,
2060 self.pg0.remote_hosts[ii].mac,
2061 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2063 # one more neighbor over the limit should fail
2064 with self.vapi.assert_negative_api_retval():
2066 self.pg0.sw_if_index,
2067 self.pg0.remote_hosts[200].mac,
2068 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2071 # change the config to allow recycling the old neighbors
2073 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2078 # now new additions are allowed
2080 self.pg0.sw_if_index,
2081 self.pg0.remote_hosts[200].mac,
2082 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2084 # add the first neighbor we configured has been re-used
2085 self.assertFalse(find_nbr(self,
2086 self.pg0.sw_if_index,
2087 self.pg0.remote_hosts[0].ip4))
2088 self.assertTrue(find_nbr(self,
2089 self.pg0.sw_if_index,
2090 self.pg0.remote_hosts[200].ip4))
2093 # change the config to age old neighbors
2095 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2100 self.vapi.cli("sh ip4 neighbor-sorted")
2103 # expect probes from all these ARP entries as they age
2104 # 3 probes for each neighbor 3*200 = 600
2105 rxs = self.pg0.get_capture(600, timeout=8)
2108 for jj in range(200):
2109 rx = rxs[ii*200 + jj]
2113 # 3 probes sent then 1 more second to see if a reply comes, before
2116 for jj in range(1, 201):
2117 self.wait_for_no_nbr(self.pg0.sw_if_index,
2118 self.pg0.remote_hosts[jj].ip4)
2120 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2121 af=vaf.ADDRESS_IP4))
2124 # load up some neighbours again with 2s aging enabled
2125 # they should be removed after 10s (2s age + 4s for probes + gap)
2126 # check for the add and remove events
2128 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2130 self.vapi.want_ip_neighbor_events_v2(enable=1)
2131 for ii in range(10):
2133 self.pg0.sw_if_index,
2134 self.pg0.remote_hosts[ii].mac,
2135 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2137 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2138 self.assertEqual(e.flags,
2139 enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2140 self.assertEqual(str(e.neighbor.ip_address),
2141 self.pg0.remote_hosts[ii].ip4)
2142 self.assertEqual(e.neighbor.mac_address,
2143 self.pg0.remote_hosts[ii].mac)
2146 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2147 af=vaf.ADDRESS_IP4))
2150 for ii in range(10):
2151 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2152 self.assertEqual(e.flags,
2153 enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
2156 # check we got the correct mac/ip pairs - done separately
2157 # because we don't care about the order the remove notifications
2159 for ii in range(10):
2161 mac = self.pg0.remote_hosts[ii].mac
2162 ip = self.pg0.remote_hosts[ii].ip4
2165 if (e.neighbor.mac_address == mac and
2166 str(e.neighbor.ip_address) == ip):
2169 self.assertTrue(found)
2172 # check if we can set age and recycle with empty neighbor list
2174 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2180 # load up some neighbours again, then disable the aging
2181 # they should still be there in 10 seconds time
2183 for ii in range(10):
2185 self.pg0.sw_if_index,
2186 self.pg0.remote_hosts[ii].mac,
2187 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2188 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2194 self.assertTrue(find_nbr(self,
2195 self.pg0.sw_if_index,
2196 self.pg0.remote_hosts[0].ip4))
2199 class NeighborReplaceTestCase(VppTestCase):
2200 """ ARP/ND Replacement """
2203 def setUpClass(cls):
2204 super(NeighborReplaceTestCase, cls).setUpClass()
2207 def tearDownClass(cls):
2208 super(NeighborReplaceTestCase, cls).tearDownClass()
2211 super(NeighborReplaceTestCase, self).setUp()
2213 self.create_pg_interfaces(range(4))
2215 # pg0 configured with ip4 and 6 addresses used for input
2216 # pg1 configured with ip4 and 6 addresses used for output
2217 # pg2 is unnumbered to pg0
2218 for i in self.pg_interfaces:
2226 super(NeighborReplaceTestCase, self).tearDown()
2228 for i in self.pg_interfaces:
2233 def test_replace(self):
2238 for i in self.pg_interfaces:
2239 i.generate_remote_hosts(N_HOSTS)
2240 i.configure_ipv4_neighbors()
2241 i.configure_ipv6_neighbors()
2244 self.vapi.ip_neighbor_replace_begin()
2245 self.vapi.ip_neighbor_replace_end()
2247 for i in self.pg_interfaces:
2248 for h in range(N_HOSTS):
2249 self.assertFalse(find_nbr(self,
2250 self.pg0.sw_if_index,
2251 self.pg0.remote_hosts[h].ip4))
2252 self.assertFalse(find_nbr(self,
2253 self.pg0.sw_if_index,
2254 self.pg0.remote_hosts[h].ip6))
2257 # and them all back via the API
2259 for i in self.pg_interfaces:
2260 for h in range(N_HOSTS):
2263 i.remote_hosts[h].mac,
2264 i.remote_hosts[h].ip4).add_vpp_config()
2267 i.remote_hosts[h].mac,
2268 i.remote_hosts[h].ip6).add_vpp_config()
2271 # begin the replacement again, this time touch some
2272 # the neighbours on pg1 so they are not deleted
2274 self.vapi.ip_neighbor_replace_begin()
2276 # update from the API all neighbours on pg1
2277 for h in range(N_HOSTS):
2279 self.pg1.sw_if_index,
2280 self.pg1.remote_hosts[h].mac,
2281 self.pg1.remote_hosts[h].ip4).add_vpp_config()
2283 self.pg1.sw_if_index,
2284 self.pg1.remote_hosts[h].mac,
2285 self.pg1.remote_hosts[h].ip6).add_vpp_config()
2287 # update from the data-plane all neighbours on pg3
2288 self.pg3.configure_ipv4_neighbors()
2289 self.pg3.configure_ipv6_neighbors()
2291 # complete the replacement
2292 self.logger.info(self.vapi.cli("sh ip neighbors"))
2293 self.vapi.ip_neighbor_replace_end()
2295 for i in self.pg_interfaces:
2296 if i == self.pg1 or i == self.pg3:
2297 # neighbours on pg1 and pg3 are still present
2298 for h in range(N_HOSTS):
2299 self.assertTrue(find_nbr(self,
2301 i.remote_hosts[h].ip4))
2302 self.assertTrue(find_nbr(self,
2304 i.remote_hosts[h].ip6))
2306 # all other neighbours are toast
2307 for h in range(N_HOSTS):
2308 self.assertFalse(find_nbr(self,
2310 i.remote_hosts[h].ip4))
2311 self.assertFalse(find_nbr(self,
2313 i.remote_hosts[h].ip6))
2316 class NeighborFlush(VppTestCase):
2317 """ Neighbor Flush """
2320 def setUpClass(cls):
2321 super(NeighborFlush, cls).setUpClass()
2324 def tearDownClass(cls):
2325 super(NeighborFlush, cls).tearDownClass()
2328 super(NeighborFlush, self).setUp()
2330 self.create_pg_interfaces(range(2))
2332 for i in self.pg_interfaces:
2340 super(NeighborFlush, self).tearDown()
2342 for i in self.pg_interfaces:
2347 def test_flush(self):
2348 """ Neighbour Flush """
2351 nf = e.vl_api_ip_neighbor_flags_t
2352 af = e.vl_api_address_family_t
2354 static = [False, True]
2355 self.pg0.generate_remote_hosts(N_HOSTS)
2356 self.pg1.generate_remote_hosts(N_HOSTS)
2359 # a few v4 and v6 dynamic neoghbors
2360 for n in range(N_HOSTS):
2362 self.pg0.sw_if_index,
2363 self.pg0.remote_hosts[n].mac,
2364 self.pg0.remote_hosts[n].ip4,
2365 is_static=s).add_vpp_config()
2367 self.pg1.sw_if_index,
2368 self.pg1.remote_hosts[n].mac,
2369 self.pg1.remote_hosts[n].ip6,
2370 is_static=s).add_vpp_config()
2372 # flush the interfaces individually
2373 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2375 # check we haven't flushed that which we shouldn't
2376 for n in range(N_HOSTS):
2377 self.assertTrue(find_nbr(self,
2378 self.pg1.sw_if_index,
2379 self.pg1.remote_hosts[n].ip6,
2382 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2384 for n in range(N_HOSTS):
2385 self.assertFalse(find_nbr(self,
2386 self.pg0.sw_if_index,
2387 self.pg0.remote_hosts[n].ip4))
2388 self.assertFalse(find_nbr(self,
2389 self.pg1.sw_if_index,
2390 self.pg1.remote_hosts[n].ip6))
2392 # add the nieghbours back
2393 for n in range(N_HOSTS):
2395 self.pg0.sw_if_index,
2396 self.pg0.remote_hosts[n].mac,
2397 self.pg0.remote_hosts[n].ip4,
2398 is_static=s).add_vpp_config()
2400 self.pg1.sw_if_index,
2401 self.pg1.remote_hosts[n].mac,
2402 self.pg1.remote_hosts[n].ip6,
2403 is_static=s).add_vpp_config()
2405 self.logger.info(self.vapi.cli("sh ip neighbor"))
2407 # flush both interfaces at the same time
2408 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2410 # check we haven't flushed that which we shouldn't
2411 for n in range(N_HOSTS):
2412 self.assertTrue(find_nbr(self,
2413 self.pg0.sw_if_index,
2414 self.pg0.remote_hosts[n].ip4,
2417 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2419 for n in range(N_HOSTS):
2420 self.assertFalse(find_nbr(self,
2421 self.pg0.sw_if_index,
2422 self.pg0.remote_hosts[n].ip4))
2423 self.assertFalse(find_nbr(self,
2424 self.pg1.sw_if_index,
2425 self.pg1.remote_hosts[n].ip6))
2428 if __name__ == '__main__':
2429 unittest.main(testRunner=VppTestRunner)