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)
139 # Generate some hosts on the LAN
141 self.pg1.generate_remote_hosts(11)
144 # Send IP traffic to one of these unresolved hosts.
145 # expect the generation of an ARP request
147 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
148 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
149 UDP(sport=1234, dport=1234) /
152 self.pg0.add_stream(p)
153 self.pg_enable_capture(self.pg_interfaces)
156 rx = self.pg1.get_capture(1)
158 self.verify_arp_req(rx[0],
161 self.pg1._remote_hosts[1].ip4)
164 # And a dynamic ARP entry for host 1
166 dyn_arp = VppNeighbor(self,
167 self.pg1.sw_if_index,
168 self.pg1.remote_hosts[1].mac,
169 self.pg1.remote_hosts[1].ip4)
170 dyn_arp.add_vpp_config()
173 # now we expect IP traffic forwarded
175 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
176 IP(src=self.pg0.remote_ip4,
177 dst=self.pg1._remote_hosts[1].ip4) /
178 UDP(sport=1234, dport=1234) /
181 self.pg0.add_stream(dyn_p)
182 self.pg_enable_capture(self.pg_interfaces)
185 rx = self.pg1.get_capture(1)
187 self.verify_ip(rx[0],
189 self.pg1.remote_hosts[1].mac,
191 self.pg1._remote_hosts[1].ip4)
194 # And a Static ARP entry for host 2
196 static_arp = VppNeighbor(self,
197 self.pg1.sw_if_index,
198 self.pg1.remote_hosts[2].mac,
199 self.pg1.remote_hosts[2].ip4,
201 static_arp.add_vpp_config()
203 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
204 IP(src=self.pg0.remote_ip4,
205 dst=self.pg1._remote_hosts[2].ip4) /
206 UDP(sport=1234, dport=1234) /
209 self.pg0.add_stream(static_p)
210 self.pg_enable_capture(self.pg_interfaces)
213 rx = self.pg1.get_capture(1)
215 self.verify_ip(rx[0],
217 self.pg1.remote_hosts[2].mac,
219 self.pg1._remote_hosts[2].ip4)
222 # flap the link. dynamic ARPs get flush, statics don't
224 self.pg1.admin_down()
227 self.pg0.add_stream(static_p)
228 self.pg_enable_capture(self.pg_interfaces)
230 rx = self.pg1.get_capture(1)
232 self.verify_ip(rx[0],
234 self.pg1.remote_hosts[2].mac,
236 self.pg1._remote_hosts[2].ip4)
238 self.pg0.add_stream(dyn_p)
239 self.pg_enable_capture(self.pg_interfaces)
242 rx = self.pg1.get_capture(1)
243 self.verify_arp_req(rx[0],
246 self.pg1._remote_hosts[1].ip4)
249 # Send an ARP request from one of the so-far unlearned remote hosts
251 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
252 src=self.pg1._remote_hosts[3].mac) /
254 hwsrc=self.pg1._remote_hosts[3].mac,
255 pdst=self.pg1.local_ip4,
256 psrc=self.pg1._remote_hosts[3].ip4))
258 self.pg1.add_stream(p)
259 self.pg_enable_capture(self.pg_interfaces)
262 rx = self.pg1.get_capture(1)
263 self.verify_arp_resp(rx[0],
265 self.pg1._remote_hosts[3].mac,
267 self.pg1._remote_hosts[3].ip4)
270 # VPP should have learned the mapping for the remote host
272 self.assertTrue(find_nbr(self,
273 self.pg1.sw_if_index,
274 self.pg1._remote_hosts[3].ip4))
276 # Fire in an ARP request before the interface becomes IP enabled
278 self.pg2.generate_remote_hosts(4)
280 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
282 hwsrc=self.pg2.remote_mac,
283 pdst=self.pg1.local_ip4,
284 psrc=self.pg2.remote_hosts[3].ip4))
285 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
288 hwsrc=self.pg2.remote_mac,
289 pdst=self.pg1.local_ip4,
290 psrc=self.pg2.remote_hosts[3].ip4))
291 self.send_and_assert_no_replies(self.pg2, p,
292 "interface not IP enabled")
295 # Make pg2 un-numbered to pg1
297 self.pg2.set_unnumbered(self.pg1.sw_if_index)
300 # We should respond to ARP requests for the unnumbered to address
301 # once an attached route to the source is known
303 self.send_and_assert_no_replies(
305 "ARP req for unnumbered address - no source")
307 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
308 [VppRoutePath("0.0.0.0",
309 self.pg2.sw_if_index)])
310 attached_host.add_vpp_config()
312 self.pg2.add_stream(p)
313 self.pg_enable_capture(self.pg_interfaces)
316 rx = self.pg2.get_capture(1)
317 self.verify_arp_resp(rx[0],
321 self.pg2.remote_hosts[3].ip4)
323 self.pg2.add_stream(pt)
324 self.pg_enable_capture(self.pg_interfaces)
327 rx = self.pg2.get_capture(1)
328 self.verify_arp_resp(rx[0],
332 self.pg2.remote_hosts[3].ip4)
335 # A neighbor entry that has no associated FIB-entry
337 arp_no_fib = VppNeighbor(self,
338 self.pg1.sw_if_index,
339 self.pg1.remote_hosts[4].mac,
340 self.pg1.remote_hosts[4].ip4,
342 arp_no_fib.add_vpp_config()
345 # check we have the neighbor, but no route
347 self.assertTrue(find_nbr(self,
348 self.pg1.sw_if_index,
349 self.pg1._remote_hosts[4].ip4))
350 self.assertFalse(find_route(self,
351 self.pg1._remote_hosts[4].ip4,
354 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
355 # from within pg1's subnet
357 arp_unnum = VppNeighbor(self,
358 self.pg2.sw_if_index,
359 self.pg1.remote_hosts[5].mac,
360 self.pg1.remote_hosts[5].ip4)
361 arp_unnum.add_vpp_config()
363 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
364 IP(src=self.pg0.remote_ip4,
365 dst=self.pg1._remote_hosts[5].ip4) /
366 UDP(sport=1234, dport=1234) /
369 self.pg0.add_stream(p)
370 self.pg_enable_capture(self.pg_interfaces)
373 rx = self.pg2.get_capture(1)
375 self.verify_ip(rx[0],
377 self.pg1.remote_hosts[5].mac,
379 self.pg1._remote_hosts[5].ip4)
382 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
383 # with the unnumbered interface's address as the source
385 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
387 hwsrc=self.pg2.remote_mac,
388 pdst=self.pg1.local_ip4,
389 psrc=self.pg1.remote_hosts[6].ip4))
391 self.pg2.add_stream(p)
392 self.pg_enable_capture(self.pg_interfaces)
395 rx = self.pg2.get_capture(1)
396 self.verify_arp_resp(rx[0],
400 self.pg1.remote_hosts[6].ip4)
403 # An attached host route out of pg2 for an undiscovered hosts generates
404 # an ARP request with the unnumbered address as the source
406 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
407 [VppRoutePath("0.0.0.0",
408 self.pg2.sw_if_index)])
409 att_unnum.add_vpp_config()
411 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
412 IP(src=self.pg0.remote_ip4,
413 dst=self.pg1._remote_hosts[7].ip4) /
414 UDP(sport=1234, dport=1234) /
417 self.pg0.add_stream(p)
418 self.pg_enable_capture(self.pg_interfaces)
421 rx = self.pg2.get_capture(1)
423 self.verify_arp_req(rx[0],
426 self.pg1._remote_hosts[7].ip4)
428 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
430 hwsrc=self.pg2.remote_mac,
431 pdst=self.pg1.local_ip4,
432 psrc=self.pg1.remote_hosts[7].ip4))
434 self.pg2.add_stream(p)
435 self.pg_enable_capture(self.pg_interfaces)
438 rx = self.pg2.get_capture(1)
439 self.verify_arp_resp(rx[0],
443 self.pg1.remote_hosts[7].ip4)
446 # An attached host route as yet unresolved out of pg2 for an
447 # undiscovered host, an ARP requests begets a response.
449 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
450 [VppRoutePath("0.0.0.0",
451 self.pg2.sw_if_index)])
452 att_unnum1.add_vpp_config()
454 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
456 hwsrc=self.pg2.remote_mac,
457 pdst=self.pg1.local_ip4,
458 psrc=self.pg1.remote_hosts[8].ip4))
460 self.pg2.add_stream(p)
461 self.pg_enable_capture(self.pg_interfaces)
464 rx = self.pg2.get_capture(1)
465 self.verify_arp_resp(rx[0],
469 self.pg1.remote_hosts[8].ip4)
472 # Send an ARP request from one of the so-far unlearned remote hosts
475 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
476 src=self.pg1._remote_hosts[9].mac) /
479 hwsrc=self.pg1._remote_hosts[9].mac,
480 pdst=self.pg1.local_ip4,
481 psrc=self.pg1._remote_hosts[9].ip4))
483 self.pg1.add_stream(p)
484 self.pg_enable_capture(self.pg_interfaces)
487 rx = self.pg1.get_capture(1)
488 self.verify_arp_resp(rx[0],
490 self.pg1._remote_hosts[9].mac,
492 self.pg1._remote_hosts[9].ip4)
495 # Add a hierachy of routes for a host in the sub-net.
496 # Should still get an ARP resp since the cover is attached
498 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
500 hwsrc=self.pg1.remote_mac,
501 pdst=self.pg1.local_ip4,
502 psrc=self.pg1.remote_hosts[10].ip4))
504 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
505 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
506 self.pg1.sw_if_index)])
509 self.pg1.add_stream(p)
510 self.pg_enable_capture(self.pg_interfaces)
512 rx = self.pg1.get_capture(1)
513 self.verify_arp_resp(rx[0],
517 self.pg1.remote_hosts[10].ip4)
519 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
520 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
521 self.pg1.sw_if_index)])
524 self.pg1.add_stream(p)
525 self.pg_enable_capture(self.pg_interfaces)
527 rx = self.pg1.get_capture(1)
528 self.verify_arp_resp(rx[0],
532 self.pg1.remote_hosts[10].ip4)
535 # add an ARP entry that's not on the sub-net and so whose
536 # adj-fib fails the refinement check. then send an ARP request
539 a1 = VppNeighbor(self,
540 self.pg0.sw_if_index,
545 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
547 hwsrc=self.pg0.remote_mac,
548 psrc="100.100.100.50",
549 pdst=self.pg0.remote_ip4))
550 self.send_and_assert_no_replies(self.pg0, p,
551 "ARP req for from failed adj-fib")
555 # 1 - don't respond to ARP request for address not within the
556 # interface's sub-net
557 # 1b - nor within the unnumbered subnet
558 # 1c - nor within the subnet of a different interface
560 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
562 hwsrc=self.pg0.remote_mac,
564 psrc=self.pg0.remote_ip4))
565 self.send_and_assert_no_replies(self.pg0, p,
566 "ARP req for non-local destination")
567 self.assertFalse(find_nbr(self,
568 self.pg0.sw_if_index,
571 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
573 hwsrc=self.pg2.remote_mac,
575 psrc=self.pg1.remote_hosts[7].ip4))
576 self.send_and_assert_no_replies(
578 "ARP req for non-local destination - unnum")
580 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
582 hwsrc=self.pg0.remote_mac,
583 pdst=self.pg1.local_ip4,
584 psrc=self.pg1.remote_ip4))
585 self.send_and_assert_no_replies(self.pg0, p,
586 "ARP req diff sub-net")
587 self.assertFalse(find_nbr(self,
588 self.pg0.sw_if_index,
589 self.pg1.remote_ip4))
592 # 2 - don't respond to ARP request from an address not within the
593 # interface's sub-net
594 # 2b - to a prxied address
595 # 2c - not within a differents interface's sub-net
596 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
598 hwsrc=self.pg0.remote_mac,
600 pdst=self.pg0.local_ip4))
601 self.send_and_assert_no_replies(self.pg0, p,
602 "ARP req for non-local source")
603 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
605 hwsrc=self.pg2.remote_mac,
607 pdst=self.pg0.local_ip4))
608 self.send_and_assert_no_replies(
610 "ARP req for non-local source - unnum")
611 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
613 hwsrc=self.pg0.remote_mac,
614 psrc=self.pg1.remote_ip4,
615 pdst=self.pg0.local_ip4))
616 self.send_and_assert_no_replies(self.pg0, p,
617 "ARP req for non-local source 2c")
620 # 3 - don't respond to ARP request from an address that belongs to
623 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
625 hwsrc=self.pg0.remote_mac,
626 psrc=self.pg0.local_ip4,
627 pdst=self.pg0.local_ip4))
628 self.send_and_assert_no_replies(self.pg0, p,
629 "ARP req for non-local source")
632 # 4 - don't respond to ARP requests that has mac source different
633 # from ARP request HW source
635 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
637 hwsrc="00:00:00:DE:AD:BE",
638 psrc=self.pg0.remote_ip4,
639 pdst=self.pg0.local_ip4))
640 self.send_and_assert_no_replies(self.pg0, p,
641 "ARP req for non-local source")
644 # 5 - don't respond to ARP requests for address within the
645 # interface's sub-net but not the interface's address
647 self.pg0.generate_remote_hosts(2)
648 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
650 hwsrc=self.pg0.remote_mac,
651 psrc=self.pg0.remote_hosts[0].ip4,
652 pdst=self.pg0.remote_hosts[1].ip4))
653 self.send_and_assert_no_replies(self.pg0, p,
654 "ARP req for non-local destination")
659 dyn_arp.remove_vpp_config()
660 static_arp.remove_vpp_config()
661 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
663 # need this to flush the adj-fibs
664 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
665 self.pg2.admin_down()
666 self.pg1.admin_down()
668 def test_proxy_mirror_arp(self):
669 """ Interface Mirror Proxy ARP """
672 # When VPP has an interface whose address is also applied to a TAP
673 # interface on the host, then VPP's TAP interface will be unnumbered
674 # to the 'real' interface and do proxy ARP from the host.
675 # the curious aspect of this setup is that ARP requests from the host
676 # will come from the VPP's own address.
678 self.pg0.generate_remote_hosts(2)
680 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
681 dst="ff:ff:ff:ff:ff:ff") /
683 hwsrc=self.pg2.remote_mac,
684 pdst=self.pg0.remote_hosts[1].ip4,
685 psrc=self.pg0.local_ip4))
688 # Configure Proxy ARP for the subnet on PG0addresses on pg0
690 self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
691 self.pg0._local_ip4n_bcast)
693 # Make pg2 un-numbered to pg0
695 self.pg2.set_unnumbered(self.pg0.sw_if_index)
698 # Enable pg2 for proxy ARP
700 self.pg2.set_proxy_arp()
703 # Send the ARP request with an originating address that
704 # is VPP's own address
706 self.pg2.add_stream(arp_req_from_me)
707 self.pg_enable_capture(self.pg_interfaces)
710 rx = self.pg2.get_capture(1)
711 self.verify_arp_resp(rx[0],
714 self.pg0.remote_hosts[1].ip4,
718 # validate we have not learned an ARP entry as a result of this
720 self.assertFalse(find_nbr(self,
721 self.pg2.sw_if_index,
727 self.pg2.set_proxy_arp(0)
728 self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
729 self.pg0._local_ip4n_bcast,
732 def test_proxy_arp(self):
735 self.pg1.generate_remote_hosts(2)
738 # Proxy ARP rewquest packets for each interface
740 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
741 dst="ff:ff:ff:ff:ff:ff") /
743 hwsrc=self.pg0.remote_mac,
745 psrc=self.pg0.remote_ip4))
746 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
747 dst="ff:ff:ff:ff:ff:ff") /
750 hwsrc=self.pg0.remote_mac,
752 psrc=self.pg0.remote_ip4))
753 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
754 dst="ff:ff:ff:ff:ff:ff") /
756 hwsrc=self.pg1.remote_mac,
758 psrc=self.pg1.remote_ip4))
759 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
760 dst="ff:ff:ff:ff:ff:ff") /
762 hwsrc=self.pg2.remote_mac,
764 psrc=self.pg1.remote_hosts[1].ip4))
765 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
766 dst="ff:ff:ff:ff:ff:ff") /
768 hwsrc=self.pg3.remote_mac,
770 psrc=self.pg3.remote_ip4))
773 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
775 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
776 inet_pton(AF_INET, "10.10.10.124"))
779 # No responses are sent when the interfaces are not enabled for proxy
782 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
783 "ARP req from unconfigured interface")
784 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
785 "ARP req from unconfigured interface")
788 # Make pg2 un-numbered to pg1
791 self.pg2.set_unnumbered(self.pg1.sw_if_index)
793 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
794 "ARP req from unnumbered interface")
797 # Enable each interface to reply to proxy ARPs
799 for i in self.pg_interfaces:
803 # Now each of the interfaces should reply to a request to a proxied
806 self.pg0.add_stream(arp_req_pg0)
807 self.pg_enable_capture(self.pg_interfaces)
810 rx = self.pg0.get_capture(1)
811 self.verify_arp_resp(rx[0],
817 self.pg0.add_stream(arp_req_pg0_tagged)
818 self.pg_enable_capture(self.pg_interfaces)
821 rx = self.pg0.get_capture(1)
822 self.verify_arp_resp(rx[0],
828 self.pg1.add_stream(arp_req_pg1)
829 self.pg_enable_capture(self.pg_interfaces)
832 rx = self.pg1.get_capture(1)
833 self.verify_arp_resp(rx[0],
839 self.pg2.add_stream(arp_req_pg2)
840 self.pg_enable_capture(self.pg_interfaces)
843 rx = self.pg2.get_capture(1)
844 self.verify_arp_resp(rx[0],
848 self.pg1.remote_hosts[1].ip4)
851 # A request for an address out of the configured range
853 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
854 dst="ff:ff:ff:ff:ff:ff") /
856 hwsrc=self.pg1.remote_mac,
858 psrc=self.pg1.remote_ip4))
859 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
860 "ARP req out of range HI")
861 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
862 dst="ff:ff:ff:ff:ff:ff") /
864 hwsrc=self.pg1.remote_mac,
866 psrc=self.pg1.remote_ip4))
867 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
868 "ARP req out of range Low")
871 # Request for an address in the proxy range but from an interface
874 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
875 "ARP req from different VRF")
878 # Disable Each interface for proxy ARP
879 # - expect none to respond
881 for i in self.pg_interfaces:
884 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
885 "ARP req from disable")
886 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
887 "ARP req from disable")
888 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
889 "ARP req from disable")
892 # clean up on interface 2
894 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
900 # Interface 2 does not yet have ip4 config
902 self.pg2.config_ip4()
903 self.pg2.generate_remote_hosts(2)
906 # Add a reoute with out going label via an ARP unresolved next-hop
908 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
909 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
910 self.pg2.sw_if_index,
912 ip_10_0_0_1.add_vpp_config()
915 # packets should generate an ARP request
917 p = (Ether(src=self.pg0.remote_mac,
918 dst=self.pg0.local_mac) /
919 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
920 UDP(sport=1234, dport=1234) /
923 self.pg0.add_stream(p)
924 self.pg_enable_capture(self.pg_interfaces)
927 rx = self.pg2.get_capture(1)
928 self.verify_arp_req(rx[0],
931 self.pg2._remote_hosts[1].ip4)
934 # now resolve the neighbours
936 self.pg2.configure_ipv4_neighbors()
939 # Now packet should be properly MPLS encapped.
940 # This verifies that MPLS link-type adjacencies are completed
941 # when the ARP entry resolves
943 self.pg0.add_stream(p)
944 self.pg_enable_capture(self.pg_interfaces)
947 rx = self.pg2.get_capture(1)
948 self.verify_ip_o_mpls(rx[0],
950 self.pg2.remote_hosts[1].mac,
954 self.pg2.unconfig_ip4()
956 def test_arp_vrrp(self):
957 """ ARP reply with VRRP virtual src hw addr """
960 # IP packet destined for pg1 remote host arrives on pg0 resulting
961 # in an ARP request for the address of the remote host on pg1
963 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
964 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
965 UDP(sport=1234, dport=1234) /
968 self.pg0.add_stream(p0)
969 self.pg_enable_capture(self.pg_interfaces)
972 rx1 = self.pg1.get_capture(1)
974 self.verify_arp_req(rx1[0],
980 # ARP reply for address of pg1 remote host arrives on pg1 with
981 # the hw src addr set to a value in the VRRP IPv4 range of
984 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
985 ARP(op="is-at", hwdst=self.pg1.local_mac,
986 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
987 psrc=self.pg1.remote_ip4))
989 self.pg1.add_stream(p1)
990 self.pg_enable_capture(self.pg_interfaces)
994 # IP packet destined for pg1 remote host arrives on pg0 again.
995 # VPP should have an ARP entry for that address now and the packet
996 # should be sent out pg1.
998 self.pg0.add_stream(p0)
999 self.pg_enable_capture(self.pg_interfaces)
1002 rx1 = self.pg1.get_capture(1)
1004 self.verify_ip(rx1[0],
1006 "00:00:5e:00:01:09",
1007 self.pg0.remote_ip4,
1008 self.pg1.remote_ip4)
1010 self.pg1.admin_down()
1013 def test_arp_duplicates(self):
1014 """ ARP Duplicates"""
1017 # Generate some hosts on the LAN
1019 self.pg1.generate_remote_hosts(3)
1022 # Add host 1 on pg1 and pg2
1024 arp_pg1 = VppNeighbor(self,
1025 self.pg1.sw_if_index,
1026 self.pg1.remote_hosts[1].mac,
1027 self.pg1.remote_hosts[1].ip4)
1028 arp_pg1.add_vpp_config()
1029 arp_pg2 = VppNeighbor(self,
1030 self.pg2.sw_if_index,
1031 self.pg2.remote_mac,
1032 self.pg1.remote_hosts[1].ip4)
1033 arp_pg2.add_vpp_config()
1036 # IP packet destined for pg1 remote host arrives on pg1 again.
1038 p = (Ether(dst=self.pg0.local_mac,
1039 src=self.pg0.remote_mac) /
1040 IP(src=self.pg0.remote_ip4,
1041 dst=self.pg1.remote_hosts[1].ip4) /
1042 UDP(sport=1234, dport=1234) /
1045 self.pg0.add_stream(p)
1046 self.pg_enable_capture(self.pg_interfaces)
1049 rx1 = self.pg1.get_capture(1)
1051 self.verify_ip(rx1[0],
1053 self.pg1.remote_hosts[1].mac,
1054 self.pg0.remote_ip4,
1055 self.pg1.remote_hosts[1].ip4)
1058 # remove the duplicate on pg1
1059 # packet stream shoud generate ARPs out of pg1
1061 arp_pg1.remove_vpp_config()
1063 self.pg0.add_stream(p)
1064 self.pg_enable_capture(self.pg_interfaces)
1067 rx1 = self.pg1.get_capture(1)
1069 self.verify_arp_req(rx1[0],
1072 self.pg1.remote_hosts[1].ip4)
1077 arp_pg1.add_vpp_config()
1079 self.pg0.add_stream(p)
1080 self.pg_enable_capture(self.pg_interfaces)
1083 rx1 = self.pg1.get_capture(1)
1085 self.verify_ip(rx1[0],
1087 self.pg1.remote_hosts[1].mac,
1088 self.pg0.remote_ip4,
1089 self.pg1.remote_hosts[1].ip4)
1091 def test_arp_static(self):
1093 self.pg2.generate_remote_hosts(3)
1096 # Add a static ARP entry
1098 static_arp = VppNeighbor(self,
1099 self.pg2.sw_if_index,
1100 self.pg2.remote_hosts[1].mac,
1101 self.pg2.remote_hosts[1].ip4,
1103 static_arp.add_vpp_config()
1106 # Add the connected prefix to the interface
1108 self.pg2.config_ip4()
1111 # We should now find the adj-fib
1113 self.assertTrue(find_nbr(self,
1114 self.pg2.sw_if_index,
1115 self.pg2.remote_hosts[1].ip4,
1117 self.assertTrue(find_route(self,
1118 self.pg2.remote_hosts[1].ip4,
1122 # remove the connected
1124 self.pg2.unconfig_ip4()
1127 # put the interface into table 1
1129 self.pg2.set_table_ip4(1)
1132 # configure the same connected and expect to find the
1133 # adj fib in the new table
1135 self.pg2.config_ip4()
1136 self.assertTrue(find_route(self,
1137 self.pg2.remote_hosts[1].ip4,
1144 self.pg2.unconfig_ip4()
1145 self.pg2.set_table_ip4(0)
1147 def test_arp_incomplete(self):
1148 """ ARP Incomplete"""
1149 self.pg1.generate_remote_hosts(3)
1151 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1152 IP(src=self.pg0.remote_ip4,
1153 dst=self.pg1.remote_hosts[1].ip4) /
1154 UDP(sport=1234, dport=1234) /
1156 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1157 IP(src=self.pg0.remote_ip4,
1158 dst=self.pg1.remote_hosts[2].ip4) /
1159 UDP(sport=1234, dport=1234) /
1163 # a packet to an unresolved destination generates an ARP request
1165 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1166 self.verify_arp_req(rx[0],
1169 self.pg1._remote_hosts[1].ip4)
1172 # add a neighbour for remote host 1
1174 static_arp = VppNeighbor(self,
1175 self.pg1.sw_if_index,
1176 self.pg1.remote_hosts[1].mac,
1177 self.pg1.remote_hosts[1].ip4,
1179 static_arp.add_vpp_config()
1182 # change the interface's MAC
1184 mac = [chr(0x00), chr(0x00), chr(0x00),
1185 chr(0x33), chr(0x33), chr(0x33)]
1186 mac_string = ''.join(mac)
1188 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1192 # now ARP requests come from the new source mac
1194 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1195 self.verify_arp_req(rx[0],
1196 "00:00:00:33:33:33",
1198 self.pg1._remote_hosts[2].ip4)
1201 # packets to the resolved host also have the new source mac
1203 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1204 self.verify_ip(rx[0],
1205 "00:00:00:33:33:33",
1206 self.pg1.remote_hosts[1].mac,
1207 self.pg0.remote_ip4,
1208 self.pg1.remote_hosts[1].ip4)
1211 # set the mac address on the inteface that does not have a
1212 # configured subnet and thus no glean
1214 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1218 if __name__ == '__main__':
1219 unittest.main(testRunner=VppTestRunner)