ARP: ignore non-connected routes and non-interface sources when determing if source...
[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, Dot1Q
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(11)
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         pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
290               Dot1Q(vlan=0) /
291               ARP(op="who-has",
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")
297
298         #
299         # Make pg2 un-numbered to pg1
300         #
301         self.pg2.set_unnumbered(self.pg1.sw_if_index)
302
303         #
304         # We should respond to ARP requests for the unnumbered to address
305         # once an attached route to the source is known
306         #
307         self.send_and_assert_no_replies(
308             self.pg2, p,
309             "ARP req for unnumbered address - no source")
310
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()
315
316         self.pg2.add_stream(p)
317         self.pg_enable_capture(self.pg_interfaces)
318         self.pg_start()
319
320         rx = self.pg2.get_capture(1)
321         self.verify_arp_resp(rx[0],
322                              self.pg2.local_mac,
323                              self.pg2.remote_mac,
324                              self.pg1.local_ip4,
325                              self.pg2.remote_hosts[3].ip4)
326
327         self.pg2.add_stream(pt)
328         self.pg_enable_capture(self.pg_interfaces)
329         self.pg_start()
330
331         rx = self.pg2.get_capture(1)
332         self.verify_arp_resp(rx[0],
333                              self.pg2.local_mac,
334                              self.pg2.remote_mac,
335                              self.pg1.local_ip4,
336                              self.pg2.remote_hosts[3].ip4)
337
338         #
339         # A neighbor entry that has no associated FIB-entry
340         #
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,
345                                  is_no_fib_entry=1)
346         arp_no_fib.add_vpp_config()
347
348         #
349         # check we have the neighbor, but no route
350         #
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,
356                                     32))
357         #
358         # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
359         # from within pg1's subnet
360         #
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()
366
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) /
371              Raw())
372
373         self.pg0.add_stream(p)
374         self.pg_enable_capture(self.pg_interfaces)
375         self.pg_start()
376
377         rx = self.pg2.get_capture(1)
378
379         self.verify_ip(rx[0],
380                        self.pg2.local_mac,
381                        self.pg1.remote_hosts[5].mac,
382                        self.pg0.remote_ip4,
383                        self.pg1._remote_hosts[5].ip4)
384
385         #
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
388         #
389         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
390              ARP(op="who-has",
391                  hwsrc=self.pg2.remote_mac,
392                  pdst=self.pg1.local_ip4,
393                  psrc=self.pg1.remote_hosts[6].ip4))
394
395         self.pg2.add_stream(p)
396         self.pg_enable_capture(self.pg_interfaces)
397         self.pg_start()
398
399         rx = self.pg2.get_capture(1)
400         self.verify_arp_resp(rx[0],
401                              self.pg2.local_mac,
402                              self.pg2.remote_mac,
403                              self.pg1.local_ip4,
404                              self.pg1.remote_hosts[6].ip4)
405
406         #
407         # An attached host route out of pg2 for an undiscovered hosts generates
408         # an ARP request with the unnumbered address as the source
409         #
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()
414
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) /
419              Raw())
420
421         self.pg0.add_stream(p)
422         self.pg_enable_capture(self.pg_interfaces)
423         self.pg_start()
424
425         rx = self.pg2.get_capture(1)
426
427         self.verify_arp_req(rx[0],
428                             self.pg2.local_mac,
429                             self.pg1.local_ip4,
430                             self.pg1._remote_hosts[7].ip4)
431
432         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
433              ARP(op="who-has",
434                  hwsrc=self.pg2.remote_mac,
435                  pdst=self.pg1.local_ip4,
436                  psrc=self.pg1.remote_hosts[7].ip4))
437
438         self.pg2.add_stream(p)
439         self.pg_enable_capture(self.pg_interfaces)
440         self.pg_start()
441
442         rx = self.pg2.get_capture(1)
443         self.verify_arp_resp(rx[0],
444                              self.pg2.local_mac,
445                              self.pg2.remote_mac,
446                              self.pg1.local_ip4,
447                              self.pg1.remote_hosts[7].ip4)
448
449         #
450         # An attached host route as yet unresolved out of pg2 for an
451         # undiscovered host, an ARP requests begets a response.
452         #
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()
457
458         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
459              ARP(op="who-has",
460                  hwsrc=self.pg2.remote_mac,
461                  pdst=self.pg1.local_ip4,
462                  psrc=self.pg1.remote_hosts[8].ip4))
463
464         self.pg2.add_stream(p)
465         self.pg_enable_capture(self.pg_interfaces)
466         self.pg_start()
467
468         rx = self.pg2.get_capture(1)
469         self.verify_arp_resp(rx[0],
470                              self.pg2.local_mac,
471                              self.pg2.remote_mac,
472                              self.pg1.local_ip4,
473                              self.pg1.remote_hosts[8].ip4)
474
475         #
476         # Send an ARP request from one of the so-far unlearned remote hosts
477         # with a VLAN0 tag
478         #
479         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
480                    src=self.pg1._remote_hosts[9].mac) /
481              Dot1Q(vlan=0) /
482              ARP(op="who-has",
483                  hwsrc=self.pg1._remote_hosts[9].mac,
484                  pdst=self.pg1.local_ip4,
485                  psrc=self.pg1._remote_hosts[9].ip4))
486
487         self.pg1.add_stream(p)
488         self.pg_enable_capture(self.pg_interfaces)
489         self.pg_start()
490
491         rx = self.pg1.get_capture(1)
492         self.verify_arp_resp(rx[0],
493                              self.pg1.local_mac,
494                              self.pg1._remote_hosts[9].mac,
495                              self.pg1.local_ip4,
496                              self.pg1._remote_hosts[9].ip4)
497
498         #
499         # Add a hierachy of routes for a host in the sub-net.
500         # Should still get an ARP resp since the cover is attached
501         #
502         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
503              ARP(op="who-has",
504                  hwsrc=self.pg1.remote_mac,
505                  pdst=self.pg1.local_ip4,
506                  psrc=self.pg1.remote_hosts[10].ip4))
507
508         r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
509                         [VppRoutePath(self.pg1.remote_hosts[10].ip4,
510                                       self.pg1.sw_if_index)])
511         r1.add_vpp_config()
512
513         self.pg1.add_stream(p)
514         self.pg_enable_capture(self.pg_interfaces)
515         self.pg_start()
516         rx = self.pg1.get_capture(1)
517         self.verify_arp_resp(rx[0],
518                              self.pg1.local_mac,
519                              self.pg1.remote_mac,
520                              self.pg1.local_ip4,
521                              self.pg1.remote_hosts[10].ip4)
522
523         r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
524                         [VppRoutePath(self.pg1.remote_hosts[10].ip4,
525                                       self.pg1.sw_if_index)])
526         r2.add_vpp_config()
527
528         self.pg1.add_stream(p)
529         self.pg_enable_capture(self.pg_interfaces)
530         self.pg_start()
531         rx = self.pg1.get_capture(1)
532         self.verify_arp_resp(rx[0],
533                              self.pg1.local_mac,
534                              self.pg1.remote_mac,
535                              self.pg1.local_ip4,
536                              self.pg1.remote_hosts[10].ip4)
537
538         #
539         # add an ARP entry that's not on the sub-net and so whose
540         # adj-fib fails the refinement check. then send an ARP request
541         # from that source
542         #
543         a1 = VppNeighbor(self,
544                          self.pg0.sw_if_index,
545                          self.pg0.remote_mac,
546                          "100.100.100.50")
547         a1.add_vpp_config()
548
549         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
550              ARP(op="who-has",
551                  hwsrc=self.pg0.remote_mac,
552                  psrc="100.100.100.50",
553                  pdst=self.pg0.remote_ip4))
554         self.send_and_assert_no_replies(self.pg0, p,
555                                         "ARP req for from failed adj-fib")
556
557         #
558         # ERROR Cases
559         #  1 - don't respond to ARP request for address not within the
560         #      interface's sub-net
561         #  1b - nor within the unnumbered subnet
562         #  1c - nor within the subnet of a different interface
563         #
564         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
565              ARP(op="who-has",
566                  hwsrc=self.pg0.remote_mac,
567                  pdst="10.10.10.3",
568                  psrc=self.pg0.remote_ip4))
569         self.send_and_assert_no_replies(self.pg0, p,
570                                         "ARP req for non-local destination")
571         self.assertFalse(find_nbr(self,
572                                   self.pg0.sw_if_index,
573                                   "10.10.10.3"))
574
575         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
576              ARP(op="who-has",
577                  hwsrc=self.pg2.remote_mac,
578                  pdst="10.10.10.3",
579                  psrc=self.pg1.remote_hosts[7].ip4))
580         self.send_and_assert_no_replies(
581             self.pg0, p,
582             "ARP req for non-local destination - unnum")
583
584         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
585              ARP(op="who-has",
586                  hwsrc=self.pg0.remote_mac,
587                  pdst=self.pg1.local_ip4,
588                  psrc=self.pg1.remote_ip4))
589         self.send_and_assert_no_replies(self.pg0, p,
590                                         "ARP req diff sub-net")
591         self.assertFalse(find_nbr(self,
592                                   self.pg0.sw_if_index,
593                                   self.pg1.remote_ip4))
594
595         #
596         #  2 - don't respond to ARP request from an address not within the
597         #      interface's sub-net
598         #   2b - to a prxied address
599         #   2c - not within a differents interface's sub-net
600         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
601              ARP(op="who-has",
602                  hwsrc=self.pg0.remote_mac,
603                  psrc="10.10.10.3",
604                  pdst=self.pg0.local_ip4))
605         self.send_and_assert_no_replies(self.pg0, p,
606                                         "ARP req for non-local source")
607         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
608              ARP(op="who-has",
609                  hwsrc=self.pg2.remote_mac,
610                  psrc="10.10.10.3",
611                  pdst=self.pg0.local_ip4))
612         self.send_and_assert_no_replies(
613             self.pg0, p,
614             "ARP req for non-local source - unnum")
615         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
616              ARP(op="who-has",
617                  hwsrc=self.pg0.remote_mac,
618                  psrc=self.pg1.remote_ip4,
619                  pdst=self.pg0.local_ip4))
620         self.send_and_assert_no_replies(self.pg0, p,
621                                         "ARP req for non-local source 2c")
622
623         #
624         #  3 - don't respond to ARP request from an address that belongs to
625         #      the router
626         #
627         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
628              ARP(op="who-has",
629                  hwsrc=self.pg0.remote_mac,
630                  psrc=self.pg0.local_ip4,
631                  pdst=self.pg0.local_ip4))
632         self.send_and_assert_no_replies(self.pg0, p,
633                                         "ARP req for non-local source")
634
635         #
636         #  4 - don't respond to ARP requests that has mac source different
637         #      from ARP request HW source
638         #      the router
639         #
640         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
641              ARP(op="who-has",
642                  hwsrc="00:00:00:DE:AD:BE",
643                  psrc=self.pg0.remote_ip4,
644                  pdst=self.pg0.local_ip4))
645         self.send_and_assert_no_replies(self.pg0, p,
646                                         "ARP req for non-local source")
647
648         #
649         # cleanup
650         #
651         dyn_arp.remove_vpp_config()
652         static_arp.remove_vpp_config()
653         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
654
655         # need this to flush the adj-fibs
656         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
657         self.pg2.admin_down()
658         self.pg1.admin_down()
659
660     def test_proxy_arp(self):
661         """ Proxy ARP """
662
663         self.pg1.generate_remote_hosts(2)
664
665         #
666         # Proxy ARP rewquest packets for each interface
667         #
668         arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
669                              dst="ff:ff:ff:ff:ff:ff") /
670                        ARP(op="who-has",
671                            hwsrc=self.pg0.remote_mac,
672                            pdst="10.10.10.3",
673                            psrc=self.pg0.remote_ip4))
674         arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
675                                     dst="ff:ff:ff:ff:ff:ff") /
676                               Dot1Q(vlan=0) /
677                               ARP(op="who-has",
678                                   hwsrc=self.pg0.remote_mac,
679                                   pdst="10.10.10.3",
680                                   psrc=self.pg0.remote_ip4))
681         arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
682                              dst="ff:ff:ff:ff:ff:ff") /
683                        ARP(op="who-has",
684                            hwsrc=self.pg1.remote_mac,
685                            pdst="10.10.10.3",
686                            psrc=self.pg1.remote_ip4))
687         arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
688                              dst="ff:ff:ff:ff:ff:ff") /
689                        ARP(op="who-has",
690                            hwsrc=self.pg2.remote_mac,
691                            pdst="10.10.10.3",
692                            psrc=self.pg1.remote_hosts[1].ip4))
693         arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
694                              dst="ff:ff:ff:ff:ff:ff") /
695                        ARP(op="who-has",
696                            hwsrc=self.pg3.remote_mac,
697                            pdst="10.10.10.3",
698                            psrc=self.pg3.remote_ip4))
699
700         #
701         # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
702         #
703         self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
704                                     inet_pton(AF_INET, "10.10.10.124"))
705
706         #
707         # No responses are sent when the interfaces are not enabled for proxy
708         # ARP
709         #
710         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
711                                         "ARP req from unconfigured interface")
712         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
713                                         "ARP req from unconfigured interface")
714
715         #
716         # Make pg2 un-numbered to pg1
717         #  still won't reply.
718         #
719         self.pg2.set_unnumbered(self.pg1.sw_if_index)
720
721         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
722                                         "ARP req from unnumbered interface")
723
724         #
725         # Enable each interface to reply to proxy ARPs
726         #
727         for i in self.pg_interfaces:
728             i.set_proxy_arp()
729
730         #
731         # Now each of the interfaces should reply to a request to a proxied
732         # address
733         #
734         self.pg0.add_stream(arp_req_pg0)
735         self.pg_enable_capture(self.pg_interfaces)
736         self.pg_start()
737
738         rx = self.pg0.get_capture(1)
739         self.verify_arp_resp(rx[0],
740                              self.pg0.local_mac,
741                              self.pg0.remote_mac,
742                              "10.10.10.3",
743                              self.pg0.remote_ip4)
744
745         self.pg0.add_stream(arp_req_pg0_tagged)
746         self.pg_enable_capture(self.pg_interfaces)
747         self.pg_start()
748
749         rx = self.pg0.get_capture(1)
750         self.verify_arp_resp(rx[0],
751                              self.pg0.local_mac,
752                              self.pg0.remote_mac,
753                              "10.10.10.3",
754                              self.pg0.remote_ip4)
755
756         self.pg1.add_stream(arp_req_pg1)
757         self.pg_enable_capture(self.pg_interfaces)
758         self.pg_start()
759
760         rx = self.pg1.get_capture(1)
761         self.verify_arp_resp(rx[0],
762                              self.pg1.local_mac,
763                              self.pg1.remote_mac,
764                              "10.10.10.3",
765                              self.pg1.remote_ip4)
766
767         self.pg2.add_stream(arp_req_pg2)
768         self.pg_enable_capture(self.pg_interfaces)
769         self.pg_start()
770
771         rx = self.pg2.get_capture(1)
772         self.verify_arp_resp(rx[0],
773                              self.pg2.local_mac,
774                              self.pg2.remote_mac,
775                              "10.10.10.3",
776                              self.pg1.remote_hosts[1].ip4)
777
778         #
779         # A request for an address out of the configured range
780         #
781         arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
782                                 dst="ff:ff:ff:ff:ff:ff") /
783                           ARP(op="who-has",
784                               hwsrc=self.pg1.remote_mac,
785                               pdst="10.10.10.125",
786                               psrc=self.pg1.remote_ip4))
787         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
788                                         "ARP req out of range HI")
789         arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
790                                  dst="ff:ff:ff:ff:ff:ff") /
791                            ARP(op="who-has",
792                                hwsrc=self.pg1.remote_mac,
793                                pdst="10.10.10.1",
794                                psrc=self.pg1.remote_ip4))
795         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
796                                         "ARP req out of range Low")
797
798         #
799         # Request for an address in the proxy range but from an interface
800         # in a different VRF
801         #
802         self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
803                                         "ARP req from different VRF")
804
805         #
806         # Disable Each interface for proxy ARP
807         #  - expect none to respond
808         #
809         for i in self.pg_interfaces:
810             i.set_proxy_arp(0)
811
812         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
813                                         "ARP req from disable")
814         self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
815                                         "ARP req from disable")
816         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
817                                         "ARP req from disable")
818
819         #
820         # clean up on interface 2
821         #
822         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
823
824     def test_mpls(self):
825         """ MPLS """
826
827         #
828         # Interface 2 does not yet have ip4 config
829         #
830         self.pg2.config_ip4()
831         self.pg2.generate_remote_hosts(2)
832
833         #
834         # Add a reoute with out going label via an ARP unresolved next-hop
835         #
836         ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
837                                  [VppRoutePath(self.pg2.remote_hosts[1].ip4,
838                                                self.pg2.sw_if_index,
839                                                labels=[55])])
840         ip_10_0_0_1.add_vpp_config()
841
842         #
843         # packets should generate an ARP request
844         #
845         p = (Ether(src=self.pg0.remote_mac,
846                    dst=self.pg0.local_mac) /
847              IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
848              UDP(sport=1234, dport=1234) /
849              Raw('\xa5' * 100))
850
851         self.pg0.add_stream(p)
852         self.pg_enable_capture(self.pg_interfaces)
853         self.pg_start()
854
855         rx = self.pg2.get_capture(1)
856         self.verify_arp_req(rx[0],
857                             self.pg2.local_mac,
858                             self.pg2.local_ip4,
859                             self.pg2._remote_hosts[1].ip4)
860
861         #
862         # now resolve the neighbours
863         #
864         self.pg2.configure_ipv4_neighbors()
865
866         #
867         # Now packet should be properly MPLS encapped.
868         #  This verifies that MPLS link-type adjacencies are completed
869         #  when the ARP entry resolves
870         #
871         self.pg0.add_stream(p)
872         self.pg_enable_capture(self.pg_interfaces)
873         self.pg_start()
874
875         rx = self.pg2.get_capture(1)
876         self.verify_ip_o_mpls(rx[0],
877                               self.pg2.local_mac,
878                               self.pg2.remote_hosts[1].mac,
879                               55,
880                               self.pg0.remote_ip4,
881                               "10.0.0.1")
882         self.pg2.unconfig_ip4()
883
884     def test_arp_vrrp(self):
885         """ ARP reply with VRRP virtual src hw addr """
886
887         #
888         # IP packet destined for pg1 remote host arrives on pg0 resulting
889         # in an ARP request for the address of the remote host on pg1
890         #
891         p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
892               IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
893               UDP(sport=1234, dport=1234) /
894               Raw())
895
896         self.pg0.add_stream(p0)
897         self.pg_enable_capture(self.pg_interfaces)
898         self.pg_start()
899
900         rx1 = self.pg1.get_capture(1)
901
902         self.verify_arp_req(rx1[0],
903                             self.pg1.local_mac,
904                             self.pg1.local_ip4,
905                             self.pg1.remote_ip4)
906
907         #
908         # ARP reply for address of pg1 remote host arrives on pg1 with
909         # the hw src addr set to a value in the VRRP IPv4 range of
910         # MAC addresses
911         #
912         p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
913               ARP(op="is-at", hwdst=self.pg1.local_mac,
914                   hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
915                   psrc=self.pg1.remote_ip4))
916
917         self.pg1.add_stream(p1)
918         self.pg_enable_capture(self.pg_interfaces)
919         self.pg_start()
920
921         #
922         # IP packet destined for pg1 remote host arrives on pg0 again.
923         # VPP should have an ARP entry for that address now and the packet
924         # should be sent out pg1.
925         #
926         self.pg0.add_stream(p0)
927         self.pg_enable_capture(self.pg_interfaces)
928         self.pg_start()
929
930         rx1 = self.pg1.get_capture(1)
931
932         self.verify_ip(rx1[0],
933                        self.pg1.local_mac,
934                        "00:00:5e:00:01:09",
935                        self.pg0.remote_ip4,
936                        self.pg1.remote_ip4)
937
938         self.pg1.admin_down()
939         self.pg1.admin_up()
940
941     def test_arp_duplicates(self):
942         """ ARP Duplicates"""
943
944         #
945         # Generate some hosts on the LAN
946         #
947         self.pg1.generate_remote_hosts(3)
948
949         #
950         # Add host 1 on pg1 and pg2
951         #
952         arp_pg1 = VppNeighbor(self,
953                               self.pg1.sw_if_index,
954                               self.pg1.remote_hosts[1].mac,
955                               self.pg1.remote_hosts[1].ip4)
956         arp_pg1.add_vpp_config()
957         arp_pg2 = VppNeighbor(self,
958                               self.pg2.sw_if_index,
959                               self.pg2.remote_mac,
960                               self.pg1.remote_hosts[1].ip4)
961         arp_pg2.add_vpp_config()
962
963         #
964         # IP packet destined for pg1 remote host arrives on pg1 again.
965         #
966         p = (Ether(dst=self.pg0.local_mac,
967                    src=self.pg0.remote_mac) /
968              IP(src=self.pg0.remote_ip4,
969                 dst=self.pg1.remote_hosts[1].ip4) /
970              UDP(sport=1234, dport=1234) /
971              Raw())
972
973         self.pg0.add_stream(p)
974         self.pg_enable_capture(self.pg_interfaces)
975         self.pg_start()
976
977         rx1 = self.pg1.get_capture(1)
978
979         self.verify_ip(rx1[0],
980                        self.pg1.local_mac,
981                        self.pg1.remote_hosts[1].mac,
982                        self.pg0.remote_ip4,
983                        self.pg1.remote_hosts[1].ip4)
984
985         #
986         # remove the duplicate on pg1
987         # packet stream shoud generate ARPs out of pg1
988         #
989         arp_pg1.remove_vpp_config()
990
991         self.pg0.add_stream(p)
992         self.pg_enable_capture(self.pg_interfaces)
993         self.pg_start()
994
995         rx1 = self.pg1.get_capture(1)
996
997         self.verify_arp_req(rx1[0],
998                             self.pg1.local_mac,
999                             self.pg1.local_ip4,
1000                             self.pg1.remote_hosts[1].ip4)
1001
1002         #
1003         # Add it back
1004         #
1005         arp_pg1.add_vpp_config()
1006
1007         self.pg0.add_stream(p)
1008         self.pg_enable_capture(self.pg_interfaces)
1009         self.pg_start()
1010
1011         rx1 = self.pg1.get_capture(1)
1012
1013         self.verify_ip(rx1[0],
1014                        self.pg1.local_mac,
1015                        self.pg1.remote_hosts[1].mac,
1016                        self.pg0.remote_ip4,
1017                        self.pg1.remote_hosts[1].ip4)
1018
1019
1020 if __name__ == '__main__':
1021     unittest.main(testRunner=VppTestRunner)