VPP-719: Accept ARP replies from VRRP hw addr
[vpp.git] / test / test_neighbor.py
1 #!/usr/bin/env python
2
3 import unittest
4 from socket import AF_INET, AF_INET6, inet_pton
5
6 from framework import VppTestCase, VppTestRunner
7 from vpp_neighbor import VppNeighbor, find_nbr
8 from vpp_ip_route import VppIpRoute, VppRoutePath, find_route
9
10 from scapy.packet import Raw
11 from scapy.layers.l2 import Ether, ARP
12 from scapy.layers.inet import IP, UDP
13 from scapy.contrib.mpls import MPLS
14
15 # not exported by scapy, so redefined here
16 arp_opts = {"who-has": 1, "is-at": 2}
17
18
19 class ARPTestCase(VppTestCase):
20     """ ARP Test Case """
21
22     def setUp(self):
23         super(ARPTestCase, self).setUp()
24
25         # create 3 pg interfaces
26         self.create_pg_interfaces(range(4))
27
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:
32             i.admin_up()
33
34         self.pg0.config_ip4()
35         self.pg0.config_ip6()
36         self.pg0.resolve_arp()
37
38         self.pg1.config_ip4()
39         self.pg1.config_ip6()
40
41         # pg3 in a different VRF
42         self.pg3.set_table_ip4(1)
43         self.pg3.config_ip4()
44
45     def tearDown(self):
46         super(ARPTestCase, self).tearDown()
47         self.pg0.unconfig_ip4()
48         self.pg0.unconfig_ip6()
49
50         self.pg1.unconfig_ip4()
51         self.pg1.unconfig_ip6()
52
53         self.pg3.unconfig_ip4()
54
55         for i in self.pg_interfaces:
56             i.admin_down()
57
58     def verify_arp_req(self, rx, smac, sip, dip):
59         ether = rx[Ether]
60         self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
61         self.assertEqual(ether.src, smac)
62
63         arp = rx[ARP]
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)
73
74     def verify_arp_resp(self, rx, smac, dmac, sip, dip):
75         ether = rx[Ether]
76         self.assertEqual(ether.dst, dmac)
77         self.assertEqual(ether.src, smac)
78
79         arp = rx[ARP]
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)
89
90     def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
91         ether = rx[Ether]
92         self.assertEqual(ether.dst, dmac)
93         self.assertEqual(ether.src, smac)
94
95         arp = rx[ARP]
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)
107
108     def verify_ip(self, rx, smac, dmac, sip, dip):
109         ether = rx[Ether]
110         self.assertEqual(ether.dst, dmac)
111         self.assertEqual(ether.src, smac)
112
113         ip = rx[IP]
114         self.assertEqual(ip.src, sip)
115         self.assertEqual(ip.dst, dip)
116
117     def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
118         ether = rx[Ether]
119         self.assertEqual(ether.dst, dmac)
120         self.assertEqual(ether.src, smac)
121
122         mpls = rx[MPLS]
123         self.assertTrue(mpls.label, label)
124
125         ip = rx[IP]
126         self.assertEqual(ip.src, sip)
127         self.assertEqual(ip.dst, dip)
128
129     def send_and_assert_no_replies(self, intf, pkts, remark):
130         intf.add_stream(pkts)
131         self.pg_enable_capture(self.pg_interfaces)
132         self.pg_start()
133         timeout = 1
134         for i in self.pg_interfaces:
135             i.get_capture(0, timeout=timeout)
136             i.assert_nothing_captured(remark=remark)
137             timeout = 0.1
138
139     def test_arp(self):
140         """ ARP """
141
142         #
143         # Generate some hosts on the LAN
144         #
145         self.pg1.generate_remote_hosts(9)
146
147         #
148         # Send IP traffic to one of these unresolved hosts.
149         #  expect the generation of an ARP request
150         #
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) /
154              Raw())
155
156         self.pg0.add_stream(p)
157         self.pg_enable_capture(self.pg_interfaces)
158         self.pg_start()
159
160         rx = self.pg1.get_capture(1)
161
162         self.verify_arp_req(rx[0],
163                             self.pg1.local_mac,
164                             self.pg1.local_ip4,
165                             self.pg1._remote_hosts[1].ip4)
166
167         #
168         # And a dynamic ARP entry for host 1
169         #
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()
175
176         #
177         # now we expect IP traffic forwarded
178         #
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) /
183                  Raw())
184
185         self.pg0.add_stream(dyn_p)
186         self.pg_enable_capture(self.pg_interfaces)
187         self.pg_start()
188
189         rx = self.pg1.get_capture(1)
190
191         self.verify_ip(rx[0],
192                        self.pg1.local_mac,
193                        self.pg1.remote_hosts[1].mac,
194                        self.pg0.remote_ip4,
195                        self.pg1._remote_hosts[1].ip4)
196
197         #
198         # And a Static ARP entry for host 2
199         #
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,
204                                  is_static=1)
205         static_arp.add_vpp_config()
206
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) /
211                     Raw())
212
213         self.pg0.add_stream(static_p)
214         self.pg_enable_capture(self.pg_interfaces)
215         self.pg_start()
216
217         rx = self.pg1.get_capture(1)
218
219         self.verify_ip(rx[0],
220                        self.pg1.local_mac,
221                        self.pg1.remote_hosts[2].mac,
222                        self.pg0.remote_ip4,
223                        self.pg1._remote_hosts[2].ip4)
224
225         #
226         # flap the link. dynamic ARPs get flush, statics don't
227         #
228         self.pg1.admin_down()
229         self.pg1.admin_up()
230
231         self.pg0.add_stream(static_p)
232         self.pg_enable_capture(self.pg_interfaces)
233         self.pg_start()
234         rx = self.pg1.get_capture(1)
235
236         self.verify_ip(rx[0],
237                        self.pg1.local_mac,
238                        self.pg1.remote_hosts[2].mac,
239                        self.pg0.remote_ip4,
240                        self.pg1._remote_hosts[2].ip4)
241
242         self.pg0.add_stream(dyn_p)
243         self.pg_enable_capture(self.pg_interfaces)
244         self.pg_start()
245
246         rx = self.pg1.get_capture(1)
247         self.verify_arp_req(rx[0],
248                             self.pg1.local_mac,
249                             self.pg1.local_ip4,
250                             self.pg1._remote_hosts[1].ip4)
251
252         #
253         # Send an ARP request from one of the so-far unlearned remote hosts
254         #
255         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
256                    src=self.pg1._remote_hosts[3].mac) /
257              ARP(op="who-has",
258                  hwsrc=self.pg1._remote_hosts[3].mac,
259                  pdst=self.pg1.local_ip4,
260                  psrc=self.pg1._remote_hosts[3].ip4))
261
262         self.pg1.add_stream(p)
263         self.pg_enable_capture(self.pg_interfaces)
264         self.pg_start()
265
266         rx = self.pg1.get_capture(1)
267         self.verify_arp_resp(rx[0],
268                              self.pg1.local_mac,
269                              self.pg1._remote_hosts[3].mac,
270                              self.pg1.local_ip4,
271                              self.pg1._remote_hosts[3].ip4)
272
273         #
274         # VPP should have learned the mapping for the remote host
275         #
276         self.assertTrue(find_nbr(self,
277                                  self.pg1.sw_if_index,
278                                  self.pg1._remote_hosts[3].ip4))
279         #
280         # Fire in an ARP request before the interface becomes IP enabled
281         #
282         self.pg2.generate_remote_hosts(4)
283
284         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
285              ARP(op="who-has",
286                  hwsrc=self.pg2.remote_mac,
287                  pdst=self.pg1.local_ip4,
288                  psrc=self.pg2.remote_hosts[3].ip4))
289         self.send_and_assert_no_replies(self.pg2, p,
290                                         "interface not IP enabled")
291
292         #
293         # Make pg2 un-numbered to pg1
294         #
295         self.pg2.set_unnumbered(self.pg1.sw_if_index)
296
297         #
298         # We should respond to ARP requests for the unnumbered to address
299         # once an attached route to the source is known
300         #
301         self.send_and_assert_no_replies(
302             self.pg2, p,
303             "ARP req for unnumbered address - no source")
304
305         attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
306                                    [VppRoutePath("0.0.0.0",
307                                                  self.pg2.sw_if_index)])
308         attached_host.add_vpp_config()
309
310         self.pg2.add_stream(p)
311         self.pg_enable_capture(self.pg_interfaces)
312         self.pg_start()
313
314         rx = self.pg2.get_capture(1)
315         self.verify_arp_resp(rx[0],
316                              self.pg2.local_mac,
317                              self.pg2.remote_mac,
318                              self.pg1.local_ip4,
319                              self.pg2.remote_hosts[3].ip4)
320
321         #
322         # A neighbor entry that has no associated FIB-entry
323         #
324         arp_no_fib = VppNeighbor(self,
325                                  self.pg1.sw_if_index,
326                                  self.pg1.remote_hosts[4].mac,
327                                  self.pg1.remote_hosts[4].ip4,
328                                  is_no_fib_entry=1)
329         arp_no_fib.add_vpp_config()
330
331         #
332         # check we have the neighbor, but no route
333         #
334         self.assertTrue(find_nbr(self,
335                                  self.pg1.sw_if_index,
336                                  self.pg1._remote_hosts[4].ip4))
337         self.assertFalse(find_route(self,
338                                     self.pg1._remote_hosts[4].ip4,
339                                     32))
340         #
341         # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
342         # from within pg1's subnet
343         #
344         arp_unnum = VppNeighbor(self,
345                                 self.pg2.sw_if_index,
346                                 self.pg1.remote_hosts[5].mac,
347                                 self.pg1.remote_hosts[5].ip4)
348         arp_unnum.add_vpp_config()
349
350         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
351              IP(src=self.pg0.remote_ip4,
352                 dst=self.pg1._remote_hosts[5].ip4) /
353              UDP(sport=1234, dport=1234) /
354              Raw())
355
356         self.pg0.add_stream(p)
357         self.pg_enable_capture(self.pg_interfaces)
358         self.pg_start()
359
360         rx = self.pg2.get_capture(1)
361
362         self.verify_ip(rx[0],
363                        self.pg2.local_mac,
364                        self.pg1.remote_hosts[5].mac,
365                        self.pg0.remote_ip4,
366                        self.pg1._remote_hosts[5].ip4)
367
368         #
369         # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
370         # with the unnumbered interface's address as the source
371         #
372         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
373              ARP(op="who-has",
374                  hwsrc=self.pg2.remote_mac,
375                  pdst=self.pg1.local_ip4,
376                  psrc=self.pg1.remote_hosts[6].ip4))
377
378         self.pg2.add_stream(p)
379         self.pg_enable_capture(self.pg_interfaces)
380         self.pg_start()
381
382         rx = self.pg2.get_capture(1)
383         self.verify_arp_resp(rx[0],
384                              self.pg2.local_mac,
385                              self.pg2.remote_mac,
386                              self.pg1.local_ip4,
387                              self.pg1.remote_hosts[6].ip4)
388
389         #
390         # An attached host route out of pg2 for an undiscovered hosts generates
391         # an ARP request with the unnumbered address as the source
392         #
393         att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
394                                [VppRoutePath("0.0.0.0",
395                                              self.pg2.sw_if_index)])
396         att_unnum.add_vpp_config()
397
398         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
399              IP(src=self.pg0.remote_ip4,
400                 dst=self.pg1._remote_hosts[7].ip4) /
401              UDP(sport=1234, dport=1234) /
402              Raw())
403
404         self.pg0.add_stream(p)
405         self.pg_enable_capture(self.pg_interfaces)
406         self.pg_start()
407
408         rx = self.pg2.get_capture(1)
409
410         self.verify_arp_req(rx[0],
411                             self.pg2.local_mac,
412                             self.pg1.local_ip4,
413                             self.pg1._remote_hosts[7].ip4)
414
415         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
416              ARP(op="who-has",
417                  hwsrc=self.pg2.remote_mac,
418                  pdst=self.pg1.local_ip4,
419                  psrc=self.pg1.remote_hosts[7].ip4))
420
421         self.pg2.add_stream(p)
422         self.pg_enable_capture(self.pg_interfaces)
423         self.pg_start()
424
425         rx = self.pg2.get_capture(1)
426         self.verify_arp_resp(rx[0],
427                              self.pg2.local_mac,
428                              self.pg2.remote_mac,
429                              self.pg1.local_ip4,
430                              self.pg1.remote_hosts[7].ip4)
431
432         #
433         # An attached host route as yet unresolved out of pg2 for an
434         # undiscovered host, an ARP requests begets a response.
435         #
436         att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
437                                 [VppRoutePath("0.0.0.0",
438                                               self.pg2.sw_if_index)])
439         att_unnum1.add_vpp_config()
440
441         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
442              ARP(op="who-has",
443                  hwsrc=self.pg2.remote_mac,
444                  pdst=self.pg1.local_ip4,
445                  psrc=self.pg1.remote_hosts[8].ip4))
446
447         self.pg2.add_stream(p)
448         self.pg_enable_capture(self.pg_interfaces)
449         self.pg_start()
450
451         rx = self.pg2.get_capture(1)
452         self.verify_arp_resp(rx[0],
453                              self.pg2.local_mac,
454                              self.pg2.remote_mac,
455                              self.pg1.local_ip4,
456                              self.pg1.remote_hosts[8].ip4)
457
458         #
459         # ERROR Cases
460         #  1 - don't respond to ARP request for address not within the
461         #      interface's sub-net
462         #  1b - nor within the unnumbered subnet
463         #  1c - nor within the subnet of a different interface
464         #
465         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
466              ARP(op="who-has",
467                  hwsrc=self.pg0.remote_mac,
468                  pdst="10.10.10.3",
469                  psrc=self.pg0.remote_ip4))
470         self.send_and_assert_no_replies(self.pg0, p,
471                                         "ARP req for non-local destination")
472         self.assertFalse(find_nbr(self,
473                                   self.pg0.sw_if_index,
474                                   "10.10.10.3"))
475
476         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
477              ARP(op="who-has",
478                  hwsrc=self.pg2.remote_mac,
479                  pdst="10.10.10.3",
480                  psrc=self.pg1.remote_hosts[7].ip4))
481         self.send_and_assert_no_replies(
482             self.pg0, p,
483             "ARP req for non-local destination - unnum")
484
485         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
486              ARP(op="who-has",
487                  hwsrc=self.pg0.remote_mac,
488                  pdst=self.pg1.local_ip4,
489                  psrc=self.pg1.remote_ip4))
490         self.send_and_assert_no_replies(self.pg0, p,
491                                         "ARP req diff sub-net")
492         self.assertFalse(find_nbr(self,
493                                   self.pg0.sw_if_index,
494                                   self.pg1.remote_ip4))
495
496         #
497         #  2 - don't respond to ARP request from an address not within the
498         #      interface's sub-net
499         #
500         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
501              ARP(op="who-has",
502                  hwsrc=self.pg0.remote_mac,
503                  psrc="10.10.10.3",
504                  pdst=self.pg0.local_ip4))
505         self.send_and_assert_no_replies(self.pg0, p,
506                                         "ARP req for non-local source")
507         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
508              ARP(op="who-has",
509                  hwsrc=self.pg2.remote_mac,
510                  psrc="10.10.10.3",
511                  pdst=self.pg0.local_ip4))
512         self.send_and_assert_no_replies(
513             self.pg0, p,
514             "ARP req for non-local source - unnum")
515
516         #
517         #  3 - don't respond to ARP request from an address that belongs to
518         #      the router
519         #
520         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
521              ARP(op="who-has",
522                  hwsrc=self.pg0.remote_mac,
523                  psrc=self.pg0.local_ip4,
524                  pdst=self.pg0.local_ip4))
525         self.send_and_assert_no_replies(self.pg0, p,
526                                         "ARP req for non-local source")
527
528         #
529         #  4 - don't respond to ARP requests that has mac source different
530         #      from ARP request HW source
531         #      the router
532         #
533         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
534              ARP(op="who-has",
535                  hwsrc="00:00:00:DE:AD:BE",
536                  psrc=self.pg0.remote_ip4,
537                  pdst=self.pg0.local_ip4))
538         self.send_and_assert_no_replies(self.pg0, p,
539                                         "ARP req for non-local source")
540
541         #
542         # cleanup
543         #
544         dyn_arp.remove_vpp_config()
545         static_arp.remove_vpp_config()
546         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
547
548         # need this to flush the adj-fibs
549         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
550         self.pg2.admin_down()
551
552     def test_proxy_arp(self):
553         """ Proxy ARP """
554
555         self.pg1.generate_remote_hosts(2)
556
557         #
558         # Proxy ARP rewquest packets for each interface
559         #
560         arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
561                              dst="ff:ff:ff:ff:ff:ff") /
562                        ARP(op="who-has",
563                            hwsrc=self.pg0.remote_mac,
564                            pdst="10.10.10.3",
565                            psrc=self.pg0.remote_ip4))
566         arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
567                              dst="ff:ff:ff:ff:ff:ff") /
568                        ARP(op="who-has",
569                            hwsrc=self.pg1.remote_mac,
570                            pdst="10.10.10.3",
571                            psrc=self.pg1.remote_ip4))
572         arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
573                              dst="ff:ff:ff:ff:ff:ff") /
574                        ARP(op="who-has",
575                            hwsrc=self.pg2.remote_mac,
576                            pdst="10.10.10.3",
577                            psrc=self.pg1.remote_hosts[1].ip4))
578         arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
579                              dst="ff:ff:ff:ff:ff:ff") /
580                        ARP(op="who-has",
581                            hwsrc=self.pg3.remote_mac,
582                            pdst="10.10.10.3",
583                            psrc=self.pg3.remote_ip4))
584
585         #
586         # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
587         #
588         self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
589                                     inet_pton(AF_INET, "10.10.10.124"))
590
591         #
592         # No responses are sent when the interfaces are not enabled for proxy
593         # ARP
594         #
595         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
596                                         "ARP req from unconfigured interface")
597         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
598                                         "ARP req from unconfigured interface")
599
600         #
601         # Make pg2 un-numbered to pg1
602         #  still won't reply.
603         #
604         self.pg2.set_unnumbered(self.pg1.sw_if_index)
605
606         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
607                                         "ARP req from unnumbered interface")
608
609         #
610         # Enable each interface to reply to proxy ARPs
611         #
612         for i in self.pg_interfaces:
613             i.set_proxy_arp()
614
615         #
616         # Now each of the interfaces should reply to a request to a proxied
617         # address
618         #
619         self.pg0.add_stream(arp_req_pg0)
620         self.pg_enable_capture(self.pg_interfaces)
621         self.pg_start()
622
623         rx = self.pg0.get_capture(1)
624         self.verify_arp_resp(rx[0],
625                              self.pg0.local_mac,
626                              self.pg0.remote_mac,
627                              "10.10.10.3",
628                              self.pg0.remote_ip4)
629
630         self.pg1.add_stream(arp_req_pg1)
631         self.pg_enable_capture(self.pg_interfaces)
632         self.pg_start()
633
634         rx = self.pg1.get_capture(1)
635         self.verify_arp_resp(rx[0],
636                              self.pg1.local_mac,
637                              self.pg1.remote_mac,
638                              "10.10.10.3",
639                              self.pg1.remote_ip4)
640
641         self.pg2.add_stream(arp_req_pg2)
642         self.pg_enable_capture(self.pg_interfaces)
643         self.pg_start()
644
645         rx = self.pg2.get_capture(1)
646         self.verify_arp_resp(rx[0],
647                              self.pg2.local_mac,
648                              self.pg2.remote_mac,
649                              "10.10.10.3",
650                              self.pg1.remote_hosts[1].ip4)
651
652         #
653         # A request for an address out of the configured range
654         #
655         arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
656                                 dst="ff:ff:ff:ff:ff:ff") /
657                           ARP(op="who-has",
658                               hwsrc=self.pg1.remote_mac,
659                               pdst="10.10.10.125",
660                               psrc=self.pg1.remote_ip4))
661         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
662                                         "ARP req out of range HI")
663         arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
664                                  dst="ff:ff:ff:ff:ff:ff") /
665                            ARP(op="who-has",
666                                hwsrc=self.pg1.remote_mac,
667                                pdst="10.10.10.1",
668                                psrc=self.pg1.remote_ip4))
669         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
670                                         "ARP req out of range Low")
671
672         #
673         # Request for an address in the proxy range but from an interface
674         # in a different VRF
675         #
676         self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
677                                         "ARP req from different VRF")
678
679         #
680         # Disable Each interface for proxy ARP
681         #  - expect none to respond
682         #
683         for i in self.pg_interfaces:
684             i.set_proxy_arp(0)
685
686         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
687                                         "ARP req from disable")
688         self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
689                                         "ARP req from disable")
690         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
691                                         "ARP req from disable")
692
693         #
694         # clean up on interface 2
695         #
696         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
697
698     def test_mpls(self):
699         """ MPLS """
700
701         #
702         # Interface 2 does not yet have ip4 config
703         #
704         self.pg2.config_ip4()
705         self.pg2.generate_remote_hosts(2)
706
707         #
708         # Add a reoute with out going label via an ARP unresolved next-hop
709         #
710         ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
711                                  [VppRoutePath(self.pg2.remote_hosts[1].ip4,
712                                                self.pg2.sw_if_index,
713                                                labels=[55])])
714         ip_10_0_0_1.add_vpp_config()
715
716         #
717         # packets should generate an ARP request
718         #
719         p = (Ether(src=self.pg0.remote_mac,
720                    dst=self.pg0.local_mac) /
721              IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
722              UDP(sport=1234, dport=1234) /
723              Raw('\xa5' * 100))
724
725         self.pg0.add_stream(p)
726         self.pg_enable_capture(self.pg_interfaces)
727         self.pg_start()
728
729         rx = self.pg2.get_capture(1)
730         self.verify_arp_req(rx[0],
731                             self.pg2.local_mac,
732                             self.pg2.local_ip4,
733                             self.pg2._remote_hosts[1].ip4)
734
735         #
736         # now resolve the neighbours
737         #
738         self.pg2.configure_ipv4_neighbors()
739
740         #
741         # Now packet should be properly MPLS encapped.
742         #  This verifies that MPLS link-type adjacencies are completed
743         #  when the ARP entry resolves
744         #
745         self.pg0.add_stream(p)
746         self.pg_enable_capture(self.pg_interfaces)
747         self.pg_start()
748
749         rx = self.pg2.get_capture(1)
750         self.verify_ip_o_mpls(rx[0],
751                               self.pg2.local_mac,
752                               self.pg2.remote_hosts[1].mac,
753                               55,
754                               self.pg0.remote_ip4,
755                               "10.0.0.1")
756         self.pg2.unconfig_ip4()
757
758     def test_arp_vrrp(self):
759         """ ARP reply with VRRP virtual src hw addr """
760
761         #
762         # IP packet destined for pg1 remote host arrives on pg0 resulting
763         # in an ARP request for the address of the remote host on pg1
764         #
765         p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
766               IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
767               UDP(sport=1234, dport=1234) /
768               Raw())
769
770         self.pg0.add_stream(p0)
771         self.pg_enable_capture(self.pg_interfaces)
772         self.pg_start()
773
774         rx1 = self.pg1.get_capture(1)
775
776         self.verify_arp_req(rx1[0],
777                             self.pg1.local_mac,
778                             self.pg1.local_ip4,
779                             self.pg1.remote_ip4)
780
781         #
782         # ARP reply for address of pg1 remote host arrives on pg1 with
783         # the hw src addr set to a value in the VRRP IPv4 range of
784         # MAC addresses
785         #
786         p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
787               ARP(op="is-at", hwdst=self.pg1.local_mac,
788                   hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
789                   psrc=self.pg1.remote_ip4))
790
791         self.pg1.add_stream(p1)
792         self.pg_enable_capture(self.pg_interfaces)
793         self.pg_start()
794
795         #
796         # IP packet destined for pg1 remote host arrives on pg0 again.
797         # VPP should have an ARP entry for that address now and the packet
798         # should be sent out pg1.
799         #
800         self.pg0.add_stream(p0)
801         self.pg_enable_capture(self.pg_interfaces)
802         self.pg_start()
803
804         rx1 = self.pg1.get_capture(1)
805
806         self.verify_ip(rx1[0],
807                        self.pg1.local_mac,
808                        "00:00:5e:00:01:09",
809                        self.pg0.remote_ip4,
810                        self.pg1.remote_ip4)
811
812         self.pg1.admin_down()
813         self.pg1.admin_up()
814
815 if __name__ == '__main__':
816     unittest.main(testRunner=VppTestRunner)