4 from socket import AF_INET, AF_INET6, inet_pton
6 from framework import VppTestCase, VppTestRunner
7 from vpp_neighbor import VppNeighbor, find_nbr
8 from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
11 from scapy.packet import Raw
12 from scapy.layers.l2 import Ether, ARP, Dot1Q
13 from scapy.layers.inet import IP, UDP
14 from scapy.contrib.mpls import MPLS
16 # not exported by scapy, so redefined here
17 arp_opts = {"who-has": 1, "is-at": 2}
20 class ARPTestCase(VppTestCase):
24 super(ARPTestCase, self).setUp()
26 # create 3 pg interfaces
27 self.create_pg_interfaces(range(4))
29 # pg0 configured with ip4 and 6 addresses used for input
30 # pg1 configured with ip4 and 6 addresses used for output
31 # pg2 is unnumbered to pg0
32 for i in self.pg_interfaces:
37 self.pg0.resolve_arp()
42 # pg3 in a different VRF
43 self.tbl = VppIpTable(self, 1)
44 self.tbl.add_vpp_config()
46 self.pg3.set_table_ip4(1)
50 self.pg0.unconfig_ip4()
51 self.pg0.unconfig_ip6()
53 self.pg1.unconfig_ip4()
54 self.pg1.unconfig_ip6()
56 self.pg3.unconfig_ip4()
57 self.pg3.set_table_ip4(0)
59 for i in self.pg_interfaces:
62 super(ARPTestCase, self).tearDown()
64 def verify_arp_req(self, rx, smac, sip, dip):
66 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
67 self.assertEqual(ether.src, smac)
70 self.assertEqual(arp.hwtype, 1)
71 self.assertEqual(arp.ptype, 0x800)
72 self.assertEqual(arp.hwlen, 6)
73 self.assertEqual(arp.plen, 4)
74 self.assertEqual(arp.op, arp_opts["who-has"])
75 self.assertEqual(arp.hwsrc, smac)
76 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
77 self.assertEqual(arp.psrc, sip)
78 self.assertEqual(arp.pdst, dip)
80 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
82 self.assertEqual(ether.dst, dmac)
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["is-at"])
91 self.assertEqual(arp.hwsrc, smac)
92 self.assertEqual(arp.hwdst, dmac)
93 self.assertEqual(arp.psrc, sip)
94 self.assertEqual(arp.pdst, dip)
96 def verify_arp_vrrp_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.assertNotEqual(arp.hwsrc, smac)
108 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
109 "00:00:5E:00:01" in arp.hwsrc)
110 self.assertEqual(arp.hwdst, dmac)
111 self.assertEqual(arp.psrc, sip)
112 self.assertEqual(arp.pdst, dip)
114 def verify_ip(self, rx, smac, dmac, sip, dip):
116 self.assertEqual(ether.dst, dmac)
117 self.assertEqual(ether.src, smac)
120 self.assertEqual(ip.src, sip)
121 self.assertEqual(ip.dst, dip)
123 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
125 self.assertEqual(ether.dst, dmac)
126 self.assertEqual(ether.src, smac)
129 self.assertTrue(mpls.label, label)
132 self.assertEqual(ip.src, sip)
133 self.assertEqual(ip.dst, dip)
135 def send_and_assert_no_replies(self, intf, pkts, remark):
136 intf.add_stream(pkts)
137 self.pg_enable_capture(self.pg_interfaces)
140 for i in self.pg_interfaces:
141 i.get_capture(0, timeout=timeout)
142 i.assert_nothing_captured(remark=remark)
149 # Generate some hosts on the LAN
151 self.pg1.generate_remote_hosts(11)
154 # Send IP traffic to one of these unresolved hosts.
155 # expect the generation of an ARP request
157 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
158 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
159 UDP(sport=1234, dport=1234) /
162 self.pg0.add_stream(p)
163 self.pg_enable_capture(self.pg_interfaces)
166 rx = self.pg1.get_capture(1)
168 self.verify_arp_req(rx[0],
171 self.pg1._remote_hosts[1].ip4)
174 # And a dynamic ARP entry for host 1
176 dyn_arp = VppNeighbor(self,
177 self.pg1.sw_if_index,
178 self.pg1.remote_hosts[1].mac,
179 self.pg1.remote_hosts[1].ip4)
180 dyn_arp.add_vpp_config()
183 # now we expect IP traffic forwarded
185 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
186 IP(src=self.pg0.remote_ip4,
187 dst=self.pg1._remote_hosts[1].ip4) /
188 UDP(sport=1234, dport=1234) /
191 self.pg0.add_stream(dyn_p)
192 self.pg_enable_capture(self.pg_interfaces)
195 rx = self.pg1.get_capture(1)
197 self.verify_ip(rx[0],
199 self.pg1.remote_hosts[1].mac,
201 self.pg1._remote_hosts[1].ip4)
204 # And a Static ARP entry for host 2
206 static_arp = VppNeighbor(self,
207 self.pg1.sw_if_index,
208 self.pg1.remote_hosts[2].mac,
209 self.pg1.remote_hosts[2].ip4,
211 static_arp.add_vpp_config()
213 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
214 IP(src=self.pg0.remote_ip4,
215 dst=self.pg1._remote_hosts[2].ip4) /
216 UDP(sport=1234, dport=1234) /
219 self.pg0.add_stream(static_p)
220 self.pg_enable_capture(self.pg_interfaces)
223 rx = self.pg1.get_capture(1)
225 self.verify_ip(rx[0],
227 self.pg1.remote_hosts[2].mac,
229 self.pg1._remote_hosts[2].ip4)
232 # flap the link. dynamic ARPs get flush, statics don't
234 self.pg1.admin_down()
237 self.pg0.add_stream(static_p)
238 self.pg_enable_capture(self.pg_interfaces)
240 rx = self.pg1.get_capture(1)
242 self.verify_ip(rx[0],
244 self.pg1.remote_hosts[2].mac,
246 self.pg1._remote_hosts[2].ip4)
248 self.pg0.add_stream(dyn_p)
249 self.pg_enable_capture(self.pg_interfaces)
252 rx = self.pg1.get_capture(1)
253 self.verify_arp_req(rx[0],
256 self.pg1._remote_hosts[1].ip4)
259 # Send an ARP request from one of the so-far unlearned remote hosts
261 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
262 src=self.pg1._remote_hosts[3].mac) /
264 hwsrc=self.pg1._remote_hosts[3].mac,
265 pdst=self.pg1.local_ip4,
266 psrc=self.pg1._remote_hosts[3].ip4))
268 self.pg1.add_stream(p)
269 self.pg_enable_capture(self.pg_interfaces)
272 rx = self.pg1.get_capture(1)
273 self.verify_arp_resp(rx[0],
275 self.pg1._remote_hosts[3].mac,
277 self.pg1._remote_hosts[3].ip4)
280 # VPP should have learned the mapping for the remote host
282 self.assertTrue(find_nbr(self,
283 self.pg1.sw_if_index,
284 self.pg1._remote_hosts[3].ip4))
286 # Fire in an ARP request before the interface becomes IP enabled
288 self.pg2.generate_remote_hosts(4)
290 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
292 hwsrc=self.pg2.remote_mac,
293 pdst=self.pg1.local_ip4,
294 psrc=self.pg2.remote_hosts[3].ip4))
295 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
298 hwsrc=self.pg2.remote_mac,
299 pdst=self.pg1.local_ip4,
300 psrc=self.pg2.remote_hosts[3].ip4))
301 self.send_and_assert_no_replies(self.pg2, p,
302 "interface not IP enabled")
305 # Make pg2 un-numbered to pg1
307 self.pg2.set_unnumbered(self.pg1.sw_if_index)
310 # We should respond to ARP requests for the unnumbered to address
311 # once an attached route to the source is known
313 self.send_and_assert_no_replies(
315 "ARP req for unnumbered address - no source")
317 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
318 [VppRoutePath("0.0.0.0",
319 self.pg2.sw_if_index)])
320 attached_host.add_vpp_config()
322 self.pg2.add_stream(p)
323 self.pg_enable_capture(self.pg_interfaces)
326 rx = self.pg2.get_capture(1)
327 self.verify_arp_resp(rx[0],
331 self.pg2.remote_hosts[3].ip4)
333 self.pg2.add_stream(pt)
334 self.pg_enable_capture(self.pg_interfaces)
337 rx = self.pg2.get_capture(1)
338 self.verify_arp_resp(rx[0],
342 self.pg2.remote_hosts[3].ip4)
345 # A neighbor entry that has no associated FIB-entry
347 arp_no_fib = VppNeighbor(self,
348 self.pg1.sw_if_index,
349 self.pg1.remote_hosts[4].mac,
350 self.pg1.remote_hosts[4].ip4,
352 arp_no_fib.add_vpp_config()
355 # check we have the neighbor, but no route
357 self.assertTrue(find_nbr(self,
358 self.pg1.sw_if_index,
359 self.pg1._remote_hosts[4].ip4))
360 self.assertFalse(find_route(self,
361 self.pg1._remote_hosts[4].ip4,
364 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
365 # from within pg1's subnet
367 arp_unnum = VppNeighbor(self,
368 self.pg2.sw_if_index,
369 self.pg1.remote_hosts[5].mac,
370 self.pg1.remote_hosts[5].ip4)
371 arp_unnum.add_vpp_config()
373 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
374 IP(src=self.pg0.remote_ip4,
375 dst=self.pg1._remote_hosts[5].ip4) /
376 UDP(sport=1234, dport=1234) /
379 self.pg0.add_stream(p)
380 self.pg_enable_capture(self.pg_interfaces)
383 rx = self.pg2.get_capture(1)
385 self.verify_ip(rx[0],
387 self.pg1.remote_hosts[5].mac,
389 self.pg1._remote_hosts[5].ip4)
392 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
393 # with the unnumbered interface's address as the source
395 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
397 hwsrc=self.pg2.remote_mac,
398 pdst=self.pg1.local_ip4,
399 psrc=self.pg1.remote_hosts[6].ip4))
401 self.pg2.add_stream(p)
402 self.pg_enable_capture(self.pg_interfaces)
405 rx = self.pg2.get_capture(1)
406 self.verify_arp_resp(rx[0],
410 self.pg1.remote_hosts[6].ip4)
413 # An attached host route out of pg2 for an undiscovered hosts generates
414 # an ARP request with the unnumbered address as the source
416 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
417 [VppRoutePath("0.0.0.0",
418 self.pg2.sw_if_index)])
419 att_unnum.add_vpp_config()
421 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
422 IP(src=self.pg0.remote_ip4,
423 dst=self.pg1._remote_hosts[7].ip4) /
424 UDP(sport=1234, dport=1234) /
427 self.pg0.add_stream(p)
428 self.pg_enable_capture(self.pg_interfaces)
431 rx = self.pg2.get_capture(1)
433 self.verify_arp_req(rx[0],
436 self.pg1._remote_hosts[7].ip4)
438 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
440 hwsrc=self.pg2.remote_mac,
441 pdst=self.pg1.local_ip4,
442 psrc=self.pg1.remote_hosts[7].ip4))
444 self.pg2.add_stream(p)
445 self.pg_enable_capture(self.pg_interfaces)
448 rx = self.pg2.get_capture(1)
449 self.verify_arp_resp(rx[0],
453 self.pg1.remote_hosts[7].ip4)
456 # An attached host route as yet unresolved out of pg2 for an
457 # undiscovered host, an ARP requests begets a response.
459 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
460 [VppRoutePath("0.0.0.0",
461 self.pg2.sw_if_index)])
462 att_unnum1.add_vpp_config()
464 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
466 hwsrc=self.pg2.remote_mac,
467 pdst=self.pg1.local_ip4,
468 psrc=self.pg1.remote_hosts[8].ip4))
470 self.pg2.add_stream(p)
471 self.pg_enable_capture(self.pg_interfaces)
474 rx = self.pg2.get_capture(1)
475 self.verify_arp_resp(rx[0],
479 self.pg1.remote_hosts[8].ip4)
482 # Send an ARP request from one of the so-far unlearned remote hosts
485 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
486 src=self.pg1._remote_hosts[9].mac) /
489 hwsrc=self.pg1._remote_hosts[9].mac,
490 pdst=self.pg1.local_ip4,
491 psrc=self.pg1._remote_hosts[9].ip4))
493 self.pg1.add_stream(p)
494 self.pg_enable_capture(self.pg_interfaces)
497 rx = self.pg1.get_capture(1)
498 self.verify_arp_resp(rx[0],
500 self.pg1._remote_hosts[9].mac,
502 self.pg1._remote_hosts[9].ip4)
505 # Add a hierachy of routes for a host in the sub-net.
506 # Should still get an ARP resp since the cover is attached
508 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
510 hwsrc=self.pg1.remote_mac,
511 pdst=self.pg1.local_ip4,
512 psrc=self.pg1.remote_hosts[10].ip4))
514 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
515 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
516 self.pg1.sw_if_index)])
519 self.pg1.add_stream(p)
520 self.pg_enable_capture(self.pg_interfaces)
522 rx = self.pg1.get_capture(1)
523 self.verify_arp_resp(rx[0],
527 self.pg1.remote_hosts[10].ip4)
529 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
530 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
531 self.pg1.sw_if_index)])
534 self.pg1.add_stream(p)
535 self.pg_enable_capture(self.pg_interfaces)
537 rx = self.pg1.get_capture(1)
538 self.verify_arp_resp(rx[0],
542 self.pg1.remote_hosts[10].ip4)
545 # add an ARP entry that's not on the sub-net and so whose
546 # adj-fib fails the refinement check. then send an ARP request
549 a1 = VppNeighbor(self,
550 self.pg0.sw_if_index,
555 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
557 hwsrc=self.pg0.remote_mac,
558 psrc="100.100.100.50",
559 pdst=self.pg0.remote_ip4))
560 self.send_and_assert_no_replies(self.pg0, p,
561 "ARP req for from failed adj-fib")
565 # 1 - don't respond to ARP request for address not within the
566 # interface's sub-net
567 # 1b - nor within the unnumbered subnet
568 # 1c - nor within the subnet of a different interface
570 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
572 hwsrc=self.pg0.remote_mac,
574 psrc=self.pg0.remote_ip4))
575 self.send_and_assert_no_replies(self.pg0, p,
576 "ARP req for non-local destination")
577 self.assertFalse(find_nbr(self,
578 self.pg0.sw_if_index,
581 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
583 hwsrc=self.pg2.remote_mac,
585 psrc=self.pg1.remote_hosts[7].ip4))
586 self.send_and_assert_no_replies(
588 "ARP req for non-local destination - unnum")
590 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
592 hwsrc=self.pg0.remote_mac,
593 pdst=self.pg1.local_ip4,
594 psrc=self.pg1.remote_ip4))
595 self.send_and_assert_no_replies(self.pg0, p,
596 "ARP req diff sub-net")
597 self.assertFalse(find_nbr(self,
598 self.pg0.sw_if_index,
599 self.pg1.remote_ip4))
602 # 2 - don't respond to ARP request from an address not within the
603 # interface's sub-net
604 # 2b - to a prxied address
605 # 2c - not within a differents interface's sub-net
606 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
608 hwsrc=self.pg0.remote_mac,
610 pdst=self.pg0.local_ip4))
611 self.send_and_assert_no_replies(self.pg0, p,
612 "ARP req for non-local source")
613 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
615 hwsrc=self.pg2.remote_mac,
617 pdst=self.pg0.local_ip4))
618 self.send_and_assert_no_replies(
620 "ARP req for non-local source - unnum")
621 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
623 hwsrc=self.pg0.remote_mac,
624 psrc=self.pg1.remote_ip4,
625 pdst=self.pg0.local_ip4))
626 self.send_and_assert_no_replies(self.pg0, p,
627 "ARP req for non-local source 2c")
630 # 3 - don't respond to ARP request from an address that belongs to
633 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
635 hwsrc=self.pg0.remote_mac,
636 psrc=self.pg0.local_ip4,
637 pdst=self.pg0.local_ip4))
638 self.send_and_assert_no_replies(self.pg0, p,
639 "ARP req for non-local source")
642 # 4 - don't respond to ARP requests that has mac source different
643 # from ARP request HW source
645 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
647 hwsrc="00:00:00:DE:AD:BE",
648 psrc=self.pg0.remote_ip4,
649 pdst=self.pg0.local_ip4))
650 self.send_and_assert_no_replies(self.pg0, p,
651 "ARP req for non-local source")
654 # 5 - don't respond to ARP requests for address within the
655 # interface's sub-net but not the interface's address
657 self.pg0.generate_remote_hosts(2)
658 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
660 hwsrc=self.pg0.remote_mac,
661 psrc=self.pg0.remote_hosts[0].ip4,
662 pdst=self.pg0.remote_hosts[1].ip4))
663 self.send_and_assert_no_replies(self.pg0, p,
664 "ARP req for non-local destination")
669 dyn_arp.remove_vpp_config()
670 static_arp.remove_vpp_config()
671 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
673 # need this to flush the adj-fibs
674 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
675 self.pg2.admin_down()
676 self.pg1.admin_down()
678 def test_proxy_mirror_arp(self):
679 """ Interface Mirror Proxy ARP """
682 # When VPP has an interface whose address is also applied to a TAP
683 # interface on the host, then VPP's TAP interface will be unnumbered
684 # to the 'real' interface and do proxy ARP from the host.
685 # the curious aspect of this setup is that ARP requests from the host
686 # will come from the VPP's own address.
688 self.pg0.generate_remote_hosts(2)
690 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
691 dst="ff:ff:ff:ff:ff:ff") /
693 hwsrc=self.pg2.remote_mac,
694 pdst=self.pg0.remote_hosts[1].ip4,
695 psrc=self.pg0.local_ip4))
698 # Configure Proxy ARP for the subnet on PG0addresses on pg0
700 self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
701 self.pg0._local_ip4n_bcast)
703 # Make pg2 un-numbered to pg0
705 self.pg2.set_unnumbered(self.pg0.sw_if_index)
708 # Enable pg2 for proxy ARP
710 self.pg2.set_proxy_arp()
713 # Send the ARP request with an originating address that
714 # is VPP's own address
716 self.pg2.add_stream(arp_req_from_me)
717 self.pg_enable_capture(self.pg_interfaces)
720 rx = self.pg2.get_capture(1)
721 self.verify_arp_resp(rx[0],
724 self.pg0.remote_hosts[1].ip4,
728 # validate we have not learned an ARP entry as a result of this
730 self.assertFalse(find_nbr(self,
731 self.pg2.sw_if_index,
737 self.pg2.set_proxy_arp(0)
738 self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
739 self.pg0._local_ip4n_bcast,
742 def test_proxy_arp(self):
745 self.pg1.generate_remote_hosts(2)
748 # Proxy ARP rewquest packets for each interface
750 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
751 dst="ff:ff:ff:ff:ff:ff") /
753 hwsrc=self.pg0.remote_mac,
755 psrc=self.pg0.remote_ip4))
756 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
757 dst="ff:ff:ff:ff:ff:ff") /
760 hwsrc=self.pg0.remote_mac,
762 psrc=self.pg0.remote_ip4))
763 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
764 dst="ff:ff:ff:ff:ff:ff") /
766 hwsrc=self.pg1.remote_mac,
768 psrc=self.pg1.remote_ip4))
769 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
770 dst="ff:ff:ff:ff:ff:ff") /
772 hwsrc=self.pg2.remote_mac,
774 psrc=self.pg1.remote_hosts[1].ip4))
775 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
776 dst="ff:ff:ff:ff:ff:ff") /
778 hwsrc=self.pg3.remote_mac,
780 psrc=self.pg3.remote_ip4))
783 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
785 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
786 inet_pton(AF_INET, "10.10.10.124"))
789 # No responses are sent when the interfaces are not enabled for proxy
792 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
793 "ARP req from unconfigured interface")
794 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
795 "ARP req from unconfigured interface")
798 # Make pg2 un-numbered to pg1
801 self.pg2.set_unnumbered(self.pg1.sw_if_index)
803 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
804 "ARP req from unnumbered interface")
807 # Enable each interface to reply to proxy ARPs
809 for i in self.pg_interfaces:
813 # Now each of the interfaces should reply to a request to a proxied
816 self.pg0.add_stream(arp_req_pg0)
817 self.pg_enable_capture(self.pg_interfaces)
820 rx = self.pg0.get_capture(1)
821 self.verify_arp_resp(rx[0],
827 self.pg0.add_stream(arp_req_pg0_tagged)
828 self.pg_enable_capture(self.pg_interfaces)
831 rx = self.pg0.get_capture(1)
832 self.verify_arp_resp(rx[0],
838 self.pg1.add_stream(arp_req_pg1)
839 self.pg_enable_capture(self.pg_interfaces)
842 rx = self.pg1.get_capture(1)
843 self.verify_arp_resp(rx[0],
849 self.pg2.add_stream(arp_req_pg2)
850 self.pg_enable_capture(self.pg_interfaces)
853 rx = self.pg2.get_capture(1)
854 self.verify_arp_resp(rx[0],
858 self.pg1.remote_hosts[1].ip4)
861 # A request for an address out of the configured range
863 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
864 dst="ff:ff:ff:ff:ff:ff") /
866 hwsrc=self.pg1.remote_mac,
868 psrc=self.pg1.remote_ip4))
869 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
870 "ARP req out of range HI")
871 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
872 dst="ff:ff:ff:ff:ff:ff") /
874 hwsrc=self.pg1.remote_mac,
876 psrc=self.pg1.remote_ip4))
877 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
878 "ARP req out of range Low")
881 # Request for an address in the proxy range but from an interface
884 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
885 "ARP req from different VRF")
888 # Disable Each interface for proxy ARP
889 # - expect none to respond
891 for i in self.pg_interfaces:
894 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
895 "ARP req from disable")
896 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
897 "ARP req from disable")
898 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
899 "ARP req from disable")
902 # clean up on interface 2
904 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
910 # Interface 2 does not yet have ip4 config
912 self.pg2.config_ip4()
913 self.pg2.generate_remote_hosts(2)
916 # Add a reoute with out going label via an ARP unresolved next-hop
918 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
919 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
920 self.pg2.sw_if_index,
922 ip_10_0_0_1.add_vpp_config()
925 # packets should generate an ARP request
927 p = (Ether(src=self.pg0.remote_mac,
928 dst=self.pg0.local_mac) /
929 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
930 UDP(sport=1234, dport=1234) /
933 self.pg0.add_stream(p)
934 self.pg_enable_capture(self.pg_interfaces)
937 rx = self.pg2.get_capture(1)
938 self.verify_arp_req(rx[0],
941 self.pg2._remote_hosts[1].ip4)
944 # now resolve the neighbours
946 self.pg2.configure_ipv4_neighbors()
949 # Now packet should be properly MPLS encapped.
950 # This verifies that MPLS link-type adjacencies are completed
951 # when the ARP entry resolves
953 self.pg0.add_stream(p)
954 self.pg_enable_capture(self.pg_interfaces)
957 rx = self.pg2.get_capture(1)
958 self.verify_ip_o_mpls(rx[0],
960 self.pg2.remote_hosts[1].mac,
964 self.pg2.unconfig_ip4()
966 def test_arp_vrrp(self):
967 """ ARP reply with VRRP virtual src hw addr """
970 # IP packet destined for pg1 remote host arrives on pg0 resulting
971 # in an ARP request for the address of the remote host on pg1
973 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
974 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
975 UDP(sport=1234, dport=1234) /
978 self.pg0.add_stream(p0)
979 self.pg_enable_capture(self.pg_interfaces)
982 rx1 = self.pg1.get_capture(1)
984 self.verify_arp_req(rx1[0],
990 # ARP reply for address of pg1 remote host arrives on pg1 with
991 # the hw src addr set to a value in the VRRP IPv4 range of
994 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
995 ARP(op="is-at", hwdst=self.pg1.local_mac,
996 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
997 psrc=self.pg1.remote_ip4))
999 self.pg1.add_stream(p1)
1000 self.pg_enable_capture(self.pg_interfaces)
1004 # IP packet destined for pg1 remote host arrives on pg0 again.
1005 # VPP should have an ARP entry for that address now and the packet
1006 # should be sent out pg1.
1008 self.pg0.add_stream(p0)
1009 self.pg_enable_capture(self.pg_interfaces)
1012 rx1 = self.pg1.get_capture(1)
1014 self.verify_ip(rx1[0],
1016 "00:00:5e:00:01:09",
1017 self.pg0.remote_ip4,
1018 self.pg1.remote_ip4)
1020 self.pg1.admin_down()
1023 def test_arp_duplicates(self):
1024 """ ARP Duplicates"""
1027 # Generate some hosts on the LAN
1029 self.pg1.generate_remote_hosts(3)
1032 # Add host 1 on pg1 and pg2
1034 arp_pg1 = VppNeighbor(self,
1035 self.pg1.sw_if_index,
1036 self.pg1.remote_hosts[1].mac,
1037 self.pg1.remote_hosts[1].ip4)
1038 arp_pg1.add_vpp_config()
1039 arp_pg2 = VppNeighbor(self,
1040 self.pg2.sw_if_index,
1041 self.pg2.remote_mac,
1042 self.pg1.remote_hosts[1].ip4)
1043 arp_pg2.add_vpp_config()
1046 # IP packet destined for pg1 remote host arrives on pg1 again.
1048 p = (Ether(dst=self.pg0.local_mac,
1049 src=self.pg0.remote_mac) /
1050 IP(src=self.pg0.remote_ip4,
1051 dst=self.pg1.remote_hosts[1].ip4) /
1052 UDP(sport=1234, dport=1234) /
1055 self.pg0.add_stream(p)
1056 self.pg_enable_capture(self.pg_interfaces)
1059 rx1 = self.pg1.get_capture(1)
1061 self.verify_ip(rx1[0],
1063 self.pg1.remote_hosts[1].mac,
1064 self.pg0.remote_ip4,
1065 self.pg1.remote_hosts[1].ip4)
1068 # remove the duplicate on pg1
1069 # packet stream shoud generate ARPs out of pg1
1071 arp_pg1.remove_vpp_config()
1073 self.pg0.add_stream(p)
1074 self.pg_enable_capture(self.pg_interfaces)
1077 rx1 = self.pg1.get_capture(1)
1079 self.verify_arp_req(rx1[0],
1082 self.pg1.remote_hosts[1].ip4)
1087 arp_pg1.add_vpp_config()
1089 self.pg0.add_stream(p)
1090 self.pg_enable_capture(self.pg_interfaces)
1093 rx1 = self.pg1.get_capture(1)
1095 self.verify_ip(rx1[0],
1097 self.pg1.remote_hosts[1].mac,
1098 self.pg0.remote_ip4,
1099 self.pg1.remote_hosts[1].ip4)
1101 def test_arp_static(self):
1103 self.pg2.generate_remote_hosts(3)
1106 # Add a static ARP entry
1108 static_arp = VppNeighbor(self,
1109 self.pg2.sw_if_index,
1110 self.pg2.remote_hosts[1].mac,
1111 self.pg2.remote_hosts[1].ip4,
1113 static_arp.add_vpp_config()
1116 # Add the connected prefix to the interface
1118 self.pg2.config_ip4()
1121 # We should now find the adj-fib
1123 self.assertTrue(find_nbr(self,
1124 self.pg2.sw_if_index,
1125 self.pg2.remote_hosts[1].ip4,
1127 self.assertTrue(find_route(self,
1128 self.pg2.remote_hosts[1].ip4,
1132 # remove the connected
1134 self.pg2.unconfig_ip4()
1137 # put the interface into table 1
1139 self.pg2.set_table_ip4(1)
1142 # configure the same connected and expect to find the
1143 # adj fib in the new table
1145 self.pg2.config_ip4()
1146 self.assertTrue(find_route(self,
1147 self.pg2.remote_hosts[1].ip4,
1154 self.pg2.unconfig_ip4()
1155 self.pg2.set_table_ip4(0)
1158 if __name__ == '__main__':
1159 unittest.main(testRunner=VppTestRunner)