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
10 from scapy.packet import Raw
11 from scapy.layers.l2 import Ether, ARP, Dot1Q
12 from scapy.layers.inet import IP, UDP
13 from scapy.contrib.mpls import MPLS
15 # not exported by scapy, so redefined here
16 arp_opts = {"who-has": 1, "is-at": 2}
19 class ARPTestCase(VppTestCase):
23 super(ARPTestCase, self).setUp()
25 # create 3 pg interfaces
26 self.create_pg_interfaces(range(4))
28 # pg0 configured with ip4 and 6 addresses used for input
29 # pg1 configured with ip4 and 6 addresses used for output
30 # pg2 is unnumbered to pg0
31 for i in self.pg_interfaces:
36 self.pg0.resolve_arp()
41 # pg3 in a different VRF
42 self.pg3.set_table_ip4(1)
46 super(ARPTestCase, self).tearDown()
47 self.pg0.unconfig_ip4()
48 self.pg0.unconfig_ip6()
50 self.pg1.unconfig_ip4()
51 self.pg1.unconfig_ip6()
53 self.pg3.unconfig_ip4()
55 for i in self.pg_interfaces:
58 def verify_arp_req(self, rx, smac, sip, dip):
60 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
61 self.assertEqual(ether.src, smac)
64 self.assertEqual(arp.hwtype, 1)
65 self.assertEqual(arp.ptype, 0x800)
66 self.assertEqual(arp.hwlen, 6)
67 self.assertEqual(arp.plen, 4)
68 self.assertEqual(arp.op, arp_opts["who-has"])
69 self.assertEqual(arp.hwsrc, smac)
70 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
71 self.assertEqual(arp.psrc, sip)
72 self.assertEqual(arp.pdst, dip)
74 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
76 self.assertEqual(ether.dst, dmac)
77 self.assertEqual(ether.src, smac)
80 self.assertEqual(arp.hwtype, 1)
81 self.assertEqual(arp.ptype, 0x800)
82 self.assertEqual(arp.hwlen, 6)
83 self.assertEqual(arp.plen, 4)
84 self.assertEqual(arp.op, arp_opts["is-at"])
85 self.assertEqual(arp.hwsrc, smac)
86 self.assertEqual(arp.hwdst, dmac)
87 self.assertEqual(arp.psrc, sip)
88 self.assertEqual(arp.pdst, dip)
90 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
92 self.assertEqual(ether.dst, dmac)
93 self.assertEqual(ether.src, smac)
96 self.assertEqual(arp.hwtype, 1)
97 self.assertEqual(arp.ptype, 0x800)
98 self.assertEqual(arp.hwlen, 6)
99 self.assertEqual(arp.plen, 4)
100 self.assertEqual(arp.op, arp_opts["is-at"])
101 self.assertNotEqual(arp.hwsrc, smac)
102 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
103 "00:00:5E:00:01" in arp.hwsrc)
104 self.assertEqual(arp.hwdst, dmac)
105 self.assertEqual(arp.psrc, sip)
106 self.assertEqual(arp.pdst, dip)
108 def verify_ip(self, rx, smac, dmac, sip, dip):
110 self.assertEqual(ether.dst, dmac)
111 self.assertEqual(ether.src, smac)
114 self.assertEqual(ip.src, sip)
115 self.assertEqual(ip.dst, dip)
117 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
119 self.assertEqual(ether.dst, dmac)
120 self.assertEqual(ether.src, smac)
123 self.assertTrue(mpls.label, label)
126 self.assertEqual(ip.src, sip)
127 self.assertEqual(ip.dst, dip)
129 def send_and_assert_no_replies(self, intf, pkts, remark):
130 intf.add_stream(pkts)
131 self.pg_enable_capture(self.pg_interfaces)
134 for i in self.pg_interfaces:
135 i.get_capture(0, timeout=timeout)
136 i.assert_nothing_captured(remark=remark)
143 # Generate some hosts on the LAN
145 self.pg1.generate_remote_hosts(10)
148 # Send IP traffic to one of these unresolved hosts.
149 # expect the generation of an ARP request
151 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
152 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
153 UDP(sport=1234, dport=1234) /
156 self.pg0.add_stream(p)
157 self.pg_enable_capture(self.pg_interfaces)
160 rx = self.pg1.get_capture(1)
162 self.verify_arp_req(rx[0],
165 self.pg1._remote_hosts[1].ip4)
168 # And a dynamic ARP entry for host 1
170 dyn_arp = VppNeighbor(self,
171 self.pg1.sw_if_index,
172 self.pg1.remote_hosts[1].mac,
173 self.pg1.remote_hosts[1].ip4)
174 dyn_arp.add_vpp_config()
177 # now we expect IP traffic forwarded
179 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
180 IP(src=self.pg0.remote_ip4,
181 dst=self.pg1._remote_hosts[1].ip4) /
182 UDP(sport=1234, dport=1234) /
185 self.pg0.add_stream(dyn_p)
186 self.pg_enable_capture(self.pg_interfaces)
189 rx = self.pg1.get_capture(1)
191 self.verify_ip(rx[0],
193 self.pg1.remote_hosts[1].mac,
195 self.pg1._remote_hosts[1].ip4)
198 # And a Static ARP entry for host 2
200 static_arp = VppNeighbor(self,
201 self.pg1.sw_if_index,
202 self.pg1.remote_hosts[2].mac,
203 self.pg1.remote_hosts[2].ip4,
205 static_arp.add_vpp_config()
207 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
208 IP(src=self.pg0.remote_ip4,
209 dst=self.pg1._remote_hosts[2].ip4) /
210 UDP(sport=1234, dport=1234) /
213 self.pg0.add_stream(static_p)
214 self.pg_enable_capture(self.pg_interfaces)
217 rx = self.pg1.get_capture(1)
219 self.verify_ip(rx[0],
221 self.pg1.remote_hosts[2].mac,
223 self.pg1._remote_hosts[2].ip4)
226 # flap the link. dynamic ARPs get flush, statics don't
228 self.pg1.admin_down()
231 self.pg0.add_stream(static_p)
232 self.pg_enable_capture(self.pg_interfaces)
234 rx = self.pg1.get_capture(1)
236 self.verify_ip(rx[0],
238 self.pg1.remote_hosts[2].mac,
240 self.pg1._remote_hosts[2].ip4)
242 self.pg0.add_stream(dyn_p)
243 self.pg_enable_capture(self.pg_interfaces)
246 rx = self.pg1.get_capture(1)
247 self.verify_arp_req(rx[0],
250 self.pg1._remote_hosts[1].ip4)
253 # Send an ARP request from one of the so-far unlearned remote hosts
255 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
256 src=self.pg1._remote_hosts[3].mac) /
258 hwsrc=self.pg1._remote_hosts[3].mac,
259 pdst=self.pg1.local_ip4,
260 psrc=self.pg1._remote_hosts[3].ip4))
262 self.pg1.add_stream(p)
263 self.pg_enable_capture(self.pg_interfaces)
266 rx = self.pg1.get_capture(1)
267 self.verify_arp_resp(rx[0],
269 self.pg1._remote_hosts[3].mac,
271 self.pg1._remote_hosts[3].ip4)
274 # VPP should have learned the mapping for the remote host
276 self.assertTrue(find_nbr(self,
277 self.pg1.sw_if_index,
278 self.pg1._remote_hosts[3].ip4))
280 # Fire in an ARP request before the interface becomes IP enabled
282 self.pg2.generate_remote_hosts(4)
284 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
286 hwsrc=self.pg2.remote_mac,
287 pdst=self.pg1.local_ip4,
288 psrc=self.pg2.remote_hosts[3].ip4))
289 pt = (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 self.send_and_assert_no_replies(self.pg2, p,
296 "interface not IP enabled")
299 # Make pg2 un-numbered to pg1
301 self.pg2.set_unnumbered(self.pg1.sw_if_index)
304 # We should respond to ARP requests for the unnumbered to address
305 # once an attached route to the source is known
307 self.send_and_assert_no_replies(
309 "ARP req for unnumbered address - no source")
311 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
312 [VppRoutePath("0.0.0.0",
313 self.pg2.sw_if_index)])
314 attached_host.add_vpp_config()
316 self.pg2.add_stream(p)
317 self.pg_enable_capture(self.pg_interfaces)
320 rx = self.pg2.get_capture(1)
321 self.verify_arp_resp(rx[0],
325 self.pg2.remote_hosts[3].ip4)
327 self.pg2.add_stream(pt)
328 self.pg_enable_capture(self.pg_interfaces)
331 rx = self.pg2.get_capture(1)
332 self.verify_arp_resp(rx[0],
336 self.pg2.remote_hosts[3].ip4)
339 # A neighbor entry that has no associated FIB-entry
341 arp_no_fib = VppNeighbor(self,
342 self.pg1.sw_if_index,
343 self.pg1.remote_hosts[4].mac,
344 self.pg1.remote_hosts[4].ip4,
346 arp_no_fib.add_vpp_config()
349 # check we have the neighbor, but no route
351 self.assertTrue(find_nbr(self,
352 self.pg1.sw_if_index,
353 self.pg1._remote_hosts[4].ip4))
354 self.assertFalse(find_route(self,
355 self.pg1._remote_hosts[4].ip4,
358 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
359 # from within pg1's subnet
361 arp_unnum = VppNeighbor(self,
362 self.pg2.sw_if_index,
363 self.pg1.remote_hosts[5].mac,
364 self.pg1.remote_hosts[5].ip4)
365 arp_unnum.add_vpp_config()
367 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
368 IP(src=self.pg0.remote_ip4,
369 dst=self.pg1._remote_hosts[5].ip4) /
370 UDP(sport=1234, dport=1234) /
373 self.pg0.add_stream(p)
374 self.pg_enable_capture(self.pg_interfaces)
377 rx = self.pg2.get_capture(1)
379 self.verify_ip(rx[0],
381 self.pg1.remote_hosts[5].mac,
383 self.pg1._remote_hosts[5].ip4)
386 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
387 # with the unnumbered interface's address as the source
389 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
391 hwsrc=self.pg2.remote_mac,
392 pdst=self.pg1.local_ip4,
393 psrc=self.pg1.remote_hosts[6].ip4))
395 self.pg2.add_stream(p)
396 self.pg_enable_capture(self.pg_interfaces)
399 rx = self.pg2.get_capture(1)
400 self.verify_arp_resp(rx[0],
404 self.pg1.remote_hosts[6].ip4)
407 # An attached host route out of pg2 for an undiscovered hosts generates
408 # an ARP request with the unnumbered address as the source
410 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
411 [VppRoutePath("0.0.0.0",
412 self.pg2.sw_if_index)])
413 att_unnum.add_vpp_config()
415 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
416 IP(src=self.pg0.remote_ip4,
417 dst=self.pg1._remote_hosts[7].ip4) /
418 UDP(sport=1234, dport=1234) /
421 self.pg0.add_stream(p)
422 self.pg_enable_capture(self.pg_interfaces)
425 rx = self.pg2.get_capture(1)
427 self.verify_arp_req(rx[0],
430 self.pg1._remote_hosts[7].ip4)
432 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
434 hwsrc=self.pg2.remote_mac,
435 pdst=self.pg1.local_ip4,
436 psrc=self.pg1.remote_hosts[7].ip4))
438 self.pg2.add_stream(p)
439 self.pg_enable_capture(self.pg_interfaces)
442 rx = self.pg2.get_capture(1)
443 self.verify_arp_resp(rx[0],
447 self.pg1.remote_hosts[7].ip4)
450 # An attached host route as yet unresolved out of pg2 for an
451 # undiscovered host, an ARP requests begets a response.
453 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
454 [VppRoutePath("0.0.0.0",
455 self.pg2.sw_if_index)])
456 att_unnum1.add_vpp_config()
458 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
460 hwsrc=self.pg2.remote_mac,
461 pdst=self.pg1.local_ip4,
462 psrc=self.pg1.remote_hosts[8].ip4))
464 self.pg2.add_stream(p)
465 self.pg_enable_capture(self.pg_interfaces)
468 rx = self.pg2.get_capture(1)
469 self.verify_arp_resp(rx[0],
473 self.pg1.remote_hosts[8].ip4)
476 # Send an ARP request from one of the so-far unlearned remote hosts
479 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
480 src=self.pg1._remote_hosts[9].mac) /
483 hwsrc=self.pg1._remote_hosts[9].mac,
484 pdst=self.pg1.local_ip4,
485 psrc=self.pg1._remote_hosts[9].ip4))
487 self.pg1.add_stream(p)
488 self.pg_enable_capture(self.pg_interfaces)
491 rx = self.pg1.get_capture(1)
492 self.verify_arp_resp(rx[0],
494 self.pg1._remote_hosts[9].mac,
496 self.pg1._remote_hosts[9].ip4)
500 # 1 - don't respond to ARP request for address not within the
501 # interface's sub-net
502 # 1b - nor within the unnumbered subnet
503 # 1c - nor within the subnet of a different interface
505 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
507 hwsrc=self.pg0.remote_mac,
509 psrc=self.pg0.remote_ip4))
510 self.send_and_assert_no_replies(self.pg0, p,
511 "ARP req for non-local destination")
512 self.assertFalse(find_nbr(self,
513 self.pg0.sw_if_index,
516 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
518 hwsrc=self.pg2.remote_mac,
520 psrc=self.pg1.remote_hosts[7].ip4))
521 self.send_and_assert_no_replies(
523 "ARP req for non-local destination - unnum")
525 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
527 hwsrc=self.pg0.remote_mac,
528 pdst=self.pg1.local_ip4,
529 psrc=self.pg1.remote_ip4))
530 self.send_and_assert_no_replies(self.pg0, p,
531 "ARP req diff sub-net")
532 self.assertFalse(find_nbr(self,
533 self.pg0.sw_if_index,
534 self.pg1.remote_ip4))
537 # 2 - don't respond to ARP request from an address not within the
538 # interface's sub-net
540 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
542 hwsrc=self.pg0.remote_mac,
544 pdst=self.pg0.local_ip4))
545 self.send_and_assert_no_replies(self.pg0, p,
546 "ARP req for non-local source")
547 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
549 hwsrc=self.pg2.remote_mac,
551 pdst=self.pg0.local_ip4))
552 self.send_and_assert_no_replies(
554 "ARP req for non-local source - unnum")
557 # 3 - don't respond to ARP request from an address that belongs to
560 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
562 hwsrc=self.pg0.remote_mac,
563 psrc=self.pg0.local_ip4,
564 pdst=self.pg0.local_ip4))
565 self.send_and_assert_no_replies(self.pg0, p,
566 "ARP req for non-local source")
569 # 4 - don't respond to ARP requests that has mac source different
570 # from ARP request HW source
573 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
575 hwsrc="00:00:00:DE:AD:BE",
576 psrc=self.pg0.remote_ip4,
577 pdst=self.pg0.local_ip4))
578 self.send_and_assert_no_replies(self.pg0, p,
579 "ARP req for non-local source")
584 dyn_arp.remove_vpp_config()
585 static_arp.remove_vpp_config()
586 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
588 # need this to flush the adj-fibs
589 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
590 self.pg2.admin_down()
592 def test_proxy_arp(self):
595 self.pg1.generate_remote_hosts(2)
598 # Proxy ARP rewquest packets for each interface
600 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
601 dst="ff:ff:ff:ff:ff:ff") /
603 hwsrc=self.pg0.remote_mac,
605 psrc=self.pg0.remote_ip4))
606 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
607 dst="ff:ff:ff:ff:ff:ff") /
610 hwsrc=self.pg0.remote_mac,
612 psrc=self.pg0.remote_ip4))
613 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
614 dst="ff:ff:ff:ff:ff:ff") /
616 hwsrc=self.pg1.remote_mac,
618 psrc=self.pg1.remote_ip4))
619 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
620 dst="ff:ff:ff:ff:ff:ff") /
622 hwsrc=self.pg2.remote_mac,
624 psrc=self.pg1.remote_hosts[1].ip4))
625 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
626 dst="ff:ff:ff:ff:ff:ff") /
628 hwsrc=self.pg3.remote_mac,
630 psrc=self.pg3.remote_ip4))
633 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
635 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
636 inet_pton(AF_INET, "10.10.10.124"))
639 # No responses are sent when the interfaces are not enabled for proxy
642 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
643 "ARP req from unconfigured interface")
644 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
645 "ARP req from unconfigured interface")
648 # Make pg2 un-numbered to pg1
651 self.pg2.set_unnumbered(self.pg1.sw_if_index)
653 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
654 "ARP req from unnumbered interface")
657 # Enable each interface to reply to proxy ARPs
659 for i in self.pg_interfaces:
663 # Now each of the interfaces should reply to a request to a proxied
666 self.pg0.add_stream(arp_req_pg0)
667 self.pg_enable_capture(self.pg_interfaces)
670 rx = self.pg0.get_capture(1)
671 self.verify_arp_resp(rx[0],
677 self.pg0.add_stream(arp_req_pg0_tagged)
678 self.pg_enable_capture(self.pg_interfaces)
681 rx = self.pg0.get_capture(1)
682 self.verify_arp_resp(rx[0],
688 self.pg1.add_stream(arp_req_pg1)
689 self.pg_enable_capture(self.pg_interfaces)
692 rx = self.pg1.get_capture(1)
693 self.verify_arp_resp(rx[0],
699 self.pg2.add_stream(arp_req_pg2)
700 self.pg_enable_capture(self.pg_interfaces)
703 rx = self.pg2.get_capture(1)
704 self.verify_arp_resp(rx[0],
708 self.pg1.remote_hosts[1].ip4)
711 # A request for an address out of the configured range
713 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
714 dst="ff:ff:ff:ff:ff:ff") /
716 hwsrc=self.pg1.remote_mac,
718 psrc=self.pg1.remote_ip4))
719 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
720 "ARP req out of range HI")
721 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
722 dst="ff:ff:ff:ff:ff:ff") /
724 hwsrc=self.pg1.remote_mac,
726 psrc=self.pg1.remote_ip4))
727 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
728 "ARP req out of range Low")
731 # Request for an address in the proxy range but from an interface
734 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
735 "ARP req from different VRF")
738 # Disable Each interface for proxy ARP
739 # - expect none to respond
741 for i in self.pg_interfaces:
744 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
745 "ARP req from disable")
746 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
747 "ARP req from disable")
748 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
749 "ARP req from disable")
752 # clean up on interface 2
754 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
760 # Interface 2 does not yet have ip4 config
762 self.pg2.config_ip4()
763 self.pg2.generate_remote_hosts(2)
766 # Add a reoute with out going label via an ARP unresolved next-hop
768 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
769 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
770 self.pg2.sw_if_index,
772 ip_10_0_0_1.add_vpp_config()
775 # packets should generate an ARP request
777 p = (Ether(src=self.pg0.remote_mac,
778 dst=self.pg0.local_mac) /
779 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
780 UDP(sport=1234, dport=1234) /
783 self.pg0.add_stream(p)
784 self.pg_enable_capture(self.pg_interfaces)
787 rx = self.pg2.get_capture(1)
788 self.verify_arp_req(rx[0],
791 self.pg2._remote_hosts[1].ip4)
794 # now resolve the neighbours
796 self.pg2.configure_ipv4_neighbors()
799 # Now packet should be properly MPLS encapped.
800 # This verifies that MPLS link-type adjacencies are completed
801 # when the ARP entry resolves
803 self.pg0.add_stream(p)
804 self.pg_enable_capture(self.pg_interfaces)
807 rx = self.pg2.get_capture(1)
808 self.verify_ip_o_mpls(rx[0],
810 self.pg2.remote_hosts[1].mac,
814 self.pg2.unconfig_ip4()
816 def test_arp_vrrp(self):
817 """ ARP reply with VRRP virtual src hw addr """
820 # IP packet destined for pg1 remote host arrives on pg0 resulting
821 # in an ARP request for the address of the remote host on pg1
823 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
824 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
825 UDP(sport=1234, dport=1234) /
828 self.pg0.add_stream(p0)
829 self.pg_enable_capture(self.pg_interfaces)
832 rx1 = self.pg1.get_capture(1)
834 self.verify_arp_req(rx1[0],
840 # ARP reply for address of pg1 remote host arrives on pg1 with
841 # the hw src addr set to a value in the VRRP IPv4 range of
844 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
845 ARP(op="is-at", hwdst=self.pg1.local_mac,
846 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
847 psrc=self.pg1.remote_ip4))
849 self.pg1.add_stream(p1)
850 self.pg_enable_capture(self.pg_interfaces)
854 # IP packet destined for pg1 remote host arrives on pg0 again.
855 # VPP should have an ARP entry for that address now and the packet
856 # should be sent out pg1.
858 self.pg0.add_stream(p0)
859 self.pg_enable_capture(self.pg_interfaces)
862 rx1 = self.pg1.get_capture(1)
864 self.verify_ip(rx1[0],
870 self.pg1.admin_down()
873 def test_arp_duplicates(self):
874 """ ARP Duplicates"""
877 # Generate some hosts on the LAN
879 self.pg1.generate_remote_hosts(3)
882 # Add host 1 on pg1 and pg2
884 arp_pg1 = VppNeighbor(self,
885 self.pg1.sw_if_index,
886 self.pg1.remote_hosts[1].mac,
887 self.pg1.remote_hosts[1].ip4)
888 arp_pg1.add_vpp_config()
889 arp_pg2 = VppNeighbor(self,
890 self.pg2.sw_if_index,
892 self.pg1.remote_hosts[1].ip4)
893 arp_pg2.add_vpp_config()
896 # IP packet destined for pg1 remote host arrives on pg1 again.
898 p = (Ether(dst=self.pg0.local_mac,
899 src=self.pg0.remote_mac) /
900 IP(src=self.pg0.remote_ip4,
901 dst=self.pg1.remote_hosts[1].ip4) /
902 UDP(sport=1234, dport=1234) /
905 self.pg0.add_stream(p)
906 self.pg_enable_capture(self.pg_interfaces)
909 rx1 = self.pg1.get_capture(1)
911 self.verify_ip(rx1[0],
913 self.pg1.remote_hosts[1].mac,
915 self.pg1.remote_hosts[1].ip4)
918 # remove the duplicate on pg1
919 # packet stream shoud generate ARPs out of pg1
921 arp_pg1.remove_vpp_config()
923 self.pg0.add_stream(p)
924 self.pg_enable_capture(self.pg_interfaces)
927 rx1 = self.pg1.get_capture(1)
929 self.verify_arp_req(rx1[0],
932 self.pg1.remote_hosts[1].ip4)
937 arp_pg1.add_vpp_config()
939 self.pg0.add_stream(p)
940 self.pg_enable_capture(self.pg_interfaces)
943 rx1 = self.pg1.get_capture(1)
945 self.verify_ip(rx1[0],
947 self.pg1.remote_hosts[1].mac,
949 self.pg1.remote_hosts[1].ip4)
952 if __name__ == '__main__':
953 unittest.main(testRunner=VppTestRunner)