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