Tests Cleanup: Fix missing calls to setUpClass/tearDownClass.
[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     VppIpTable, DpoProto
10 from vpp_papi import VppEnum
11
12 import scapy.compat
13 from scapy.packet import Raw
14 from scapy.layers.l2 import Ether, ARP, Dot1Q
15 from scapy.layers.inet import IP, UDP
16 from scapy.layers.inet6 import IPv6
17 from scapy.contrib.mpls import MPLS
18 from scapy.layers.inet6 import IPv6
19
20 # not exported by scapy, so redefined here
21 arp_opts = {"who-has": 1, "is-at": 2}
22
23
24 class ARPTestCase(VppTestCase):
25     """ ARP Test Case """
26
27     @classmethod
28     def setUpClass(cls):
29         super(ARPTestCase, cls).setUpClass()
30
31     @classmethod
32     def tearDownClass(cls):
33         super(ARPTestCase, cls).tearDownClass()
34
35     def setUp(self):
36         super(ARPTestCase, self).setUp()
37
38         # create 3 pg interfaces
39         self.create_pg_interfaces(range(4))
40
41         # pg0 configured with ip4 and 6 addresses used for input
42         # pg1 configured with ip4 and 6 addresses used for output
43         # pg2 is unnumbered to pg0
44         for i in self.pg_interfaces:
45             i.admin_up()
46
47         self.pg0.config_ip4()
48         self.pg0.config_ip6()
49         self.pg0.resolve_arp()
50
51         self.pg1.config_ip4()
52         self.pg1.config_ip6()
53
54         # pg3 in a different VRF
55         self.tbl = VppIpTable(self, 1)
56         self.tbl.add_vpp_config()
57
58         self.pg3.set_table_ip4(1)
59         self.pg3.config_ip4()
60
61     def tearDown(self):
62         self.pg0.unconfig_ip4()
63         self.pg0.unconfig_ip6()
64
65         self.pg1.unconfig_ip4()
66         self.pg1.unconfig_ip6()
67
68         self.pg3.unconfig_ip4()
69         self.pg3.set_table_ip4(0)
70
71         for i in self.pg_interfaces:
72             i.admin_down()
73
74         super(ARPTestCase, self).tearDown()
75
76     def verify_arp_req(self, rx, smac, sip, dip):
77         ether = rx[Ether]
78         self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
79         self.assertEqual(ether.src, smac)
80
81         arp = rx[ARP]
82         self.assertEqual(arp.hwtype, 1)
83         self.assertEqual(arp.ptype, 0x800)
84         self.assertEqual(arp.hwlen, 6)
85         self.assertEqual(arp.plen, 4)
86         self.assertEqual(arp.op, arp_opts["who-has"])
87         self.assertEqual(arp.hwsrc, smac)
88         self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
89         self.assertEqual(arp.psrc, sip)
90         self.assertEqual(arp.pdst, dip)
91
92     def verify_arp_resp(self, rx, smac, dmac, sip, dip):
93         ether = rx[Ether]
94         self.assertEqual(ether.dst, dmac)
95         self.assertEqual(ether.src, smac)
96
97         arp = rx[ARP]
98         self.assertEqual(arp.hwtype, 1)
99         self.assertEqual(arp.ptype, 0x800)
100         self.assertEqual(arp.hwlen, 6)
101         self.assertEqual(arp.plen, 4)
102         self.assertEqual(arp.op, arp_opts["is-at"])
103         self.assertEqual(arp.hwsrc, smac)
104         self.assertEqual(arp.hwdst, dmac)
105         self.assertEqual(arp.psrc, sip)
106         self.assertEqual(arp.pdst, dip)
107
108     def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
109         ether = rx[Ether]
110         self.assertEqual(ether.dst, dmac)
111         self.assertEqual(ether.src, smac)
112
113         arp = rx[ARP]
114         self.assertEqual(arp.hwtype, 1)
115         self.assertEqual(arp.ptype, 0x800)
116         self.assertEqual(arp.hwlen, 6)
117         self.assertEqual(arp.plen, 4)
118         self.assertEqual(arp.op, arp_opts["is-at"])
119         self.assertNotEqual(arp.hwsrc, smac)
120         self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
121                         "00:00:5E:00:01" in arp.hwsrc)
122         self.assertEqual(arp.hwdst, dmac)
123         self.assertEqual(arp.psrc, sip)
124         self.assertEqual(arp.pdst, dip)
125
126     def verify_ip(self, rx, smac, dmac, sip, dip):
127         ether = rx[Ether]
128         self.assertEqual(ether.dst, dmac)
129         self.assertEqual(ether.src, smac)
130
131         ip = rx[IP]
132         self.assertEqual(ip.src, sip)
133         self.assertEqual(ip.dst, dip)
134
135     def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
136         ether = rx[Ether]
137         self.assertEqual(ether.dst, dmac)
138         self.assertEqual(ether.src, smac)
139
140         mpls = rx[MPLS]
141         self.assertTrue(mpls.label, label)
142
143         ip = rx[IP]
144         self.assertEqual(ip.src, sip)
145         self.assertEqual(ip.dst, dip)
146
147     def test_arp(self):
148         """ ARP """
149
150         #
151         # Generate some hosts on the LAN
152         #
153         self.pg1.generate_remote_hosts(11)
154
155         #
156         # Send IP traffic to one of these unresolved hosts.
157         #  expect the generation of an ARP request
158         #
159         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
160              IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
161              UDP(sport=1234, dport=1234) /
162              Raw())
163
164         self.pg0.add_stream(p)
165         self.pg_enable_capture(self.pg_interfaces)
166         self.pg_start()
167
168         rx = self.pg1.get_capture(1)
169
170         self.verify_arp_req(rx[0],
171                             self.pg1.local_mac,
172                             self.pg1.local_ip4,
173                             self.pg1._remote_hosts[1].ip4)
174
175         #
176         # And a dynamic ARP entry for host 1
177         #
178         dyn_arp = VppNeighbor(self,
179                               self.pg1.sw_if_index,
180                               self.pg1.remote_hosts[1].mac,
181                               self.pg1.remote_hosts[1].ip4)
182         dyn_arp.add_vpp_config()
183
184         #
185         # now we expect IP traffic forwarded
186         #
187         dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
188                  IP(src=self.pg0.remote_ip4,
189                     dst=self.pg1._remote_hosts[1].ip4) /
190                  UDP(sport=1234, dport=1234) /
191                  Raw())
192
193         self.pg0.add_stream(dyn_p)
194         self.pg_enable_capture(self.pg_interfaces)
195         self.pg_start()
196
197         rx = self.pg1.get_capture(1)
198
199         self.verify_ip(rx[0],
200                        self.pg1.local_mac,
201                        self.pg1.remote_hosts[1].mac,
202                        self.pg0.remote_ip4,
203                        self.pg1._remote_hosts[1].ip4)
204
205         #
206         # And a Static ARP entry for host 2
207         #
208         static_arp = VppNeighbor(self,
209                                  self.pg1.sw_if_index,
210                                  self.pg1.remote_hosts[2].mac,
211                                  self.pg1.remote_hosts[2].ip4,
212                                  is_static=1)
213         static_arp.add_vpp_config()
214
215         static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
216                     IP(src=self.pg0.remote_ip4,
217                        dst=self.pg1._remote_hosts[2].ip4) /
218                     UDP(sport=1234, dport=1234) /
219                     Raw())
220
221         self.pg0.add_stream(static_p)
222         self.pg_enable_capture(self.pg_interfaces)
223         self.pg_start()
224
225         rx = self.pg1.get_capture(1)
226
227         self.verify_ip(rx[0],
228                        self.pg1.local_mac,
229                        self.pg1.remote_hosts[2].mac,
230                        self.pg0.remote_ip4,
231                        self.pg1._remote_hosts[2].ip4)
232
233         #
234         # flap the link. dynamic ARPs get flush, statics don't
235         #
236         self.pg1.admin_down()
237         self.pg1.admin_up()
238
239         self.pg0.add_stream(static_p)
240         self.pg_enable_capture(self.pg_interfaces)
241         self.pg_start()
242         rx = self.pg1.get_capture(1)
243
244         self.verify_ip(rx[0],
245                        self.pg1.local_mac,
246                        self.pg1.remote_hosts[2].mac,
247                        self.pg0.remote_ip4,
248                        self.pg1._remote_hosts[2].ip4)
249
250         self.pg0.add_stream(dyn_p)
251         self.pg_enable_capture(self.pg_interfaces)
252         self.pg_start()
253
254         rx = self.pg1.get_capture(1)
255         self.verify_arp_req(rx[0],
256                             self.pg1.local_mac,
257                             self.pg1.local_ip4,
258                             self.pg1._remote_hosts[1].ip4)
259
260         #
261         # Send an ARP request from one of the so-far unlearned remote hosts
262         #
263         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
264                    src=self.pg1._remote_hosts[3].mac) /
265              ARP(op="who-has",
266                  hwsrc=self.pg1._remote_hosts[3].mac,
267                  pdst=self.pg1.local_ip4,
268                  psrc=self.pg1._remote_hosts[3].ip4))
269
270         self.pg1.add_stream(p)
271         self.pg_enable_capture(self.pg_interfaces)
272         self.pg_start()
273
274         rx = self.pg1.get_capture(1)
275         self.verify_arp_resp(rx[0],
276                              self.pg1.local_mac,
277                              self.pg1._remote_hosts[3].mac,
278                              self.pg1.local_ip4,
279                              self.pg1._remote_hosts[3].ip4)
280
281         #
282         # VPP should have learned the mapping for the remote host
283         #
284         self.assertTrue(find_nbr(self,
285                                  self.pg1.sw_if_index,
286                                  self.pg1._remote_hosts[3].ip4))
287         #
288         # Fire in an ARP request before the interface becomes IP enabled
289         #
290         self.pg2.generate_remote_hosts(4)
291
292         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
293              ARP(op="who-has",
294                  hwsrc=self.pg2.remote_mac,
295                  pdst=self.pg1.local_ip4,
296                  psrc=self.pg2.remote_hosts[3].ip4))
297         pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
298               Dot1Q(vlan=0) /
299               ARP(op="who-has",
300                   hwsrc=self.pg2.remote_mac,
301                   pdst=self.pg1.local_ip4,
302                   psrc=self.pg2.remote_hosts[3].ip4))
303         self.send_and_assert_no_replies(self.pg2, p,
304                                         "interface not IP enabled")
305
306         #
307         # Make pg2 un-numbered to pg1
308         #
309         self.pg2.set_unnumbered(self.pg1.sw_if_index)
310
311         unnum = self.vapi.ip_unnumbered_dump()
312         self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
313         self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
314
315         #
316         # We should respond to ARP requests for the unnumbered to address
317         # once an attached route to the source is known
318         #
319         self.send_and_assert_no_replies(
320             self.pg2, p,
321             "ARP req for unnumbered address - no source")
322
323         attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
324                                    [VppRoutePath("0.0.0.0",
325                                                  self.pg2.sw_if_index)])
326         attached_host.add_vpp_config()
327
328         self.pg2.add_stream(p)
329         self.pg_enable_capture(self.pg_interfaces)
330         self.pg_start()
331
332         rx = self.pg2.get_capture(1)
333         self.verify_arp_resp(rx[0],
334                              self.pg2.local_mac,
335                              self.pg2.remote_mac,
336                              self.pg1.local_ip4,
337                              self.pg2.remote_hosts[3].ip4)
338
339         self.pg2.add_stream(pt)
340         self.pg_enable_capture(self.pg_interfaces)
341         self.pg_start()
342
343         rx = self.pg2.get_capture(1)
344         self.verify_arp_resp(rx[0],
345                              self.pg2.local_mac,
346                              self.pg2.remote_mac,
347                              self.pg1.local_ip4,
348                              self.pg2.remote_hosts[3].ip4)
349
350         #
351         # A neighbor entry that has no associated FIB-entry
352         #
353         arp_no_fib = VppNeighbor(self,
354                                  self.pg1.sw_if_index,
355                                  self.pg1.remote_hosts[4].mac,
356                                  self.pg1.remote_hosts[4].ip4,
357                                  is_no_fib_entry=1)
358         arp_no_fib.add_vpp_config()
359
360         #
361         # check we have the neighbor, but no route
362         #
363         self.assertTrue(find_nbr(self,
364                                  self.pg1.sw_if_index,
365                                  self.pg1._remote_hosts[4].ip4))
366         self.assertFalse(find_route(self,
367                                     self.pg1._remote_hosts[4].ip4,
368                                     32))
369         #
370         # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
371         # from within pg1's subnet
372         #
373         arp_unnum = VppNeighbor(self,
374                                 self.pg2.sw_if_index,
375                                 self.pg1.remote_hosts[5].mac,
376                                 self.pg1.remote_hosts[5].ip4)
377         arp_unnum.add_vpp_config()
378
379         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
380              IP(src=self.pg0.remote_ip4,
381                 dst=self.pg1._remote_hosts[5].ip4) /
382              UDP(sport=1234, dport=1234) /
383              Raw())
384
385         self.pg0.add_stream(p)
386         self.pg_enable_capture(self.pg_interfaces)
387         self.pg_start()
388
389         rx = self.pg2.get_capture(1)
390
391         self.verify_ip(rx[0],
392                        self.pg2.local_mac,
393                        self.pg1.remote_hosts[5].mac,
394                        self.pg0.remote_ip4,
395                        self.pg1._remote_hosts[5].ip4)
396
397         #
398         # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
399         # with the unnumbered interface's address as the source
400         #
401         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
402              ARP(op="who-has",
403                  hwsrc=self.pg2.remote_mac,
404                  pdst=self.pg1.local_ip4,
405                  psrc=self.pg1.remote_hosts[6].ip4))
406
407         self.pg2.add_stream(p)
408         self.pg_enable_capture(self.pg_interfaces)
409         self.pg_start()
410
411         rx = self.pg2.get_capture(1)
412         self.verify_arp_resp(rx[0],
413                              self.pg2.local_mac,
414                              self.pg2.remote_mac,
415                              self.pg1.local_ip4,
416                              self.pg1.remote_hosts[6].ip4)
417
418         #
419         # An attached host route out of pg2 for an undiscovered hosts generates
420         # an ARP request with the unnumbered address as the source
421         #
422         att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
423                                [VppRoutePath("0.0.0.0",
424                                              self.pg2.sw_if_index)])
425         att_unnum.add_vpp_config()
426
427         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
428              IP(src=self.pg0.remote_ip4,
429                 dst=self.pg1._remote_hosts[7].ip4) /
430              UDP(sport=1234, dport=1234) /
431              Raw())
432
433         self.pg0.add_stream(p)
434         self.pg_enable_capture(self.pg_interfaces)
435         self.pg_start()
436
437         rx = self.pg2.get_capture(1)
438
439         self.verify_arp_req(rx[0],
440                             self.pg2.local_mac,
441                             self.pg1.local_ip4,
442                             self.pg1._remote_hosts[7].ip4)
443
444         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
445              ARP(op="who-has",
446                  hwsrc=self.pg2.remote_mac,
447                  pdst=self.pg1.local_ip4,
448                  psrc=self.pg1.remote_hosts[7].ip4))
449
450         self.pg2.add_stream(p)
451         self.pg_enable_capture(self.pg_interfaces)
452         self.pg_start()
453
454         rx = self.pg2.get_capture(1)
455         self.verify_arp_resp(rx[0],
456                              self.pg2.local_mac,
457                              self.pg2.remote_mac,
458                              self.pg1.local_ip4,
459                              self.pg1.remote_hosts[7].ip4)
460
461         #
462         # An attached host route as yet unresolved out of pg2 for an
463         # undiscovered host, an ARP requests begets a response.
464         #
465         att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
466                                 [VppRoutePath("0.0.0.0",
467                                               self.pg2.sw_if_index)])
468         att_unnum1.add_vpp_config()
469
470         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
471              ARP(op="who-has",
472                  hwsrc=self.pg2.remote_mac,
473                  pdst=self.pg1.local_ip4,
474                  psrc=self.pg1.remote_hosts[8].ip4))
475
476         self.pg2.add_stream(p)
477         self.pg_enable_capture(self.pg_interfaces)
478         self.pg_start()
479
480         rx = self.pg2.get_capture(1)
481         self.verify_arp_resp(rx[0],
482                              self.pg2.local_mac,
483                              self.pg2.remote_mac,
484                              self.pg1.local_ip4,
485                              self.pg1.remote_hosts[8].ip4)
486
487         #
488         # Send an ARP request from one of the so-far unlearned remote hosts
489         # with a VLAN0 tag
490         #
491         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
492                    src=self.pg1._remote_hosts[9].mac) /
493              Dot1Q(vlan=0) /
494              ARP(op="who-has",
495                  hwsrc=self.pg1._remote_hosts[9].mac,
496                  pdst=self.pg1.local_ip4,
497                  psrc=self.pg1._remote_hosts[9].ip4))
498
499         self.pg1.add_stream(p)
500         self.pg_enable_capture(self.pg_interfaces)
501         self.pg_start()
502
503         rx = self.pg1.get_capture(1)
504         self.verify_arp_resp(rx[0],
505                              self.pg1.local_mac,
506                              self.pg1._remote_hosts[9].mac,
507                              self.pg1.local_ip4,
508                              self.pg1._remote_hosts[9].ip4)
509
510         #
511         # Add a hierarchy of routes for a host in the sub-net.
512         # Should still get an ARP resp since the cover is attached
513         #
514         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
515              ARP(op="who-has",
516                  hwsrc=self.pg1.remote_mac,
517                  pdst=self.pg1.local_ip4,
518                  psrc=self.pg1.remote_hosts[10].ip4))
519
520         r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
521                         [VppRoutePath(self.pg1.remote_hosts[10].ip4,
522                                       self.pg1.sw_if_index)])
523         r1.add_vpp_config()
524
525         self.pg1.add_stream(p)
526         self.pg_enable_capture(self.pg_interfaces)
527         self.pg_start()
528         rx = self.pg1.get_capture(1)
529         self.verify_arp_resp(rx[0],
530                              self.pg1.local_mac,
531                              self.pg1.remote_mac,
532                              self.pg1.local_ip4,
533                              self.pg1.remote_hosts[10].ip4)
534
535         r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
536                         [VppRoutePath(self.pg1.remote_hosts[10].ip4,
537                                       self.pg1.sw_if_index)])
538         r2.add_vpp_config()
539
540         self.pg1.add_stream(p)
541         self.pg_enable_capture(self.pg_interfaces)
542         self.pg_start()
543         rx = self.pg1.get_capture(1)
544         self.verify_arp_resp(rx[0],
545                              self.pg1.local_mac,
546                              self.pg1.remote_mac,
547                              self.pg1.local_ip4,
548                              self.pg1.remote_hosts[10].ip4)
549
550         #
551         # add an ARP entry that's not on the sub-net and so whose
552         # adj-fib fails the refinement check. then send an ARP request
553         # from that source
554         #
555         a1 = VppNeighbor(self,
556                          self.pg0.sw_if_index,
557                          self.pg0.remote_mac,
558                          "100.100.100.50")
559         a1.add_vpp_config()
560
561         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
562              ARP(op="who-has",
563                  hwsrc=self.pg0.remote_mac,
564                  psrc="100.100.100.50",
565                  pdst=self.pg0.remote_ip4))
566         self.send_and_assert_no_replies(self.pg0, p,
567                                         "ARP req for from failed adj-fib")
568
569         #
570         # ERROR Cases
571         #  1 - don't respond to ARP request for address not within the
572         #      interface's sub-net
573         #  1b - nor within the unnumbered subnet
574         #  1c - nor within the subnet of a different interface
575         #
576         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
577              ARP(op="who-has",
578                  hwsrc=self.pg0.remote_mac,
579                  pdst="10.10.10.3",
580                  psrc=self.pg0.remote_ip4))
581         self.send_and_assert_no_replies(self.pg0, p,
582                                         "ARP req for non-local destination")
583         self.assertFalse(find_nbr(self,
584                                   self.pg0.sw_if_index,
585                                   "10.10.10.3"))
586
587         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
588              ARP(op="who-has",
589                  hwsrc=self.pg2.remote_mac,
590                  pdst="10.10.10.3",
591                  psrc=self.pg1.remote_hosts[7].ip4))
592         self.send_and_assert_no_replies(
593             self.pg0, p,
594             "ARP req for non-local destination - unnum")
595
596         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
597              ARP(op="who-has",
598                  hwsrc=self.pg0.remote_mac,
599                  pdst=self.pg1.local_ip4,
600                  psrc=self.pg1.remote_ip4))
601         self.send_and_assert_no_replies(self.pg0, p,
602                                         "ARP req diff sub-net")
603         self.assertFalse(find_nbr(self,
604                                   self.pg0.sw_if_index,
605                                   self.pg1.remote_ip4))
606
607         #
608         #  2 - don't respond to ARP request from an address not within the
609         #      interface's sub-net
610         #   2b - to a proxied address
611         #   2c - not within a different interface's sub-net
612         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
613              ARP(op="who-has",
614                  hwsrc=self.pg0.remote_mac,
615                  psrc="10.10.10.3",
616                  pdst=self.pg0.local_ip4))
617         self.send_and_assert_no_replies(self.pg0, p,
618                                         "ARP req for non-local source")
619         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
620              ARP(op="who-has",
621                  hwsrc=self.pg2.remote_mac,
622                  psrc="10.10.10.3",
623                  pdst=self.pg0.local_ip4))
624         self.send_and_assert_no_replies(
625             self.pg0, p,
626             "ARP req for non-local source - unnum")
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.pg1.remote_ip4,
631                  pdst=self.pg0.local_ip4))
632         self.send_and_assert_no_replies(self.pg0, p,
633                                         "ARP req for non-local source 2c")
634
635         #
636         #  3 - don't respond to ARP request from an address that belongs to
637         #      the router
638         #
639         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
640              ARP(op="who-has",
641                  hwsrc=self.pg0.remote_mac,
642                  psrc=self.pg0.local_ip4,
643                  pdst=self.pg0.local_ip4))
644         self.send_and_assert_no_replies(self.pg0, p,
645                                         "ARP req for non-local source")
646
647         #
648         #  4 - don't respond to ARP requests that has mac source different
649         #      from ARP request HW source
650         #
651         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
652              ARP(op="who-has",
653                  hwsrc="00:00:00:DE:AD:BE",
654                  psrc=self.pg0.remote_ip4,
655                  pdst=self.pg0.local_ip4))
656         self.send_and_assert_no_replies(self.pg0, p,
657                                         "ARP req for non-local source")
658
659         #
660         #  5 - don't respond to ARP requests for address within the
661         #      interface's sub-net but not the interface's address
662         #
663         self.pg0.generate_remote_hosts(2)
664         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
665              ARP(op="who-has",
666                  hwsrc=self.pg0.remote_mac,
667                  psrc=self.pg0.remote_hosts[0].ip4,
668                  pdst=self.pg0.remote_hosts[1].ip4))
669         self.send_and_assert_no_replies(self.pg0, p,
670                                         "ARP req for non-local destination")
671
672         #
673         # cleanup
674         #
675         dyn_arp.remove_vpp_config()
676         static_arp.remove_vpp_config()
677         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
678
679         # need this to flush the adj-fibs
680         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
681         self.pg2.admin_down()
682         self.pg1.admin_down()
683
684     def test_proxy_mirror_arp(self):
685         """ Interface Mirror Proxy ARP """
686
687         #
688         # When VPP has an interface whose address is also applied to a TAP
689         # interface on the host, then VPP's TAP interface will be unnumbered
690         # to the 'real' interface and do proxy ARP from the host.
691         # the curious aspect of this setup is that ARP requests from the host
692         # will come from the VPP's own address.
693         #
694         self.pg0.generate_remote_hosts(2)
695
696         arp_req_from_me = (Ether(src=self.pg2.remote_mac,
697                                  dst="ff:ff:ff:ff:ff:ff") /
698                            ARP(op="who-has",
699                                hwsrc=self.pg2.remote_mac,
700                                pdst=self.pg0.remote_hosts[1].ip4,
701                                psrc=self.pg0.local_ip4))
702
703         #
704         # Configure Proxy ARP for the subnet on PG0addresses on pg0
705         #
706         self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
707                                     self.pg0._local_ip4_bcast)
708
709         # Make pg2 un-numbered to pg0
710         #
711         self.pg2.set_unnumbered(self.pg0.sw_if_index)
712
713         #
714         # Enable pg2 for proxy ARP
715         #
716         self.pg2.set_proxy_arp()
717
718         #
719         # Send the ARP request with an originating address that
720         # is VPP's own address
721         #
722         self.pg2.add_stream(arp_req_from_me)
723         self.pg_enable_capture(self.pg_interfaces)
724         self.pg_start()
725
726         rx = self.pg2.get_capture(1)
727         self.verify_arp_resp(rx[0],
728                              self.pg2.local_mac,
729                              self.pg2.remote_mac,
730                              self.pg0.remote_hosts[1].ip4,
731                              self.pg0.local_ip4)
732
733         #
734         # validate we have not learned an ARP entry as a result of this
735         #
736         self.assertFalse(find_nbr(self,
737                                   self.pg2.sw_if_index,
738                                   self.pg0.local_ip4))
739
740         #
741         # cleanup
742         #
743         self.pg2.set_proxy_arp(0)
744         self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
745                                     self.pg0._local_ip4_bcast,
746                                     is_add=0)
747
748     def test_proxy_arp(self):
749         """ Proxy ARP """
750
751         self.pg1.generate_remote_hosts(2)
752
753         #
754         # Proxy ARP request packets for each interface
755         #
756         arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
757                              dst="ff:ff:ff:ff:ff:ff") /
758                        ARP(op="who-has",
759                            hwsrc=self.pg0.remote_mac,
760                            pdst="10.10.10.3",
761                            psrc=self.pg0.remote_ip4))
762         arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
763                                     dst="ff:ff:ff:ff:ff:ff") /
764                               Dot1Q(vlan=0) /
765                               ARP(op="who-has",
766                                   hwsrc=self.pg0.remote_mac,
767                                   pdst="10.10.10.3",
768                                   psrc=self.pg0.remote_ip4))
769         arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
770                              dst="ff:ff:ff:ff:ff:ff") /
771                        ARP(op="who-has",
772                            hwsrc=self.pg1.remote_mac,
773                            pdst="10.10.10.3",
774                            psrc=self.pg1.remote_ip4))
775         arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
776                              dst="ff:ff:ff:ff:ff:ff") /
777                        ARP(op="who-has",
778                            hwsrc=self.pg2.remote_mac,
779                            pdst="10.10.10.3",
780                            psrc=self.pg1.remote_hosts[1].ip4))
781         arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
782                              dst="ff:ff:ff:ff:ff:ff") /
783                        ARP(op="who-has",
784                            hwsrc=self.pg3.remote_mac,
785                            pdst="10.10.10.3",
786                            psrc=self.pg3.remote_ip4))
787
788         #
789         # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
790         #
791         self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
792                                     inet_pton(AF_INET, "10.10.10.124"))
793
794         #
795         # No responses are sent when the interfaces are not enabled for proxy
796         # ARP
797         #
798         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
799                                         "ARP req from unconfigured interface")
800         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
801                                         "ARP req from unconfigured interface")
802
803         #
804         # Make pg2 un-numbered to pg1
805         #  still won't reply.
806         #
807         self.pg2.set_unnumbered(self.pg1.sw_if_index)
808
809         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
810                                         "ARP req from unnumbered interface")
811
812         #
813         # Enable each interface to reply to proxy ARPs
814         #
815         for i in self.pg_interfaces:
816             i.set_proxy_arp()
817
818         #
819         # Now each of the interfaces should reply to a request to a proxied
820         # address
821         #
822         self.pg0.add_stream(arp_req_pg0)
823         self.pg_enable_capture(self.pg_interfaces)
824         self.pg_start()
825
826         rx = self.pg0.get_capture(1)
827         self.verify_arp_resp(rx[0],
828                              self.pg0.local_mac,
829                              self.pg0.remote_mac,
830                              "10.10.10.3",
831                              self.pg0.remote_ip4)
832
833         self.pg0.add_stream(arp_req_pg0_tagged)
834         self.pg_enable_capture(self.pg_interfaces)
835         self.pg_start()
836
837         rx = self.pg0.get_capture(1)
838         self.verify_arp_resp(rx[0],
839                              self.pg0.local_mac,
840                              self.pg0.remote_mac,
841                              "10.10.10.3",
842                              self.pg0.remote_ip4)
843
844         self.pg1.add_stream(arp_req_pg1)
845         self.pg_enable_capture(self.pg_interfaces)
846         self.pg_start()
847
848         rx = self.pg1.get_capture(1)
849         self.verify_arp_resp(rx[0],
850                              self.pg1.local_mac,
851                              self.pg1.remote_mac,
852                              "10.10.10.3",
853                              self.pg1.remote_ip4)
854
855         self.pg2.add_stream(arp_req_pg2)
856         self.pg_enable_capture(self.pg_interfaces)
857         self.pg_start()
858
859         rx = self.pg2.get_capture(1)
860         self.verify_arp_resp(rx[0],
861                              self.pg2.local_mac,
862                              self.pg2.remote_mac,
863                              "10.10.10.3",
864                              self.pg1.remote_hosts[1].ip4)
865
866         #
867         # A request for an address out of the configured range
868         #
869         arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
870                                 dst="ff:ff:ff:ff:ff:ff") /
871                           ARP(op="who-has",
872                               hwsrc=self.pg1.remote_mac,
873                               pdst="10.10.10.125",
874                               psrc=self.pg1.remote_ip4))
875         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
876                                         "ARP req out of range HI")
877         arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
878                                  dst="ff:ff:ff:ff:ff:ff") /
879                            ARP(op="who-has",
880                                hwsrc=self.pg1.remote_mac,
881                                pdst="10.10.10.1",
882                                psrc=self.pg1.remote_ip4))
883         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
884                                         "ARP req out of range Low")
885
886         #
887         # Request for an address in the proxy range but from an interface
888         # in a different VRF
889         #
890         self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
891                                         "ARP req from different VRF")
892
893         #
894         # Disable Each interface for proxy ARP
895         #  - expect none to respond
896         #
897         for i in self.pg_interfaces:
898             i.set_proxy_arp(0)
899
900         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
901                                         "ARP req from disable")
902         self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
903                                         "ARP req from disable")
904         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
905                                         "ARP req from disable")
906
907         #
908         # clean up on interface 2
909         #
910         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
911
912     def test_mpls(self):
913         """ MPLS """
914
915         #
916         # Interface 2 does not yet have ip4 config
917         #
918         self.pg2.config_ip4()
919         self.pg2.generate_remote_hosts(2)
920
921         #
922         # Add a route with out going label via an ARP unresolved next-hop
923         #
924         ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
925                                  [VppRoutePath(self.pg2.remote_hosts[1].ip4,
926                                                self.pg2.sw_if_index,
927                                                labels=[55])])
928         ip_10_0_0_1.add_vpp_config()
929
930         #
931         # packets should generate an ARP request
932         #
933         p = (Ether(src=self.pg0.remote_mac,
934                    dst=self.pg0.local_mac) /
935              IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
936              UDP(sport=1234, dport=1234) /
937              Raw('\xa5' * 100))
938
939         self.pg0.add_stream(p)
940         self.pg_enable_capture(self.pg_interfaces)
941         self.pg_start()
942
943         rx = self.pg2.get_capture(1)
944         self.verify_arp_req(rx[0],
945                             self.pg2.local_mac,
946                             self.pg2.local_ip4,
947                             self.pg2._remote_hosts[1].ip4)
948
949         #
950         # now resolve the neighbours
951         #
952         self.pg2.configure_ipv4_neighbors()
953
954         #
955         # Now packet should be properly MPLS encapped.
956         #  This verifies that MPLS link-type adjacencies are completed
957         #  when the ARP entry resolves
958         #
959         self.pg0.add_stream(p)
960         self.pg_enable_capture(self.pg_interfaces)
961         self.pg_start()
962
963         rx = self.pg2.get_capture(1)
964         self.verify_ip_o_mpls(rx[0],
965                               self.pg2.local_mac,
966                               self.pg2.remote_hosts[1].mac,
967                               55,
968                               self.pg0.remote_ip4,
969                               "10.0.0.1")
970         self.pg2.unconfig_ip4()
971
972     def test_arp_vrrp(self):
973         """ ARP reply with VRRP virtual src hw addr """
974
975         #
976         # IP packet destined for pg1 remote host arrives on pg0 resulting
977         # in an ARP request for the address of the remote host on pg1
978         #
979         p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
980               IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
981               UDP(sport=1234, dport=1234) /
982               Raw())
983
984         rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
985
986         self.verify_arp_req(rx1[0],
987                             self.pg1.local_mac,
988                             self.pg1.local_ip4,
989                             self.pg1.remote_ip4)
990
991         #
992         # ARP reply for address of pg1 remote host arrives on pg1 with
993         # the hw src addr set to a value in the VRRP IPv4 range of
994         # MAC addresses
995         #
996         p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
997               ARP(op="is-at", hwdst=self.pg1.local_mac,
998                   hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
999                   psrc=self.pg1.remote_ip4))
1000
1001         self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1002
1003         #
1004         # IP packet destined for pg1 remote host arrives on pg0 again.
1005         # VPP should have an ARP entry for that address now and the packet
1006         # should be sent out pg1.
1007         #
1008         rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
1009
1010         self.verify_ip(rx1[0],
1011                        self.pg1.local_mac,
1012                        "00:00:5e:00:01:09",
1013                        self.pg0.remote_ip4,
1014                        self.pg1.remote_ip4)
1015
1016         self.pg1.admin_down()
1017         self.pg1.admin_up()
1018
1019     def test_arp_duplicates(self):
1020         """ ARP Duplicates"""
1021
1022         #
1023         # Generate some hosts on the LAN
1024         #
1025         self.pg1.generate_remote_hosts(3)
1026
1027         #
1028         # Add host 1 on pg1 and pg2
1029         #
1030         arp_pg1 = VppNeighbor(self,
1031                               self.pg1.sw_if_index,
1032                               self.pg1.remote_hosts[1].mac,
1033                               self.pg1.remote_hosts[1].ip4)
1034         arp_pg1.add_vpp_config()
1035         arp_pg2 = VppNeighbor(self,
1036                               self.pg2.sw_if_index,
1037                               self.pg2.remote_mac,
1038                               self.pg1.remote_hosts[1].ip4)
1039         arp_pg2.add_vpp_config()
1040
1041         #
1042         # IP packet destined for pg1 remote host arrives on pg1 again.
1043         #
1044         p = (Ether(dst=self.pg0.local_mac,
1045                    src=self.pg0.remote_mac) /
1046              IP(src=self.pg0.remote_ip4,
1047                 dst=self.pg1.remote_hosts[1].ip4) /
1048              UDP(sport=1234, dport=1234) /
1049              Raw())
1050
1051         self.pg0.add_stream(p)
1052         self.pg_enable_capture(self.pg_interfaces)
1053         self.pg_start()
1054
1055         rx1 = self.pg1.get_capture(1)
1056
1057         self.verify_ip(rx1[0],
1058                        self.pg1.local_mac,
1059                        self.pg1.remote_hosts[1].mac,
1060                        self.pg0.remote_ip4,
1061                        self.pg1.remote_hosts[1].ip4)
1062
1063         #
1064         # remove the duplicate on pg1
1065         # packet stream should generate ARPs out of pg1
1066         #
1067         arp_pg1.remove_vpp_config()
1068
1069         self.pg0.add_stream(p)
1070         self.pg_enable_capture(self.pg_interfaces)
1071         self.pg_start()
1072
1073         rx1 = self.pg1.get_capture(1)
1074
1075         self.verify_arp_req(rx1[0],
1076                             self.pg1.local_mac,
1077                             self.pg1.local_ip4,
1078                             self.pg1.remote_hosts[1].ip4)
1079
1080         #
1081         # Add it back
1082         #
1083         arp_pg1.add_vpp_config()
1084
1085         self.pg0.add_stream(p)
1086         self.pg_enable_capture(self.pg_interfaces)
1087         self.pg_start()
1088
1089         rx1 = self.pg1.get_capture(1)
1090
1091         self.verify_ip(rx1[0],
1092                        self.pg1.local_mac,
1093                        self.pg1.remote_hosts[1].mac,
1094                        self.pg0.remote_ip4,
1095                        self.pg1.remote_hosts[1].ip4)
1096
1097     def test_arp_static(self):
1098         """ ARP Static"""
1099         self.pg2.generate_remote_hosts(3)
1100
1101         #
1102         # Add a static ARP entry
1103         #
1104         static_arp = VppNeighbor(self,
1105                                  self.pg2.sw_if_index,
1106                                  self.pg2.remote_hosts[1].mac,
1107                                  self.pg2.remote_hosts[1].ip4,
1108                                  is_static=1)
1109         static_arp.add_vpp_config()
1110
1111         #
1112         # Add the connected prefix to the interface
1113         #
1114         self.pg2.config_ip4()
1115
1116         #
1117         # We should now find the adj-fib
1118         #
1119         self.assertTrue(find_nbr(self,
1120                                  self.pg2.sw_if_index,
1121                                  self.pg2.remote_hosts[1].ip4,
1122                                  is_static=1))
1123         self.assertTrue(find_route(self,
1124                                    self.pg2.remote_hosts[1].ip4,
1125                                    32))
1126
1127         #
1128         # remove the connected
1129         #
1130         self.pg2.unconfig_ip4()
1131
1132         #
1133         # put the interface into table 1
1134         #
1135         self.pg2.set_table_ip4(1)
1136
1137         #
1138         # configure the same connected and expect to find the
1139         # adj fib in the new table
1140         #
1141         self.pg2.config_ip4()
1142         self.assertTrue(find_route(self,
1143                                    self.pg2.remote_hosts[1].ip4,
1144                                    32,
1145                                    table_id=1))
1146
1147         #
1148         # clean-up
1149         #
1150         self.pg2.unconfig_ip4()
1151         self.pg2.set_table_ip4(0)
1152
1153     def test_arp_incomplete(self):
1154         """ ARP Incomplete"""
1155         self.pg1.generate_remote_hosts(3)
1156
1157         p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1158               IP(src=self.pg0.remote_ip4,
1159                  dst=self.pg1.remote_hosts[1].ip4) /
1160               UDP(sport=1234, dport=1234) /
1161               Raw())
1162         p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1163               IP(src=self.pg0.remote_ip4,
1164                  dst=self.pg1.remote_hosts[2].ip4) /
1165               UDP(sport=1234, dport=1234) /
1166               Raw())
1167
1168         #
1169         # a packet to an unresolved destination generates an ARP request
1170         #
1171         rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1172         self.verify_arp_req(rx[0],
1173                             self.pg1.local_mac,
1174                             self.pg1.local_ip4,
1175                             self.pg1._remote_hosts[1].ip4)
1176
1177         #
1178         # add a neighbour for remote host 1
1179         #
1180         static_arp = VppNeighbor(self,
1181                                  self.pg1.sw_if_index,
1182                                  self.pg1.remote_hosts[1].mac,
1183                                  self.pg1.remote_hosts[1].ip4,
1184                                  is_static=1)
1185         static_arp.add_vpp_config()
1186
1187         #
1188         # change the interface's MAC
1189         #
1190         mac = [scapy.compat.chb(0x00), scapy.compat.chb(0x00),
1191                scapy.compat.chb(0x00), scapy.compat.chb(0x33),
1192                scapy.compat.chb(0x33), scapy.compat.chb(0x33)]
1193         mac_string = ''.join(mac)
1194
1195         self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1196                                                mac_string)
1197
1198         #
1199         # now ARP requests come from the new source mac
1200         #
1201         rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1202         self.verify_arp_req(rx[0],
1203                             "00:00:00:33:33:33",
1204                             self.pg1.local_ip4,
1205                             self.pg1._remote_hosts[2].ip4)
1206
1207         #
1208         # packets to the resolved host also have the new source mac
1209         #
1210         rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1211         self.verify_ip(rx[0],
1212                        "00:00:00:33:33:33",
1213                        self.pg1.remote_hosts[1].mac,
1214                        self.pg0.remote_ip4,
1215                        self.pg1.remote_hosts[1].ip4)
1216
1217         #
1218         # set the mac address on the interface that does not have a
1219         # configured subnet and thus no glean
1220         #
1221         self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1222                                                mac_string)
1223
1224     def test_garp(self):
1225         """ GARP """
1226
1227         #
1228         # Generate some hosts on the LAN
1229         #
1230         self.pg1.generate_remote_hosts(4)
1231
1232         #
1233         # And an ARP entry
1234         #
1235         arp = VppNeighbor(self,
1236                           self.pg1.sw_if_index,
1237                           self.pg1.remote_hosts[1].mac,
1238                           self.pg1.remote_hosts[1].ip4)
1239         arp.add_vpp_config()
1240
1241         self.assertTrue(find_nbr(self,
1242                                  self.pg1.sw_if_index,
1243                                  self.pg1.remote_hosts[1].ip4,
1244                                  mac=self.pg1.remote_hosts[1].mac))
1245
1246         #
1247         # Send a GARP (request) to swap the host 1's address to that of host 2
1248         #
1249         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1250                     src=self.pg1.remote_hosts[2].mac) /
1251               ARP(op="who-has",
1252                   hwdst=self.pg1.local_mac,
1253                   hwsrc=self.pg1.remote_hosts[2].mac,
1254                   pdst=self.pg1.remote_hosts[1].ip4,
1255                   psrc=self.pg1.remote_hosts[1].ip4))
1256
1257         self.pg1.add_stream(p1)
1258         self.pg_enable_capture(self.pg_interfaces)
1259         self.pg_start()
1260
1261         self.assertTrue(find_nbr(self,
1262                                  self.pg1.sw_if_index,
1263                                  self.pg1.remote_hosts[1].ip4,
1264                                  mac=self.pg1.remote_hosts[2].mac))
1265
1266         #
1267         # Send a GARP (reply) to swap the host 1's address to that of host 3
1268         #
1269         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1270                     src=self.pg1.remote_hosts[3].mac) /
1271               ARP(op="is-at",
1272                   hwdst=self.pg1.local_mac,
1273                   hwsrc=self.pg1.remote_hosts[3].mac,
1274                   pdst=self.pg1.remote_hosts[1].ip4,
1275                   psrc=self.pg1.remote_hosts[1].ip4))
1276
1277         self.pg1.add_stream(p1)
1278         self.pg_enable_capture(self.pg_interfaces)
1279         self.pg_start()
1280
1281         self.assertTrue(find_nbr(self,
1282                                  self.pg1.sw_if_index,
1283                                  self.pg1.remote_hosts[1].ip4,
1284                                  mac=self.pg1.remote_hosts[3].mac))
1285
1286         #
1287         # GARPs (request nor replies) for host we don't know yet
1288         # don't result in new neighbour entries
1289         #
1290         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1291                     src=self.pg1.remote_hosts[3].mac) /
1292               ARP(op="who-has",
1293                   hwdst=self.pg1.local_mac,
1294                   hwsrc=self.pg1.remote_hosts[3].mac,
1295                   pdst=self.pg1.remote_hosts[2].ip4,
1296                   psrc=self.pg1.remote_hosts[2].ip4))
1297
1298         self.pg1.add_stream(p1)
1299         self.pg_enable_capture(self.pg_interfaces)
1300         self.pg_start()
1301
1302         self.assertFalse(find_nbr(self,
1303                                   self.pg1.sw_if_index,
1304                                   self.pg1.remote_hosts[2].ip4))
1305
1306         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1307                     src=self.pg1.remote_hosts[3].mac) /
1308               ARP(op="is-at",
1309                   hwdst=self.pg1.local_mac,
1310                   hwsrc=self.pg1.remote_hosts[3].mac,
1311                   pdst=self.pg1.remote_hosts[2].ip4,
1312                   psrc=self.pg1.remote_hosts[2].ip4))
1313
1314         self.pg1.add_stream(p1)
1315         self.pg_enable_capture(self.pg_interfaces)
1316         self.pg_start()
1317
1318         self.assertFalse(find_nbr(self,
1319                                   self.pg1.sw_if_index,
1320                                   self.pg1.remote_hosts[2].ip4))
1321
1322     def test_arp_incomplete(self):
1323         """ Incomplete Entries """
1324
1325         #
1326         # ensure that we throttle the ARP and ND requests
1327         #
1328         self.pg0.generate_remote_hosts(2)
1329
1330         #
1331         # IPv4/ARP
1332         #
1333         ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1334                                  [VppRoutePath(self.pg0.remote_hosts[1].ip4,
1335                                                self.pg0.sw_if_index)])
1336         ip_10_0_0_1.add_vpp_config()
1337
1338         p1 = (Ether(dst=self.pg1.local_mac,
1339                     src=self.pg1.remote_mac) /
1340               IP(src=self.pg1.remote_ip4,
1341                  dst="10.0.0.1") /
1342               UDP(sport=1234, dport=1234) /
1343               Raw())
1344
1345         self.pg1.add_stream(p1 * 257)
1346         self.pg_enable_capture(self.pg_interfaces)
1347         self.pg_start()
1348         rx = self.pg0._get_capture(1)
1349
1350         #
1351         # how many we get is going to be dependent on the time for packet
1352         # processing but it should be small
1353         #
1354         self.assertLess(len(rx), 64)
1355
1356         #
1357         # IPv6/ND
1358         #
1359         ip_10_1 = VppIpRoute(self, "10::1", 128,
1360                              [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1361                                            self.pg0.sw_if_index,
1362                                            proto=DpoProto.DPO_PROTO_IP6)],
1363                              is_ip6=1)
1364         ip_10_1.add_vpp_config()
1365
1366         p1 = (Ether(dst=self.pg1.local_mac,
1367                     src=self.pg1.remote_mac) /
1368               IPv6(src=self.pg1.remote_ip6,
1369                    dst="10::1") /
1370               UDP(sport=1234, dport=1234) /
1371               Raw())
1372
1373         self.pg1.add_stream(p1 * 257)
1374         self.pg_enable_capture(self.pg_interfaces)
1375         self.pg_start()
1376         rx = self.pg0._get_capture(1)
1377
1378         #
1379         # how many we get is going to be dependent on the time for packet
1380         # processing but it should be small
1381         #
1382         self.assertLess(len(rx), 64)
1383
1384     def test_arp_forus(self):
1385         """ ARP for for-us """
1386
1387         #
1388         # Test that VPP responds with ARP requests to addresses that
1389         # are connected and local routes.
1390         # Use one of the 'remote' addresses in the subnet as a local address
1391         # The intention of this route is that it then acts like a secondary
1392         # address added to an interface
1393         #
1394         self.pg0.generate_remote_hosts(2)
1395
1396         forus = VppIpRoute(self, self.pg0.remote_hosts[1].ip4, 32,
1397                            [VppRoutePath(self.pg0.remote_hosts[1].ip4,
1398                                          self.pg0.sw_if_index)],
1399                            is_local=1)
1400         forus.add_vpp_config()
1401
1402         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1403                    src=self.pg0.remote_mac) /
1404              ARP(op="who-has",
1405                  hwdst=self.pg0.local_mac,
1406                  hwsrc=self.pg0.remote_mac,
1407                  pdst=self.pg0.remote_hosts[1].ip4,
1408                  psrc=self.pg0.remote_ip4))
1409
1410         rx = self.send_and_expect(self.pg0, [p], self.pg0)
1411
1412         self.verify_arp_resp(rx[0],
1413                              self.pg0.local_mac,
1414                              self.pg0.remote_mac,
1415                              self.pg0.remote_hosts[1].ip4,
1416                              self.pg0.remote_ip4)
1417
1418
1419 class NeighborStatsTestCase(VppTestCase):
1420     """ ARP/ND Counters """
1421
1422     @classmethod
1423     def setUpClass(cls):
1424         super(NeighborStatsTestCase, cls).setUpClass()
1425
1426     @classmethod
1427     def tearDownClass(cls):
1428         super(NeighborStatsTestCase, cls).tearDownClass()
1429
1430     def setUp(self):
1431         super(NeighborStatsTestCase, self).setUp()
1432
1433         self.create_pg_interfaces(range(2))
1434
1435         # pg0 configured with ip4 and 6 addresses used for input
1436         # pg1 configured with ip4 and 6 addresses used for output
1437         # pg2 is unnumbered to pg0
1438         for i in self.pg_interfaces:
1439             i.admin_up()
1440             i.config_ip4()
1441             i.config_ip6()
1442             i.resolve_arp()
1443             i.resolve_ndp()
1444
1445     def tearDown(self):
1446         super(NeighborStatsTestCase, self).tearDown()
1447
1448         for i in self.pg_interfaces:
1449             i.unconfig_ip4()
1450             i.unconfig_ip6()
1451             i.admin_down()
1452
1453     def test_arp_stats(self):
1454         """ ARP Counters """
1455
1456         self.vapi.cli("adj counters enable")
1457         self.pg1.generate_remote_hosts(2)
1458
1459         arp1 = VppNeighbor(self,
1460                            self.pg1.sw_if_index,
1461                            self.pg1.remote_hosts[0].mac,
1462                            self.pg1.remote_hosts[0].ip4)
1463         arp1.add_vpp_config()
1464         arp2 = VppNeighbor(self,
1465                            self.pg1.sw_if_index,
1466                            self.pg1.remote_hosts[1].mac,
1467                            self.pg1.remote_hosts[1].ip4)
1468         arp2.add_vpp_config()
1469
1470         p1 = (Ether(dst=self.pg0.local_mac,
1471                     src=self.pg0.remote_mac) /
1472               IP(src=self.pg0.remote_ip4,
1473                  dst=self.pg1.remote_hosts[0].ip4) /
1474               UDP(sport=1234, dport=1234) /
1475               Raw())
1476         p2 = (Ether(dst=self.pg0.local_mac,
1477                     src=self.pg0.remote_mac) /
1478               IP(src=self.pg0.remote_ip4,
1479                  dst=self.pg1.remote_hosts[1].ip4) /
1480               UDP(sport=1234, dport=1234) /
1481               Raw())
1482
1483         rx = self.send_and_expect(self.pg0, p1 * 65, self.pg1)
1484         rx = self.send_and_expect(self.pg0, p2 * 65, self.pg1)
1485
1486         self.assertEqual(65, arp1.get_stats()['packets'])
1487         self.assertEqual(65, arp2.get_stats()['packets'])
1488
1489         rx = self.send_and_expect(self.pg0, p1 * 65, self.pg1)
1490         self.assertEqual(130, arp1.get_stats()['packets'])
1491
1492     def test_nd_stats(self):
1493         """ ND Counters """
1494
1495         self.vapi.cli("adj counters enable")
1496         self.pg0.generate_remote_hosts(3)
1497
1498         nd1 = VppNeighbor(self,
1499                           self.pg0.sw_if_index,
1500                           self.pg0.remote_hosts[1].mac,
1501                           self.pg0.remote_hosts[1].ip6)
1502         nd1.add_vpp_config()
1503         nd2 = VppNeighbor(self,
1504                           self.pg0.sw_if_index,
1505                           self.pg0.remote_hosts[2].mac,
1506                           self.pg0.remote_hosts[2].ip6)
1507         nd2.add_vpp_config()
1508
1509         p1 = (Ether(dst=self.pg1.local_mac,
1510                     src=self.pg1.remote_mac) /
1511               IPv6(src=self.pg1.remote_ip6,
1512                    dst=self.pg0.remote_hosts[1].ip6) /
1513               UDP(sport=1234, dport=1234) /
1514               Raw())
1515         p2 = (Ether(dst=self.pg1.local_mac,
1516                     src=self.pg1.remote_mac) /
1517               IPv6(src=self.pg1.remote_ip6,
1518                    dst=self.pg0.remote_hosts[2].ip6) /
1519               UDP(sport=1234, dport=1234) /
1520               Raw())
1521
1522         rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1523         rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1524
1525         self.assertEqual(16, nd1.get_stats()['packets'])
1526         self.assertEqual(16, nd2.get_stats()['packets'])
1527
1528         rx = self.send_and_expect(self.pg1, p1 * 65, self.pg0)
1529         self.assertEqual(81, nd1.get_stats()['packets'])
1530
1531
1532 if __name__ == '__main__':
1533     unittest.main(testRunner=VppTestRunner)