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