5 from socket import AF_INET, AF_INET6, inet_pton
7 from framework import VppTestCase, VppTestRunner
8 from vpp_neighbor import VppNeighbor, find_nbr
9 from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
10 VppIpTable, DpoProto, FibPathType
11 from vpp_papi import VppEnum
14 from scapy.packet import Raw
15 from scapy.layers.l2 import Ether, ARP, Dot1Q
16 from scapy.layers.inet import IP, UDP
17 from scapy.layers.inet6 import IPv6
18 from scapy.contrib.mpls import MPLS
19 from scapy.layers.inet6 import IPv6
24 # not exported by scapy, so redefined here
25 arp_opts = {"who-has": 1, "is-at": 2}
28 class ARPTestCase(VppTestCase):
33 super(ARPTestCase, cls).setUpClass()
36 def tearDownClass(cls):
37 super(ARPTestCase, cls).tearDownClass()
40 super(ARPTestCase, self).setUp()
42 # create 3 pg interfaces
43 self.create_pg_interfaces(range(4))
45 # pg0 configured with ip4 and 6 addresses used for input
46 # pg1 configured with ip4 and 6 addresses used for output
47 # pg2 is unnumbered to pg0
48 for i in self.pg_interfaces:
53 self.pg0.resolve_arp()
58 # pg3 in a different VRF
59 self.tbl = VppIpTable(self, 1)
60 self.tbl.add_vpp_config()
62 self.pg3.set_table_ip4(1)
66 self.pg0.unconfig_ip4()
67 self.pg0.unconfig_ip6()
69 self.pg1.unconfig_ip4()
70 self.pg1.unconfig_ip6()
72 self.pg3.unconfig_ip4()
73 self.pg3.set_table_ip4(0)
75 for i in self.pg_interfaces:
78 super(ARPTestCase, self).tearDown()
80 def verify_arp_req(self, rx, smac, sip, dip):
82 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
83 self.assertEqual(ether.src, smac)
86 self.assertEqual(arp.hwtype, 1)
87 self.assertEqual(arp.ptype, 0x800)
88 self.assertEqual(arp.hwlen, 6)
89 self.assertEqual(arp.plen, 4)
90 self.assertEqual(arp.op, arp_opts["who-has"])
91 self.assertEqual(arp.hwsrc, smac)
92 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
93 self.assertEqual(arp.psrc, sip)
94 self.assertEqual(arp.pdst, dip)
96 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
98 self.assertEqual(ether.dst, dmac)
99 self.assertEqual(ether.src, smac)
102 self.assertEqual(arp.hwtype, 1)
103 self.assertEqual(arp.ptype, 0x800)
104 self.assertEqual(arp.hwlen, 6)
105 self.assertEqual(arp.plen, 4)
106 self.assertEqual(arp.op, arp_opts["is-at"])
107 self.assertEqual(arp.hwsrc, smac)
108 self.assertEqual(arp.hwdst, dmac)
109 self.assertEqual(arp.psrc, sip)
110 self.assertEqual(arp.pdst, dip)
112 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
114 self.assertEqual(ether.dst, dmac)
115 self.assertEqual(ether.src, smac)
118 self.assertEqual(arp.hwtype, 1)
119 self.assertEqual(arp.ptype, 0x800)
120 self.assertEqual(arp.hwlen, 6)
121 self.assertEqual(arp.plen, 4)
122 self.assertEqual(arp.op, arp_opts["is-at"])
123 self.assertNotEqual(arp.hwsrc, smac)
124 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
125 "00:00:5E:00:01" in arp.hwsrc)
126 self.assertEqual(arp.hwdst, dmac)
127 self.assertEqual(arp.psrc, sip)
128 self.assertEqual(arp.pdst, dip)
130 def verify_ip(self, rx, smac, dmac, sip, dip):
132 self.assertEqual(ether.dst, dmac)
133 self.assertEqual(ether.src, smac)
136 self.assertEqual(ip.src, sip)
137 self.assertEqual(ip.dst, dip)
139 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
141 self.assertEqual(ether.dst, dmac)
142 self.assertEqual(ether.src, smac)
145 self.assertTrue(mpls.label, label)
148 self.assertEqual(ip.src, sip)
149 self.assertEqual(ip.dst, dip)
155 # Generate some hosts on the LAN
157 self.pg1.generate_remote_hosts(11)
161 # - all neighbour events
162 # - all neighbor events on pg1
163 # - neighbor events for host[1] on pg1
165 self.vapi.want_ip_neighbor_events(enable=1,
167 self.vapi.want_ip_neighbor_events(enable=1,
169 sw_if_index=self.pg1.sw_if_index)
170 self.vapi.want_ip_neighbor_events(enable=1,
172 sw_if_index=self.pg1.sw_if_index,
173 ip=self.pg1.remote_hosts[1].ip4)
175 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
178 # Send IP traffic to one of these unresolved hosts.
179 # expect the generation of an ARP request
181 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
182 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
183 UDP(sport=1234, dport=1234) /
186 self.pg0.add_stream(p)
187 self.pg_enable_capture(self.pg_interfaces)
190 rx = self.pg1.get_capture(1)
192 self.verify_arp_req(rx[0],
195 self.pg1._remote_hosts[1].ip4)
198 # And a dynamic ARP entry for host 1
200 dyn_arp = VppNeighbor(self,
201 self.pg1.sw_if_index,
202 self.pg1.remote_hosts[1].mac,
203 self.pg1.remote_hosts[1].ip4)
204 dyn_arp.add_vpp_config()
205 self.assertTrue(dyn_arp.query_vpp_config())
207 # this matches all of the listnerers
208 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
211 self.assertEqual(str(e.neighbor.ip_address),
212 self.pg1.remote_hosts[1].ip4)
215 # now we expect IP traffic forwarded
217 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
218 IP(src=self.pg0.remote_ip4,
219 dst=self.pg1._remote_hosts[1].ip4) /
220 UDP(sport=1234, dport=1234) /
223 self.pg0.add_stream(dyn_p)
224 self.pg_enable_capture(self.pg_interfaces)
227 rx = self.pg1.get_capture(1)
229 self.verify_ip(rx[0],
231 self.pg1.remote_hosts[1].mac,
233 self.pg1._remote_hosts[1].ip4)
236 # And a Static ARP entry for host 2
238 static_arp = VppNeighbor(self,
239 self.pg1.sw_if_index,
240 self.pg1.remote_hosts[2].mac,
241 self.pg1.remote_hosts[2].ip4,
243 static_arp.add_vpp_config()
244 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
247 self.assertEqual(str(e.neighbor.ip_address),
248 self.pg1.remote_hosts[2].ip4)
250 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
251 IP(src=self.pg0.remote_ip4,
252 dst=self.pg1._remote_hosts[2].ip4) /
253 UDP(sport=1234, dport=1234) /
256 self.pg0.add_stream(static_p)
257 self.pg_enable_capture(self.pg_interfaces)
260 rx = self.pg1.get_capture(1)
262 self.verify_ip(rx[0],
264 self.pg1.remote_hosts[2].mac,
266 self.pg1._remote_hosts[2].ip4)
269 # remove all the listeners
271 self.vapi.want_ip_neighbor_events(enable=0,
273 self.vapi.want_ip_neighbor_events(enable=0,
275 sw_if_index=self.pg1.sw_if_index)
276 self.vapi.want_ip_neighbor_events(enable=0,
278 sw_if_index=self.pg1.sw_if_index,
279 ip=self.pg1.remote_hosts[1].ip4)
282 # flap the link. dynamic ARPs get flush, statics don't
284 self.pg1.admin_down()
287 self.pg0.add_stream(static_p)
288 self.pg_enable_capture(self.pg_interfaces)
290 rx = self.pg1.get_capture(1)
292 self.verify_ip(rx[0],
294 self.pg1.remote_hosts[2].mac,
296 self.pg1._remote_hosts[2].ip4)
298 self.pg0.add_stream(dyn_p)
299 self.pg_enable_capture(self.pg_interfaces)
302 rx = self.pg1.get_capture(1)
303 self.verify_arp_req(rx[0],
306 self.pg1._remote_hosts[1].ip4)
308 self.assertFalse(dyn_arp.query_vpp_config())
309 self.assertTrue(static_arp.query_vpp_config())
311 # Send an ARP request from one of the so-far unlearned remote hosts
313 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
314 src=self.pg1._remote_hosts[3].mac) /
316 hwsrc=self.pg1._remote_hosts[3].mac,
317 pdst=self.pg1.local_ip4,
318 psrc=self.pg1._remote_hosts[3].ip4))
320 self.pg1.add_stream(p)
321 self.pg_enable_capture(self.pg_interfaces)
324 rx = self.pg1.get_capture(1)
325 self.verify_arp_resp(rx[0],
327 self.pg1._remote_hosts[3].mac,
329 self.pg1._remote_hosts[3].ip4)
332 # VPP should have learned the mapping for the remote host
334 self.assertTrue(find_nbr(self,
335 self.pg1.sw_if_index,
336 self.pg1._remote_hosts[3].ip4))
338 # Fire in an ARP request before the interface becomes IP enabled
340 self.pg2.generate_remote_hosts(4)
342 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
344 hwsrc=self.pg2.remote_mac,
345 pdst=self.pg1.local_ip4,
346 psrc=self.pg2.remote_hosts[3].ip4))
347 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
350 hwsrc=self.pg2.remote_mac,
351 pdst=self.pg1.local_ip4,
352 psrc=self.pg2.remote_hosts[3].ip4))
353 self.send_and_assert_no_replies(self.pg2, p,
354 "interface not IP enabled")
357 # Make pg2 un-numbered to pg1
359 self.pg2.set_unnumbered(self.pg1.sw_if_index)
362 # test the unnumbered dump both by all interfaces and just the enabled
365 unnum = self.vapi.ip_unnumbered_dump()
366 self.assertTrue(len(unnum))
367 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
368 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
369 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
370 self.assertTrue(len(unnum))
371 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
372 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
375 # We should respond to ARP requests for the unnumbered to address
376 # once an attached route to the source is known
378 self.send_and_assert_no_replies(
380 "ARP req for unnumbered address - no source")
382 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
383 [VppRoutePath("0.0.0.0",
384 self.pg2.sw_if_index)])
385 attached_host.add_vpp_config()
387 self.pg2.add_stream(p)
388 self.pg_enable_capture(self.pg_interfaces)
391 rx = self.pg2.get_capture(1)
392 self.verify_arp_resp(rx[0],
396 self.pg2.remote_hosts[3].ip4)
398 self.pg2.add_stream(pt)
399 self.pg_enable_capture(self.pg_interfaces)
402 rx = self.pg2.get_capture(1)
403 self.verify_arp_resp(rx[0],
407 self.pg2.remote_hosts[3].ip4)
410 # A neighbor entry that has no associated FIB-entry
412 arp_no_fib = VppNeighbor(self,
413 self.pg1.sw_if_index,
414 self.pg1.remote_hosts[4].mac,
415 self.pg1.remote_hosts[4].ip4,
417 arp_no_fib.add_vpp_config()
420 # check we have the neighbor, but no route
422 self.assertTrue(find_nbr(self,
423 self.pg1.sw_if_index,
424 self.pg1._remote_hosts[4].ip4))
425 self.assertFalse(find_route(self,
426 self.pg1._remote_hosts[4].ip4,
429 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
430 # from within pg1's subnet
432 arp_unnum = VppNeighbor(self,
433 self.pg2.sw_if_index,
434 self.pg1.remote_hosts[5].mac,
435 self.pg1.remote_hosts[5].ip4)
436 arp_unnum.add_vpp_config()
438 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
439 IP(src=self.pg0.remote_ip4,
440 dst=self.pg1._remote_hosts[5].ip4) /
441 UDP(sport=1234, dport=1234) /
444 self.pg0.add_stream(p)
445 self.pg_enable_capture(self.pg_interfaces)
448 rx = self.pg2.get_capture(1)
450 self.verify_ip(rx[0],
452 self.pg1.remote_hosts[5].mac,
454 self.pg1._remote_hosts[5].ip4)
457 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
458 # with the unnumbered interface's address as the source
460 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
462 hwsrc=self.pg2.remote_mac,
463 pdst=self.pg1.local_ip4,
464 psrc=self.pg1.remote_hosts[6].ip4))
466 self.pg2.add_stream(p)
467 self.pg_enable_capture(self.pg_interfaces)
470 rx = self.pg2.get_capture(1)
471 self.verify_arp_resp(rx[0],
475 self.pg1.remote_hosts[6].ip4)
478 # An attached host route out of pg2 for an undiscovered hosts generates
479 # an ARP request with the unnumbered address as the source
481 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
482 [VppRoutePath("0.0.0.0",
483 self.pg2.sw_if_index)])
484 att_unnum.add_vpp_config()
486 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
487 IP(src=self.pg0.remote_ip4,
488 dst=self.pg1._remote_hosts[7].ip4) /
489 UDP(sport=1234, dport=1234) /
492 self.pg0.add_stream(p)
493 self.pg_enable_capture(self.pg_interfaces)
496 rx = self.pg2.get_capture(1)
498 self.verify_arp_req(rx[0],
501 self.pg1._remote_hosts[7].ip4)
503 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
505 hwsrc=self.pg2.remote_mac,
506 pdst=self.pg1.local_ip4,
507 psrc=self.pg1.remote_hosts[7].ip4))
509 self.pg2.add_stream(p)
510 self.pg_enable_capture(self.pg_interfaces)
513 rx = self.pg2.get_capture(1)
514 self.verify_arp_resp(rx[0],
518 self.pg1.remote_hosts[7].ip4)
521 # An attached host route as yet unresolved out of pg2 for an
522 # undiscovered host, an ARP requests begets a response.
524 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
525 [VppRoutePath("0.0.0.0",
526 self.pg2.sw_if_index)])
527 att_unnum1.add_vpp_config()
529 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
531 hwsrc=self.pg2.remote_mac,
532 pdst=self.pg1.local_ip4,
533 psrc=self.pg1.remote_hosts[8].ip4))
535 self.pg2.add_stream(p)
536 self.pg_enable_capture(self.pg_interfaces)
539 rx = self.pg2.get_capture(1)
540 self.verify_arp_resp(rx[0],
544 self.pg1.remote_hosts[8].ip4)
547 # Send an ARP request from one of the so-far unlearned remote hosts
550 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
551 src=self.pg1._remote_hosts[9].mac) /
554 hwsrc=self.pg1._remote_hosts[9].mac,
555 pdst=self.pg1.local_ip4,
556 psrc=self.pg1._remote_hosts[9].ip4))
558 self.pg1.add_stream(p)
559 self.pg_enable_capture(self.pg_interfaces)
562 rx = self.pg1.get_capture(1)
563 self.verify_arp_resp(rx[0],
565 self.pg1._remote_hosts[9].mac,
567 self.pg1._remote_hosts[9].ip4)
570 # Add a hierarchy of routes for a host in the sub-net.
571 # Should still get an ARP resp since the cover is attached
573 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
575 hwsrc=self.pg1.remote_mac,
576 pdst=self.pg1.local_ip4,
577 psrc=self.pg1.remote_hosts[10].ip4))
579 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
580 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
581 self.pg1.sw_if_index)])
584 self.pg1.add_stream(p)
585 self.pg_enable_capture(self.pg_interfaces)
587 rx = self.pg1.get_capture(1)
588 self.verify_arp_resp(rx[0],
592 self.pg1.remote_hosts[10].ip4)
594 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
595 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
596 self.pg1.sw_if_index)])
599 self.pg1.add_stream(p)
600 self.pg_enable_capture(self.pg_interfaces)
602 rx = self.pg1.get_capture(1)
603 self.verify_arp_resp(rx[0],
607 self.pg1.remote_hosts[10].ip4)
610 # add an ARP entry that's not on the sub-net and so whose
611 # adj-fib fails the refinement check. then send an ARP request
614 a1 = VppNeighbor(self,
615 self.pg0.sw_if_index,
620 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
622 hwsrc=self.pg0.remote_mac,
623 psrc="100.100.100.50",
624 pdst=self.pg0.remote_ip4))
625 self.send_and_assert_no_replies(self.pg0, p,
626 "ARP req for from failed adj-fib")
630 # 1 - don't respond to ARP request for address not within the
631 # interface's sub-net
632 # 1b - nor within the unnumbered subnet
633 # 1c - nor within the subnet of a different interface
635 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
637 hwsrc=self.pg0.remote_mac,
639 psrc=self.pg0.remote_ip4))
640 self.send_and_assert_no_replies(self.pg0, p,
641 "ARP req for non-local destination")
642 self.assertFalse(find_nbr(self,
643 self.pg0.sw_if_index,
646 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
648 hwsrc=self.pg2.remote_mac,
650 psrc=self.pg1.remote_hosts[7].ip4))
651 self.send_and_assert_no_replies(
653 "ARP req for non-local destination - unnum")
655 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
657 hwsrc=self.pg0.remote_mac,
658 pdst=self.pg1.local_ip4,
659 psrc=self.pg1.remote_ip4))
660 self.send_and_assert_no_replies(self.pg0, p,
661 "ARP req diff sub-net")
662 self.assertFalse(find_nbr(self,
663 self.pg0.sw_if_index,
664 self.pg1.remote_ip4))
667 # 2 - don't respond to ARP request from an address not within the
668 # interface's sub-net
669 # 2b - to a proxied address
670 # 2c - not within a different interface's sub-net
671 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
673 hwsrc=self.pg0.remote_mac,
675 pdst=self.pg0.local_ip4))
676 self.send_and_assert_no_replies(self.pg0, p,
677 "ARP req for non-local source")
678 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
680 hwsrc=self.pg2.remote_mac,
682 pdst=self.pg0.local_ip4))
683 self.send_and_assert_no_replies(
685 "ARP req for non-local source - unnum")
686 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
688 hwsrc=self.pg0.remote_mac,
689 psrc=self.pg1.remote_ip4,
690 pdst=self.pg0.local_ip4))
691 self.send_and_assert_no_replies(self.pg0, p,
692 "ARP req for non-local source 2c")
695 # 3 - don't respond to ARP request from an address that belongs to
698 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
700 hwsrc=self.pg0.remote_mac,
701 psrc=self.pg0.local_ip4,
702 pdst=self.pg0.local_ip4))
703 self.send_and_assert_no_replies(self.pg0, p,
704 "ARP req for non-local source")
707 # 4 - don't respond to ARP requests that has mac source different
708 # from ARP request HW source
710 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
712 hwsrc="00:00:00:DE:AD:BE",
713 psrc=self.pg0.remote_ip4,
714 pdst=self.pg0.local_ip4))
715 self.send_and_assert_no_replies(self.pg0, p,
716 "ARP req for non-local source")
719 # 5 - don't respond to ARP requests for address within the
720 # interface's sub-net but not the interface's address
722 self.pg0.generate_remote_hosts(2)
723 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
725 hwsrc=self.pg0.remote_mac,
726 psrc=self.pg0.remote_hosts[0].ip4,
727 pdst=self.pg0.remote_hosts[1].ip4))
728 self.send_and_assert_no_replies(self.pg0, p,
729 "ARP req for non-local destination")
734 static_arp.remove_vpp_config()
735 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
737 # need this to flush the adj-fibs
738 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
739 self.pg2.admin_down()
740 self.pg1.admin_down()
742 def test_proxy_mirror_arp(self):
743 """ Interface Mirror Proxy ARP """
746 # When VPP has an interface whose address is also applied to a TAP
747 # interface on the host, then VPP's TAP interface will be unnumbered
748 # to the 'real' interface and do proxy ARP from the host.
749 # the curious aspect of this setup is that ARP requests from the host
750 # will come from the VPP's own address.
752 self.pg0.generate_remote_hosts(2)
754 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
755 dst="ff:ff:ff:ff:ff:ff") /
757 hwsrc=self.pg2.remote_mac,
758 pdst=self.pg0.remote_hosts[1].ip4,
759 psrc=self.pg0.local_ip4))
762 # Configure Proxy ARP for the subnet on PG0addresses on pg0
764 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
765 self.pg0._local_ip4_bcast)
767 # Make pg2 un-numbered to pg0
769 self.pg2.set_unnumbered(self.pg0.sw_if_index)
772 # Enable pg2 for proxy ARP
774 self.pg2.set_proxy_arp()
777 # Send the ARP request with an originating address that
778 # is VPP's own address
780 self.pg2.add_stream(arp_req_from_me)
781 self.pg_enable_capture(self.pg_interfaces)
784 rx = self.pg2.get_capture(1)
785 self.verify_arp_resp(rx[0],
788 self.pg0.remote_hosts[1].ip4,
792 # validate we have not learned an ARP entry as a result of this
794 self.assertFalse(find_nbr(self,
795 self.pg2.sw_if_index,
801 self.pg2.set_proxy_arp(0)
802 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
803 self.pg0._local_ip4_bcast,
806 def test_proxy_arp(self):
809 self.pg1.generate_remote_hosts(2)
812 # Proxy ARP request packets for each interface
814 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
815 dst="ff:ff:ff:ff:ff:ff") /
817 hwsrc=self.pg0.remote_mac,
819 psrc=self.pg0.remote_ip4))
820 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
821 dst="ff:ff:ff:ff:ff:ff") /
824 hwsrc=self.pg0.remote_mac,
826 psrc=self.pg0.remote_ip4))
827 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
828 dst="ff:ff:ff:ff:ff:ff") /
830 hwsrc=self.pg1.remote_mac,
832 psrc=self.pg1.remote_ip4))
833 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
834 dst="ff:ff:ff:ff:ff:ff") /
836 hwsrc=self.pg2.remote_mac,
838 psrc=self.pg1.remote_hosts[1].ip4))
839 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
840 dst="ff:ff:ff:ff:ff:ff") /
842 hwsrc=self.pg3.remote_mac,
844 psrc=self.pg3.remote_ip4))
847 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
849 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
850 inet_pton(AF_INET, "10.10.10.124"))
853 # No responses are sent when the interfaces are not enabled for proxy
856 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
857 "ARP req from unconfigured interface")
858 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
859 "ARP req from unconfigured interface")
862 # Make pg2 un-numbered to pg1
865 self.pg2.set_unnumbered(self.pg1.sw_if_index)
867 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
868 "ARP req from unnumbered interface")
871 # Enable each interface to reply to proxy ARPs
873 for i in self.pg_interfaces:
877 # Now each of the interfaces should reply to a request to a proxied
880 self.pg0.add_stream(arp_req_pg0)
881 self.pg_enable_capture(self.pg_interfaces)
884 rx = self.pg0.get_capture(1)
885 self.verify_arp_resp(rx[0],
891 self.pg0.add_stream(arp_req_pg0_tagged)
892 self.pg_enable_capture(self.pg_interfaces)
895 rx = self.pg0.get_capture(1)
896 self.verify_arp_resp(rx[0],
902 self.pg1.add_stream(arp_req_pg1)
903 self.pg_enable_capture(self.pg_interfaces)
906 rx = self.pg1.get_capture(1)
907 self.verify_arp_resp(rx[0],
913 self.pg2.add_stream(arp_req_pg2)
914 self.pg_enable_capture(self.pg_interfaces)
917 rx = self.pg2.get_capture(1)
918 self.verify_arp_resp(rx[0],
922 self.pg1.remote_hosts[1].ip4)
925 # A request for an address out of the configured range
927 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
928 dst="ff:ff:ff:ff:ff:ff") /
930 hwsrc=self.pg1.remote_mac,
932 psrc=self.pg1.remote_ip4))
933 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
934 "ARP req out of range HI")
935 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
936 dst="ff:ff:ff:ff:ff:ff") /
938 hwsrc=self.pg1.remote_mac,
940 psrc=self.pg1.remote_ip4))
941 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
942 "ARP req out of range Low")
945 # Request for an address in the proxy range but from an interface
948 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
949 "ARP req from different VRF")
952 # Disable Each interface for proxy ARP
953 # - expect none to respond
955 for i in self.pg_interfaces:
958 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
959 "ARP req from disable")
960 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
961 "ARP req from disable")
962 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
963 "ARP req from disable")
966 # clean up on interface 2
968 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
974 # Interface 2 does not yet have ip4 config
976 self.pg2.config_ip4()
977 self.pg2.generate_remote_hosts(2)
980 # Add a route with out going label via an ARP unresolved next-hop
982 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
983 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
984 self.pg2.sw_if_index,
986 ip_10_0_0_1.add_vpp_config()
989 # packets should generate an ARP request
991 p = (Ether(src=self.pg0.remote_mac,
992 dst=self.pg0.local_mac) /
993 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
994 UDP(sport=1234, dport=1234) /
997 self.pg0.add_stream(p)
998 self.pg_enable_capture(self.pg_interfaces)
1001 rx = self.pg2.get_capture(1)
1002 self.verify_arp_req(rx[0],
1005 self.pg2._remote_hosts[1].ip4)
1008 # now resolve the neighbours
1010 self.pg2.configure_ipv4_neighbors()
1013 # Now packet should be properly MPLS encapped.
1014 # This verifies that MPLS link-type adjacencies are completed
1015 # when the ARP entry resolves
1017 self.pg0.add_stream(p)
1018 self.pg_enable_capture(self.pg_interfaces)
1021 rx = self.pg2.get_capture(1)
1022 self.verify_ip_o_mpls(rx[0],
1024 self.pg2.remote_hosts[1].mac,
1026 self.pg0.remote_ip4,
1028 self.pg2.unconfig_ip4()
1030 def test_arp_vrrp(self):
1031 """ ARP reply with VRRP virtual src hw addr """
1034 # IP packet destined for pg1 remote host arrives on pg0 resulting
1035 # in an ARP request for the address of the remote host on pg1
1037 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1038 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1039 UDP(sport=1234, dport=1234) /
1042 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
1044 self.verify_arp_req(rx1[0],
1047 self.pg1.remote_ip4)
1050 # ARP reply for address of pg1 remote host arrives on pg1 with
1051 # the hw src addr set to a value in the VRRP IPv4 range of
1054 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1055 ARP(op="is-at", hwdst=self.pg1.local_mac,
1056 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1057 psrc=self.pg1.remote_ip4))
1059 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1062 # IP packet destined for pg1 remote host arrives on pg0 again.
1063 # VPP should have an ARP entry for that address now and the packet
1064 # should be sent out pg1.
1066 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
1068 self.verify_ip(rx1[0],
1070 "00:00:5e:00:01:09",
1071 self.pg0.remote_ip4,
1072 self.pg1.remote_ip4)
1074 self.pg1.admin_down()
1077 def test_arp_duplicates(self):
1078 """ ARP Duplicates"""
1081 # Generate some hosts on the LAN
1083 self.pg1.generate_remote_hosts(3)
1086 # Add host 1 on pg1 and pg2
1088 arp_pg1 = VppNeighbor(self,
1089 self.pg1.sw_if_index,
1090 self.pg1.remote_hosts[1].mac,
1091 self.pg1.remote_hosts[1].ip4)
1092 arp_pg1.add_vpp_config()
1093 arp_pg2 = VppNeighbor(self,
1094 self.pg2.sw_if_index,
1095 self.pg2.remote_mac,
1096 self.pg1.remote_hosts[1].ip4)
1097 arp_pg2.add_vpp_config()
1100 # IP packet destined for pg1 remote host arrives on pg1 again.
1102 p = (Ether(dst=self.pg0.local_mac,
1103 src=self.pg0.remote_mac) /
1104 IP(src=self.pg0.remote_ip4,
1105 dst=self.pg1.remote_hosts[1].ip4) /
1106 UDP(sport=1234, dport=1234) /
1109 self.pg0.add_stream(p)
1110 self.pg_enable_capture(self.pg_interfaces)
1113 rx1 = self.pg1.get_capture(1)
1115 self.verify_ip(rx1[0],
1117 self.pg1.remote_hosts[1].mac,
1118 self.pg0.remote_ip4,
1119 self.pg1.remote_hosts[1].ip4)
1122 # remove the duplicate on pg1
1123 # packet stream should generate ARPs out of pg1
1125 arp_pg1.remove_vpp_config()
1127 self.pg0.add_stream(p)
1128 self.pg_enable_capture(self.pg_interfaces)
1131 rx1 = self.pg1.get_capture(1)
1133 self.verify_arp_req(rx1[0],
1136 self.pg1.remote_hosts[1].ip4)
1141 arp_pg1.add_vpp_config()
1143 self.pg0.add_stream(p)
1144 self.pg_enable_capture(self.pg_interfaces)
1147 rx1 = self.pg1.get_capture(1)
1149 self.verify_ip(rx1[0],
1151 self.pg1.remote_hosts[1].mac,
1152 self.pg0.remote_ip4,
1153 self.pg1.remote_hosts[1].ip4)
1155 def test_arp_static(self):
1157 self.pg2.generate_remote_hosts(3)
1160 # Add a static ARP entry
1162 static_arp = VppNeighbor(self,
1163 self.pg2.sw_if_index,
1164 self.pg2.remote_hosts[1].mac,
1165 self.pg2.remote_hosts[1].ip4,
1167 static_arp.add_vpp_config()
1170 # Add the connected prefix to the interface
1172 self.pg2.config_ip4()
1175 # We should now find the adj-fib
1177 self.assertTrue(find_nbr(self,
1178 self.pg2.sw_if_index,
1179 self.pg2.remote_hosts[1].ip4,
1181 self.assertTrue(find_route(self,
1182 self.pg2.remote_hosts[1].ip4,
1186 # remove the connected
1188 self.pg2.unconfig_ip4()
1191 # put the interface into table 1
1193 self.pg2.set_table_ip4(1)
1196 # configure the same connected and expect to find the
1197 # adj fib in the new table
1199 self.pg2.config_ip4()
1200 self.assertTrue(find_route(self,
1201 self.pg2.remote_hosts[1].ip4,
1208 self.pg2.unconfig_ip4()
1209 static_arp.remove_vpp_config()
1210 self.pg2.set_table_ip4(0)
1212 def test_arp_incomplete(self):
1213 """ ARP Incomplete"""
1214 self.pg1.generate_remote_hosts(3)
1216 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1217 IP(src=self.pg0.remote_ip4,
1218 dst=self.pg1.remote_hosts[1].ip4) /
1219 UDP(sport=1234, dport=1234) /
1221 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1222 IP(src=self.pg0.remote_ip4,
1223 dst=self.pg1.remote_hosts[2].ip4) /
1224 UDP(sport=1234, dport=1234) /
1228 # a packet to an unresolved destination generates an ARP request
1230 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1231 self.verify_arp_req(rx[0],
1234 self.pg1._remote_hosts[1].ip4)
1237 # add a neighbour for remote host 1
1239 static_arp = VppNeighbor(self,
1240 self.pg1.sw_if_index,
1241 self.pg1.remote_hosts[1].mac,
1242 self.pg1.remote_hosts[1].ip4,
1244 static_arp.add_vpp_config()
1247 # change the interface's MAC
1249 mac = [scapy.compat.chb(0x00), scapy.compat.chb(0x00),
1250 scapy.compat.chb(0x00), scapy.compat.chb(0x33),
1251 scapy.compat.chb(0x33), scapy.compat.chb(0x33)]
1252 mac_string = ''.join(mac)
1254 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1258 # now ARP requests come from the new source mac
1260 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1261 self.verify_arp_req(rx[0],
1262 "00:00:00:33:33:33",
1264 self.pg1._remote_hosts[2].ip4)
1267 # packets to the resolved host also have the new source mac
1269 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1270 self.verify_ip(rx[0],
1271 "00:00:00:33:33:33",
1272 self.pg1.remote_hosts[1].mac,
1273 self.pg0.remote_ip4,
1274 self.pg1.remote_hosts[1].ip4)
1277 # set the mac address on the interface that does not have a
1278 # configured subnet and thus no glean
1280 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1283 def test_garp(self):
1287 # Generate some hosts on the LAN
1289 self.pg1.generate_remote_hosts(4)
1294 arp = VppNeighbor(self,
1295 self.pg1.sw_if_index,
1296 self.pg1.remote_hosts[1].mac,
1297 self.pg1.remote_hosts[1].ip4)
1298 arp.add_vpp_config()
1300 self.assertTrue(find_nbr(self,
1301 self.pg1.sw_if_index,
1302 self.pg1.remote_hosts[1].ip4,
1303 mac=self.pg1.remote_hosts[1].mac))
1306 # Send a GARP (request) to swap the host 1's address to that of host 2
1308 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1309 src=self.pg1.remote_hosts[2].mac) /
1311 hwdst=self.pg1.local_mac,
1312 hwsrc=self.pg1.remote_hosts[2].mac,
1313 pdst=self.pg1.remote_hosts[1].ip4,
1314 psrc=self.pg1.remote_hosts[1].ip4))
1316 self.pg1.add_stream(p1)
1317 self.pg_enable_capture(self.pg_interfaces)
1320 self.assertTrue(find_nbr(self,
1321 self.pg1.sw_if_index,
1322 self.pg1.remote_hosts[1].ip4,
1323 mac=self.pg1.remote_hosts[2].mac))
1326 # Send a GARP (reply) to swap the host 1's address to that of host 3
1328 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1329 src=self.pg1.remote_hosts[3].mac) /
1331 hwdst=self.pg1.local_mac,
1332 hwsrc=self.pg1.remote_hosts[3].mac,
1333 pdst=self.pg1.remote_hosts[1].ip4,
1334 psrc=self.pg1.remote_hosts[1].ip4))
1336 self.pg1.add_stream(p1)
1337 self.pg_enable_capture(self.pg_interfaces)
1340 self.assertTrue(find_nbr(self,
1341 self.pg1.sw_if_index,
1342 self.pg1.remote_hosts[1].ip4,
1343 mac=self.pg1.remote_hosts[3].mac))
1346 # GARPs (request nor replies) for host we don't know yet
1347 # don't result in new neighbour entries
1349 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1350 src=self.pg1.remote_hosts[3].mac) /
1352 hwdst=self.pg1.local_mac,
1353 hwsrc=self.pg1.remote_hosts[3].mac,
1354 pdst=self.pg1.remote_hosts[2].ip4,
1355 psrc=self.pg1.remote_hosts[2].ip4))
1357 self.pg1.add_stream(p1)
1358 self.pg_enable_capture(self.pg_interfaces)
1361 self.assertFalse(find_nbr(self,
1362 self.pg1.sw_if_index,
1363 self.pg1.remote_hosts[2].ip4))
1365 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1366 src=self.pg1.remote_hosts[3].mac) /
1368 hwdst=self.pg1.local_mac,
1369 hwsrc=self.pg1.remote_hosts[3].mac,
1370 pdst=self.pg1.remote_hosts[2].ip4,
1371 psrc=self.pg1.remote_hosts[2].ip4))
1373 self.pg1.add_stream(p1)
1374 self.pg_enable_capture(self.pg_interfaces)
1377 self.assertFalse(find_nbr(self,
1378 self.pg1.sw_if_index,
1379 self.pg1.remote_hosts[2].ip4))
1381 def test_arp_incomplete(self):
1382 """ Incomplete Entries """
1385 # ensure that we throttle the ARP and ND requests
1387 self.pg0.generate_remote_hosts(2)
1392 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1393 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
1394 self.pg0.sw_if_index)])
1395 ip_10_0_0_1.add_vpp_config()
1397 p1 = (Ether(dst=self.pg1.local_mac,
1398 src=self.pg1.remote_mac) /
1399 IP(src=self.pg1.remote_ip4,
1401 UDP(sport=1234, dport=1234) /
1404 self.pg1.add_stream(p1 * 257)
1405 self.pg_enable_capture(self.pg_interfaces)
1407 rx = self.pg0._get_capture(1)
1410 # how many we get is going to be dependent on the time for packet
1411 # processing but it should be small
1413 self.assertLess(len(rx), 64)
1418 ip_10_1 = VppIpRoute(self, "10::1", 128,
1419 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1420 self.pg0.sw_if_index,
1421 proto=DpoProto.DPO_PROTO_IP6)])
1422 ip_10_1.add_vpp_config()
1424 p1 = (Ether(dst=self.pg1.local_mac,
1425 src=self.pg1.remote_mac) /
1426 IPv6(src=self.pg1.remote_ip6,
1428 UDP(sport=1234, dport=1234) /
1431 self.pg1.add_stream(p1 * 257)
1432 self.pg_enable_capture(self.pg_interfaces)
1434 rx = self.pg0._get_capture(1)
1437 # how many we get is going to be dependent on the time for packet
1438 # processing but it should be small
1440 self.assertLess(len(rx), 64)
1442 def test_arp_forus(self):
1443 """ ARP for for-us """
1446 # Test that VPP responds with ARP requests to addresses that
1447 # are connected and local routes.
1448 # Use one of the 'remote' addresses in the subnet as a local address
1449 # The intention of this route is that it then acts like a secondary
1450 # address added to an interface
1452 self.pg0.generate_remote_hosts(2)
1455 self, self.pg0.remote_hosts[1].ip4, 32,
1456 [VppRoutePath("0.0.0.0",
1457 self.pg0.sw_if_index,
1458 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
1459 forus.add_vpp_config()
1461 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1462 src=self.pg0.remote_mac) /
1464 hwdst=self.pg0.local_mac,
1465 hwsrc=self.pg0.remote_mac,
1466 pdst=self.pg0.remote_hosts[1].ip4,
1467 psrc=self.pg0.remote_ip4))
1469 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1471 self.verify_arp_resp(rx[0],
1473 self.pg0.remote_mac,
1474 self.pg0.remote_hosts[1].ip4,
1475 self.pg0.remote_ip4)
1477 def test_arp_table_swap(self):
1479 # Generate some hosts on the LAN
1482 self.pg1.generate_remote_hosts(N_NBRS)
1484 for n in range(N_NBRS):
1485 # a route thru each neighbour
1486 VppIpRoute(self, "10.0.0.%d" % n, 32,
1487 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1488 self.pg1.sw_if_index)]).add_vpp_config()
1490 # resolve each neighbour
1491 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1492 ARP(op="is-at", hwdst=self.pg1.local_mac,
1493 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1494 psrc=self.pg1.remote_hosts[n].ip4))
1496 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1498 self.logger.info(self.vapi.cli("sh ip neighbors"))
1501 # swap the table pg1 is in
1503 table = VppIpTable(self, 100).add_vpp_config()
1505 self.pg1.unconfig_ip4()
1506 self.pg1.set_table_ip4(100)
1507 self.pg1.config_ip4()
1510 # all neighbours are cleared
1512 for n in range(N_NBRS):
1513 self.assertFalse(find_nbr(self,
1514 self.pg1.sw_if_index,
1515 self.pg1.remote_hosts[n].ip4))
1518 # packets to all neighbours generate ARP requests
1520 for n in range(N_NBRS):
1521 # a route thru each neighbour
1522 VppIpRoute(self, "10.0.0.%d" % n, 32,
1523 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1524 self.pg1.sw_if_index)],
1525 table_id=100).add_vpp_config()
1527 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1528 dst=self.pg1.local_mac) /
1529 IP(src=self.pg1.remote_hosts[n].ip4,
1530 dst="10.0.0.%d" % n) /
1532 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1534 self.verify_arp_req(rx,
1537 self.pg1.remote_hosts[n].ip4)
1539 self.pg1.unconfig_ip4()
1540 self.pg1.set_table_ip4(0)
1543 class NeighborStatsTestCase(VppTestCase):
1544 """ ARP/ND Counters """
1547 def setUpClass(cls):
1548 super(NeighborStatsTestCase, cls).setUpClass()
1551 def tearDownClass(cls):
1552 super(NeighborStatsTestCase, cls).tearDownClass()
1555 super(NeighborStatsTestCase, self).setUp()
1557 self.create_pg_interfaces(range(2))
1559 # pg0 configured with ip4 and 6 addresses used for input
1560 # pg1 configured with ip4 and 6 addresses used for output
1561 # pg2 is unnumbered to pg0
1562 for i in self.pg_interfaces:
1570 super(NeighborStatsTestCase, self).tearDown()
1572 for i in self.pg_interfaces:
1577 def test_arp_stats(self):
1578 """ ARP Counters """
1580 self.vapi.cli("adj counters enable")
1581 self.pg1.generate_remote_hosts(2)
1583 arp1 = VppNeighbor(self,
1584 self.pg1.sw_if_index,
1585 self.pg1.remote_hosts[0].mac,
1586 self.pg1.remote_hosts[0].ip4)
1587 arp1.add_vpp_config()
1588 arp2 = VppNeighbor(self,
1589 self.pg1.sw_if_index,
1590 self.pg1.remote_hosts[1].mac,
1591 self.pg1.remote_hosts[1].ip4)
1592 arp2.add_vpp_config()
1594 p1 = (Ether(dst=self.pg0.local_mac,
1595 src=self.pg0.remote_mac) /
1596 IP(src=self.pg0.remote_ip4,
1597 dst=self.pg1.remote_hosts[0].ip4) /
1598 UDP(sport=1234, dport=1234) /
1600 p2 = (Ether(dst=self.pg0.local_mac,
1601 src=self.pg0.remote_mac) /
1602 IP(src=self.pg0.remote_ip4,
1603 dst=self.pg1.remote_hosts[1].ip4) /
1604 UDP(sport=1234, dport=1234) /
1607 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1608 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
1610 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1611 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
1613 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1614 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
1616 def test_nd_stats(self):
1619 self.vapi.cli("adj counters enable")
1620 self.pg0.generate_remote_hosts(3)
1622 nd1 = VppNeighbor(self,
1623 self.pg0.sw_if_index,
1624 self.pg0.remote_hosts[1].mac,
1625 self.pg0.remote_hosts[1].ip6)
1626 nd1.add_vpp_config()
1627 nd2 = VppNeighbor(self,
1628 self.pg0.sw_if_index,
1629 self.pg0.remote_hosts[2].mac,
1630 self.pg0.remote_hosts[2].ip6)
1631 nd2.add_vpp_config()
1633 p1 = (Ether(dst=self.pg1.local_mac,
1634 src=self.pg1.remote_mac) /
1635 IPv6(src=self.pg1.remote_ip6,
1636 dst=self.pg0.remote_hosts[1].ip6) /
1637 UDP(sport=1234, dport=1234) /
1639 p2 = (Ether(dst=self.pg1.local_mac,
1640 src=self.pg1.remote_mac) /
1641 IPv6(src=self.pg1.remote_ip6,
1642 dst=self.pg0.remote_hosts[2].ip6) /
1643 UDP(sport=1234, dport=1234) /
1646 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1647 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1649 self.assertEqual(16, nd1.get_stats()['packets'])
1650 self.assertEqual(16, nd2.get_stats()['packets'])
1652 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1653 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
1656 class NeighborAgeTestCase(VppTestCase):
1657 """ ARP/ND Aging """
1660 def setUpClass(cls):
1661 super(NeighborAgeTestCase, cls).setUpClass()
1664 def tearDownClass(cls):
1665 super(NeighborAgeTestCase, cls).tearDownClass()
1668 super(NeighborAgeTestCase, self).setUp()
1670 self.create_pg_interfaces(range(1))
1672 # pg0 configured with ip4 and 6 addresses used for input
1673 # pg1 configured with ip4 and 6 addresses used for output
1674 # pg2 is unnumbered to pg0
1675 for i in self.pg_interfaces:
1683 super(NeighborAgeTestCase, self).tearDown()
1685 for i in self.pg_interfaces:
1690 def wait_for_no_nbr(self, intf, address,
1691 n_tries=50, s_time=1):
1693 if not find_nbr(self, intf, address):
1695 n_tries = n_tries - 1
1700 def verify_arp_req(self, rx, smac, sip, dip):
1702 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1703 self.assertEqual(ether.src, smac)
1706 self.assertEqual(arp.hwtype, 1)
1707 self.assertEqual(arp.ptype, 0x800)
1708 self.assertEqual(arp.hwlen, 6)
1709 self.assertEqual(arp.plen, 4)
1710 self.assertEqual(arp.op, arp_opts["who-has"])
1711 self.assertEqual(arp.hwsrc, smac)
1712 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
1713 self.assertEqual(arp.psrc, sip)
1714 self.assertEqual(arp.pdst, dip)
1717 """ Aging/Recycle """
1719 self.vapi.cli("set logging unthrottle 0")
1720 self.vapi.cli("set logging size %d" % 0xffff)
1722 self.pg0.generate_remote_hosts(201)
1724 vaf = VppEnum.vl_api_address_family_t
1727 # start listening on all interfaces
1729 self.pg_enable_capture(self.pg_interfaces)
1732 # Set the neighbor configuration:
1737 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1742 self.vapi.cli("sh ip neighbor-config")
1744 # add the 198 neighbours that should pass (-1 for one created in setup)
1745 for ii in range(200):
1747 self.pg0.sw_if_index,
1748 self.pg0.remote_hosts[ii].mac,
1749 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1751 # one more neighbor over the limit should fail
1752 with self.vapi.assert_negative_api_retval():
1754 self.pg0.sw_if_index,
1755 self.pg0.remote_hosts[200].mac,
1756 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1759 # change the config to allow recycling the old neighbors
1761 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1766 # now new additions are allowed
1768 self.pg0.sw_if_index,
1769 self.pg0.remote_hosts[200].mac,
1770 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1772 # add the first neighbor we configured has been re-used
1773 self.assertFalse(find_nbr(self,
1774 self.pg0.sw_if_index,
1775 self.pg0.remote_hosts[0].ip4))
1776 self.assertTrue(find_nbr(self,
1777 self.pg0.sw_if_index,
1778 self.pg0.remote_hosts[200].ip4))
1781 # change the config to age old neighbors
1783 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1788 self.vapi.cli("sh ip4 neighbor-sorted")
1791 # expect probes from all these ARP entries as they age
1792 # 3 probes for each neighbor 3*200 = 600
1793 rxs = self.pg0.get_capture(600, timeout=8)
1796 for jj in range(200):
1797 rx = rxs[ii*200 + jj]
1801 # 3 probes sent then 1 more second to see if a reply comes, before
1804 for jj in range(1, 201):
1805 self.wait_for_no_nbr(self.pg0.sw_if_index,
1806 self.pg0.remote_hosts[jj].ip4)
1808 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1809 af=vaf.ADDRESS_IP4))
1812 # load up some neighbours again with 2s aging enabled
1813 # they should be removed after 10s (2s age + 4s for probes + gap)
1815 for ii in range(10):
1817 self.pg0.sw_if_index,
1818 self.pg0.remote_hosts[ii].mac,
1819 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1821 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1822 af=vaf.ADDRESS_IP4))
1825 # check if we can set age and recycle with empty neighbor list
1827 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1833 # load up some neighbours again, then disable the aging
1834 # they should still be there in 10 seconds time
1836 for ii in range(10):
1838 self.pg0.sw_if_index,
1839 self.pg0.remote_hosts[ii].mac,
1840 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1841 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1847 self.assertTrue(find_nbr(self,
1848 self.pg0.sw_if_index,
1849 self.pg0.remote_hosts[0].ip4))
1852 if __name__ == '__main__':
1853 unittest.main(testRunner=VppTestRunner)