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