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