ip-neighbor: Add flush API
[vpp.git] / test / test_neighbor.py
1 #!/usr/bin/env python3
2
3 import unittest
4 import os
5 from socket import AF_INET, AF_INET6, inet_pton
6
7 from framework import VppTestCase, VppTestRunner
8 from vpp_neighbor import VppNeighbor, find_nbr
9 from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
10     VppIpTable, DpoProto, FibPathType
11 from vpp_papi import VppEnum
12
13 import scapy.compat
14 from scapy.packet import Raw
15 from scapy.layers.l2 import Ether, ARP, Dot1Q
16 from scapy.layers.inet import IP, UDP, TCP
17 from scapy.layers.inet6 import IPv6
18 from scapy.contrib.mpls import MPLS
19 from scapy.layers.inet6 import IPv6
20
21
22 NUM_PKTS = 67
23
24 # not exported by scapy, so redefined here
25 arp_opts = {"who-has": 1, "is-at": 2}
26
27
28 class ARPTestCase(VppTestCase):
29     """ ARP Test Case """
30
31     @classmethod
32     def setUpClass(cls):
33         super(ARPTestCase, cls).setUpClass()
34
35     @classmethod
36     def tearDownClass(cls):
37         super(ARPTestCase, cls).tearDownClass()
38
39     def setUp(self):
40         super(ARPTestCase, self).setUp()
41
42         # create 3 pg interfaces
43         self.create_pg_interfaces(range(4))
44
45         # pg0 configured with ip4 and 6 addresses used for input
46         # pg1 configured with ip4 and 6 addresses used for output
47         # pg2 is unnumbered to pg0
48         for i in self.pg_interfaces:
49             i.admin_up()
50
51         self.pg0.config_ip4()
52         self.pg0.config_ip6()
53         self.pg0.resolve_arp()
54
55         self.pg1.config_ip4()
56         self.pg1.config_ip6()
57
58         # pg3 in a different VRF
59         self.tbl = VppIpTable(self, 1)
60         self.tbl.add_vpp_config()
61
62         self.pg3.set_table_ip4(1)
63         self.pg3.config_ip4()
64
65     def tearDown(self):
66         self.pg0.unconfig_ip4()
67         self.pg0.unconfig_ip6()
68
69         self.pg1.unconfig_ip4()
70         self.pg1.unconfig_ip6()
71
72         self.pg3.unconfig_ip4()
73         self.pg3.set_table_ip4(0)
74
75         for i in self.pg_interfaces:
76             i.admin_down()
77
78         super(ARPTestCase, self).tearDown()
79
80     def verify_arp_req(self, rx, smac, sip, dip):
81         ether = rx[Ether]
82         self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
83         self.assertEqual(ether.src, smac)
84
85         arp = rx[ARP]
86         self.assertEqual(arp.hwtype, 1)
87         self.assertEqual(arp.ptype, 0x800)
88         self.assertEqual(arp.hwlen, 6)
89         self.assertEqual(arp.plen, 4)
90         self.assertEqual(arp.op, arp_opts["who-has"])
91         self.assertEqual(arp.hwsrc, smac)
92         self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
93         self.assertEqual(arp.psrc, sip)
94         self.assertEqual(arp.pdst, dip)
95
96     def verify_arp_resp(self, rx, smac, dmac, sip, dip):
97         ether = rx[Ether]
98         self.assertEqual(ether.dst, dmac)
99         self.assertEqual(ether.src, smac)
100
101         arp = rx[ARP]
102         self.assertEqual(arp.hwtype, 1)
103         self.assertEqual(arp.ptype, 0x800)
104         self.assertEqual(arp.hwlen, 6)
105         self.assertEqual(arp.plen, 4)
106         self.assertEqual(arp.op, arp_opts["is-at"])
107         self.assertEqual(arp.hwsrc, smac)
108         self.assertEqual(arp.hwdst, dmac)
109         self.assertEqual(arp.psrc, sip)
110         self.assertEqual(arp.pdst, dip)
111
112     def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
113         ether = rx[Ether]
114         self.assertEqual(ether.dst, dmac)
115         self.assertEqual(ether.src, smac)
116
117         arp = rx[ARP]
118         self.assertEqual(arp.hwtype, 1)
119         self.assertEqual(arp.ptype, 0x800)
120         self.assertEqual(arp.hwlen, 6)
121         self.assertEqual(arp.plen, 4)
122         self.assertEqual(arp.op, arp_opts["is-at"])
123         self.assertNotEqual(arp.hwsrc, smac)
124         self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
125                         "00:00:5E:00:01" in arp.hwsrc)
126         self.assertEqual(arp.hwdst, dmac)
127         self.assertEqual(arp.psrc, sip)
128         self.assertEqual(arp.pdst, dip)
129
130     def verify_ip(self, rx, smac, dmac, sip, dip):
131         ether = rx[Ether]
132         self.assertEqual(ether.dst, dmac)
133         self.assertEqual(ether.src, smac)
134
135         ip = rx[IP]
136         self.assertEqual(ip.src, sip)
137         self.assertEqual(ip.dst, dip)
138
139     def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
140         ether = rx[Ether]
141         self.assertEqual(ether.dst, dmac)
142         self.assertEqual(ether.src, smac)
143
144         mpls = rx[MPLS]
145         self.assertTrue(mpls.label, label)
146
147         ip = rx[IP]
148         self.assertEqual(ip.src, sip)
149         self.assertEqual(ip.dst, dip)
150
151     def test_arp(self):
152         """ ARP """
153
154         #
155         # Generate some hosts on the LAN
156         #
157         self.pg1.generate_remote_hosts(11)
158
159         #
160         # watch for:
161         #  - all neighbour events
162         #  - all neighbor events on pg1
163         #  - neighbor events for host[1] on pg1
164         #
165         self.vapi.want_ip_neighbor_events(enable=1,
166                                           pid=os.getpid())
167         self.vapi.want_ip_neighbor_events(enable=1,
168                                           pid=os.getpid(),
169                                           sw_if_index=self.pg1.sw_if_index)
170         self.vapi.want_ip_neighbor_events(enable=1,
171                                           pid=os.getpid(),
172                                           sw_if_index=self.pg1.sw_if_index,
173                                           ip=self.pg1.remote_hosts[1].ip4)
174
175         self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
176
177         #
178         # Send IP traffic to one of these unresolved hosts.
179         #  expect the generation of an ARP request
180         #
181         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
182              IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
183              UDP(sport=1234, dport=1234) /
184              Raw())
185
186         self.pg0.add_stream(p)
187         self.pg_enable_capture(self.pg_interfaces)
188         self.pg_start()
189
190         rx = self.pg1.get_capture(1)
191
192         self.verify_arp_req(rx[0],
193                             self.pg1.local_mac,
194                             self.pg1.local_ip4,
195                             self.pg1._remote_hosts[1].ip4)
196
197         #
198         # And a dynamic ARP entry for host 1
199         #
200         dyn_arp = VppNeighbor(self,
201                               self.pg1.sw_if_index,
202                               self.pg1.remote_hosts[1].mac,
203                               self.pg1.remote_hosts[1].ip4)
204         dyn_arp.add_vpp_config()
205         self.assertTrue(dyn_arp.query_vpp_config())
206
207         # this matches all of the listnerers
208         es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
209               for i in range(3)]
210         for e in es:
211             self.assertEqual(str(e.neighbor.ip_address),
212                              self.pg1.remote_hosts[1].ip4)
213
214         #
215         # now we expect IP traffic forwarded
216         #
217         dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
218                  IP(src=self.pg0.remote_ip4,
219                     dst=self.pg1._remote_hosts[1].ip4) /
220                  UDP(sport=1234, dport=1234) /
221                  Raw())
222
223         self.pg0.add_stream(dyn_p)
224         self.pg_enable_capture(self.pg_interfaces)
225         self.pg_start()
226
227         rx = self.pg1.get_capture(1)
228
229         self.verify_ip(rx[0],
230                        self.pg1.local_mac,
231                        self.pg1.remote_hosts[1].mac,
232                        self.pg0.remote_ip4,
233                        self.pg1._remote_hosts[1].ip4)
234
235         #
236         # And a Static ARP entry for host 2
237         #
238         static_arp = VppNeighbor(self,
239                                  self.pg1.sw_if_index,
240                                  self.pg1.remote_hosts[2].mac,
241                                  self.pg1.remote_hosts[2].ip4,
242                                  is_static=1)
243         static_arp.add_vpp_config()
244         es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
245               for i in range(2)]
246         for e in es:
247             self.assertEqual(str(e.neighbor.ip_address),
248                              self.pg1.remote_hosts[2].ip4)
249
250         static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
251                     IP(src=self.pg0.remote_ip4,
252                        dst=self.pg1._remote_hosts[2].ip4) /
253                     UDP(sport=1234, dport=1234) /
254                     Raw())
255
256         self.pg0.add_stream(static_p)
257         self.pg_enable_capture(self.pg_interfaces)
258         self.pg_start()
259
260         rx = self.pg1.get_capture(1)
261
262         self.verify_ip(rx[0],
263                        self.pg1.local_mac,
264                        self.pg1.remote_hosts[2].mac,
265                        self.pg0.remote_ip4,
266                        self.pg1._remote_hosts[2].ip4)
267
268         #
269         # remove all the listeners
270         #
271         self.vapi.want_ip_neighbor_events(enable=0,
272                                           pid=os.getpid())
273         self.vapi.want_ip_neighbor_events(enable=0,
274                                           pid=os.getpid(),
275                                           sw_if_index=self.pg1.sw_if_index)
276         self.vapi.want_ip_neighbor_events(enable=0,
277                                           pid=os.getpid(),
278                                           sw_if_index=self.pg1.sw_if_index,
279                                           ip=self.pg1.remote_hosts[1].ip4)
280
281         #
282         # flap the link. dynamic ARPs get flush, statics don't
283         #
284         self.pg1.admin_down()
285         self.pg1.admin_up()
286
287         self.pg0.add_stream(static_p)
288         self.pg_enable_capture(self.pg_interfaces)
289         self.pg_start()
290         rx = self.pg1.get_capture(1)
291
292         self.verify_ip(rx[0],
293                        self.pg1.local_mac,
294                        self.pg1.remote_hosts[2].mac,
295                        self.pg0.remote_ip4,
296                        self.pg1._remote_hosts[2].ip4)
297
298         self.pg0.add_stream(dyn_p)
299         self.pg_enable_capture(self.pg_interfaces)
300         self.pg_start()
301
302         rx = self.pg1.get_capture(1)
303         self.verify_arp_req(rx[0],
304                             self.pg1.local_mac,
305                             self.pg1.local_ip4,
306                             self.pg1._remote_hosts[1].ip4)
307
308         self.assertFalse(dyn_arp.query_vpp_config())
309         self.assertTrue(static_arp.query_vpp_config())
310         #
311         # Send an ARP request from one of the so-far unlearned remote hosts
312         #
313         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
314                    src=self.pg1._remote_hosts[3].mac) /
315              ARP(op="who-has",
316                  hwsrc=self.pg1._remote_hosts[3].mac,
317                  pdst=self.pg1.local_ip4,
318                  psrc=self.pg1._remote_hosts[3].ip4))
319
320         self.pg1.add_stream(p)
321         self.pg_enable_capture(self.pg_interfaces)
322         self.pg_start()
323
324         rx = self.pg1.get_capture(1)
325         self.verify_arp_resp(rx[0],
326                              self.pg1.local_mac,
327                              self.pg1._remote_hosts[3].mac,
328                              self.pg1.local_ip4,
329                              self.pg1._remote_hosts[3].ip4)
330
331         #
332         # VPP should have learned the mapping for the remote host
333         #
334         self.assertTrue(find_nbr(self,
335                                  self.pg1.sw_if_index,
336                                  self.pg1._remote_hosts[3].ip4))
337         #
338         # Fire in an ARP request before the interface becomes IP enabled
339         #
340         self.pg2.generate_remote_hosts(4)
341
342         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
343              ARP(op="who-has",
344                  hwsrc=self.pg2.remote_mac,
345                  pdst=self.pg1.local_ip4,
346                  psrc=self.pg2.remote_hosts[3].ip4))
347         pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
348               Dot1Q(vlan=0) /
349               ARP(op="who-has",
350                   hwsrc=self.pg2.remote_mac,
351                   pdst=self.pg1.local_ip4,
352                   psrc=self.pg2.remote_hosts[3].ip4))
353         self.send_and_assert_no_replies(self.pg2, p,
354                                         "interface not IP enabled")
355
356         #
357         # Make pg2 un-numbered to pg1
358         #
359         self.pg2.set_unnumbered(self.pg1.sw_if_index)
360
361         #
362         # test the unnumbered dump both by all interfaces and just the enabled
363         # one
364         #
365         unnum = self.vapi.ip_unnumbered_dump()
366         self.assertTrue(len(unnum))
367         self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
368         self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
369         unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
370         self.assertTrue(len(unnum))
371         self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
372         self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
373
374         #
375         # We should respond to ARP requests for the unnumbered to address
376         # once an attached route to the source is known
377         #
378         self.send_and_assert_no_replies(
379             self.pg2, p,
380             "ARP req for unnumbered address - no source")
381
382         attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
383                                    [VppRoutePath("0.0.0.0",
384                                                  self.pg2.sw_if_index)])
385         attached_host.add_vpp_config()
386
387         self.pg2.add_stream(p)
388         self.pg_enable_capture(self.pg_interfaces)
389         self.pg_start()
390
391         rx = self.pg2.get_capture(1)
392         self.verify_arp_resp(rx[0],
393                              self.pg2.local_mac,
394                              self.pg2.remote_mac,
395                              self.pg1.local_ip4,
396                              self.pg2.remote_hosts[3].ip4)
397
398         self.pg2.add_stream(pt)
399         self.pg_enable_capture(self.pg_interfaces)
400         self.pg_start()
401
402         rx = self.pg2.get_capture(1)
403         self.verify_arp_resp(rx[0],
404                              self.pg2.local_mac,
405                              self.pg2.remote_mac,
406                              self.pg1.local_ip4,
407                              self.pg2.remote_hosts[3].ip4)
408
409         #
410         # A neighbor entry that has no associated FIB-entry
411         #
412         arp_no_fib = VppNeighbor(self,
413                                  self.pg1.sw_if_index,
414                                  self.pg1.remote_hosts[4].mac,
415                                  self.pg1.remote_hosts[4].ip4,
416                                  is_no_fib_entry=1)
417         arp_no_fib.add_vpp_config()
418
419         #
420         # check we have the neighbor, but no route
421         #
422         self.assertTrue(find_nbr(self,
423                                  self.pg1.sw_if_index,
424                                  self.pg1._remote_hosts[4].ip4))
425         self.assertFalse(find_route(self,
426                                     self.pg1._remote_hosts[4].ip4,
427                                     32))
428         #
429         # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
430         # from within pg1's subnet
431         #
432         arp_unnum = VppNeighbor(self,
433                                 self.pg2.sw_if_index,
434                                 self.pg1.remote_hosts[5].mac,
435                                 self.pg1.remote_hosts[5].ip4)
436         arp_unnum.add_vpp_config()
437
438         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
439              IP(src=self.pg0.remote_ip4,
440                 dst=self.pg1._remote_hosts[5].ip4) /
441              UDP(sport=1234, dport=1234) /
442              Raw())
443
444         self.pg0.add_stream(p)
445         self.pg_enable_capture(self.pg_interfaces)
446         self.pg_start()
447
448         rx = self.pg2.get_capture(1)
449
450         self.verify_ip(rx[0],
451                        self.pg2.local_mac,
452                        self.pg1.remote_hosts[5].mac,
453                        self.pg0.remote_ip4,
454                        self.pg1._remote_hosts[5].ip4)
455
456         #
457         # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
458         # with the unnumbered interface's address as the source
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[6].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[6].ip4)
476
477         #
478         # An attached host route out of pg2 for an undiscovered hosts generates
479         # an ARP request with the unnumbered address as the source
480         #
481         att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
482                                [VppRoutePath("0.0.0.0",
483                                              self.pg2.sw_if_index)])
484         att_unnum.add_vpp_config()
485
486         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
487              IP(src=self.pg0.remote_ip4,
488                 dst=self.pg1._remote_hosts[7].ip4) /
489              UDP(sport=1234, dport=1234) /
490              Raw())
491
492         self.pg0.add_stream(p)
493         self.pg_enable_capture(self.pg_interfaces)
494         self.pg_start()
495
496         rx = self.pg2.get_capture(1)
497
498         self.verify_arp_req(rx[0],
499                             self.pg2.local_mac,
500                             self.pg1.local_ip4,
501                             self.pg1._remote_hosts[7].ip4)
502
503         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
504              ARP(op="who-has",
505                  hwsrc=self.pg2.remote_mac,
506                  pdst=self.pg1.local_ip4,
507                  psrc=self.pg1.remote_hosts[7].ip4))
508
509         self.pg2.add_stream(p)
510         self.pg_enable_capture(self.pg_interfaces)
511         self.pg_start()
512
513         rx = self.pg2.get_capture(1)
514         self.verify_arp_resp(rx[0],
515                              self.pg2.local_mac,
516                              self.pg2.remote_mac,
517                              self.pg1.local_ip4,
518                              self.pg1.remote_hosts[7].ip4)
519
520         #
521         # An attached host route as yet unresolved out of pg2 for an
522         # undiscovered host, an ARP requests begets a response.
523         #
524         att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
525                                 [VppRoutePath("0.0.0.0",
526                                               self.pg2.sw_if_index)])
527         att_unnum1.add_vpp_config()
528
529         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
530              ARP(op="who-has",
531                  hwsrc=self.pg2.remote_mac,
532                  pdst=self.pg1.local_ip4,
533                  psrc=self.pg1.remote_hosts[8].ip4))
534
535         self.pg2.add_stream(p)
536         self.pg_enable_capture(self.pg_interfaces)
537         self.pg_start()
538
539         rx = self.pg2.get_capture(1)
540         self.verify_arp_resp(rx[0],
541                              self.pg2.local_mac,
542                              self.pg2.remote_mac,
543                              self.pg1.local_ip4,
544                              self.pg1.remote_hosts[8].ip4)
545
546         #
547         # Send an ARP request from one of the so-far unlearned remote hosts
548         # with a VLAN0 tag
549         #
550         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
551                    src=self.pg1._remote_hosts[9].mac) /
552              Dot1Q(vlan=0) /
553              ARP(op="who-has",
554                  hwsrc=self.pg1._remote_hosts[9].mac,
555                  pdst=self.pg1.local_ip4,
556                  psrc=self.pg1._remote_hosts[9].ip4))
557
558         self.pg1.add_stream(p)
559         self.pg_enable_capture(self.pg_interfaces)
560         self.pg_start()
561
562         rx = self.pg1.get_capture(1)
563         self.verify_arp_resp(rx[0],
564                              self.pg1.local_mac,
565                              self.pg1._remote_hosts[9].mac,
566                              self.pg1.local_ip4,
567                              self.pg1._remote_hosts[9].ip4)
568
569         #
570         # Add a hierarchy of routes for a host in the sub-net.
571         # Should still get an ARP resp since the cover is attached
572         #
573         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
574              ARP(op="who-has",
575                  hwsrc=self.pg1.remote_mac,
576                  pdst=self.pg1.local_ip4,
577                  psrc=self.pg1.remote_hosts[10].ip4))
578
579         r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
580                         [VppRoutePath(self.pg1.remote_hosts[10].ip4,
581                                       self.pg1.sw_if_index)])
582         r1.add_vpp_config()
583
584         self.pg1.add_stream(p)
585         self.pg_enable_capture(self.pg_interfaces)
586         self.pg_start()
587         rx = self.pg1.get_capture(1)
588         self.verify_arp_resp(rx[0],
589                              self.pg1.local_mac,
590                              self.pg1.remote_mac,
591                              self.pg1.local_ip4,
592                              self.pg1.remote_hosts[10].ip4)
593
594         r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
595                         [VppRoutePath(self.pg1.remote_hosts[10].ip4,
596                                       self.pg1.sw_if_index)])
597         r2.add_vpp_config()
598
599         self.pg1.add_stream(p)
600         self.pg_enable_capture(self.pg_interfaces)
601         self.pg_start()
602         rx = self.pg1.get_capture(1)
603         self.verify_arp_resp(rx[0],
604                              self.pg1.local_mac,
605                              self.pg1.remote_mac,
606                              self.pg1.local_ip4,
607                              self.pg1.remote_hosts[10].ip4)
608
609         #
610         # add an ARP entry that's not on the sub-net and so whose
611         # adj-fib fails the refinement check. then send an ARP request
612         # from that source
613         #
614         a1 = VppNeighbor(self,
615                          self.pg0.sw_if_index,
616                          self.pg0.remote_mac,
617                          "100.100.100.50")
618         a1.add_vpp_config()
619
620         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
621              ARP(op="who-has",
622                  hwsrc=self.pg0.remote_mac,
623                  psrc="100.100.100.50",
624                  pdst=self.pg0.remote_ip4))
625         self.send_and_assert_no_replies(self.pg0, p,
626                                         "ARP req for from failed adj-fib")
627
628         #
629         # ERROR Cases
630         #  1 - don't respond to ARP request for address not within the
631         #      interface's sub-net
632         #  1b - nor within the unnumbered subnet
633         #  1c - nor within the subnet of a different interface
634         #
635         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
636              ARP(op="who-has",
637                  hwsrc=self.pg0.remote_mac,
638                  pdst="10.10.10.3",
639                  psrc=self.pg0.remote_ip4))
640         self.send_and_assert_no_replies(self.pg0, p,
641                                         "ARP req for non-local destination")
642         self.assertFalse(find_nbr(self,
643                                   self.pg0.sw_if_index,
644                                   "10.10.10.3"))
645
646         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
647              ARP(op="who-has",
648                  hwsrc=self.pg2.remote_mac,
649                  pdst="10.10.10.3",
650                  psrc=self.pg1.remote_hosts[7].ip4))
651         self.send_and_assert_no_replies(
652             self.pg0, p,
653             "ARP req for non-local destination - unnum")
654
655         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
656              ARP(op="who-has",
657                  hwsrc=self.pg0.remote_mac,
658                  pdst=self.pg1.local_ip4,
659                  psrc=self.pg1.remote_ip4))
660         self.send_and_assert_no_replies(self.pg0, p,
661                                         "ARP req diff sub-net")
662         self.assertFalse(find_nbr(self,
663                                   self.pg0.sw_if_index,
664                                   self.pg1.remote_ip4))
665
666         #
667         #  2 - don't respond to ARP request from an address not within the
668         #      interface's sub-net
669         #   2b - to a proxied address
670         #   2c - not within a different interface's sub-net
671         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
672              ARP(op="who-has",
673                  hwsrc=self.pg0.remote_mac,
674                  psrc="10.10.10.3",
675                  pdst=self.pg0.local_ip4))
676         self.send_and_assert_no_replies(self.pg0, p,
677                                         "ARP req for non-local source")
678         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
679              ARP(op="who-has",
680                  hwsrc=self.pg2.remote_mac,
681                  psrc="10.10.10.3",
682                  pdst=self.pg0.local_ip4))
683         self.send_and_assert_no_replies(
684             self.pg0, p,
685             "ARP req for non-local source - unnum")
686         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
687              ARP(op="who-has",
688                  hwsrc=self.pg0.remote_mac,
689                  psrc=self.pg1.remote_ip4,
690                  pdst=self.pg0.local_ip4))
691         self.send_and_assert_no_replies(self.pg0, p,
692                                         "ARP req for non-local source 2c")
693
694         #
695         #  3 - don't respond to ARP request from an address that belongs to
696         #      the router
697         #
698         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
699              ARP(op="who-has",
700                  hwsrc=self.pg0.remote_mac,
701                  psrc=self.pg0.local_ip4,
702                  pdst=self.pg0.local_ip4))
703         self.send_and_assert_no_replies(self.pg0, p,
704                                         "ARP req for non-local source")
705
706         #
707         #  4 - don't respond to ARP requests that has mac source different
708         #      from ARP request HW source
709         #
710         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
711              ARP(op="who-has",
712                  hwsrc="00:00:00:DE:AD:BE",
713                  psrc=self.pg0.remote_ip4,
714                  pdst=self.pg0.local_ip4))
715         self.send_and_assert_no_replies(self.pg0, p,
716                                         "ARP req for non-local source")
717
718         #
719         #  5 - don't respond to ARP requests for address within the
720         #      interface's sub-net but not the interface's address
721         #
722         self.pg0.generate_remote_hosts(2)
723         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
724              ARP(op="who-has",
725                  hwsrc=self.pg0.remote_mac,
726                  psrc=self.pg0.remote_hosts[0].ip4,
727                  pdst=self.pg0.remote_hosts[1].ip4))
728         self.send_and_assert_no_replies(self.pg0, p,
729                                         "ARP req for non-local destination")
730
731         #
732         # cleanup
733         #
734         static_arp.remove_vpp_config()
735         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
736
737         # need this to flush the adj-fibs
738         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
739         self.pg2.admin_down()
740         self.pg1.admin_down()
741
742     def test_proxy_mirror_arp(self):
743         """ Interface Mirror Proxy ARP """
744
745         #
746         # When VPP has an interface whose address is also applied to a TAP
747         # interface on the host, then VPP's TAP interface will be unnumbered
748         # to the 'real' interface and do proxy ARP from the host.
749         # the curious aspect of this setup is that ARP requests from the host
750         # will come from the VPP's own address.
751         #
752         self.pg0.generate_remote_hosts(2)
753
754         arp_req_from_me = (Ether(src=self.pg2.remote_mac,
755                                  dst="ff:ff:ff:ff:ff:ff") /
756                            ARP(op="who-has",
757                                hwsrc=self.pg2.remote_mac,
758                                pdst=self.pg0.remote_hosts[1].ip4,
759                                psrc=self.pg0.local_ip4))
760
761         #
762         # Configure Proxy ARP for the subnet on PG0addresses on pg0
763         #
764         self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
765                                     self.pg0._local_ip4_bcast)
766
767         # Make pg2 un-numbered to pg0
768         #
769         self.pg2.set_unnumbered(self.pg0.sw_if_index)
770
771         #
772         # Enable pg2 for proxy ARP
773         #
774         self.pg2.set_proxy_arp()
775
776         #
777         # Send the ARP request with an originating address that
778         # is VPP's own address
779         #
780         rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
781         self.verify_arp_resp(rx[0],
782                              self.pg2.local_mac,
783                              self.pg2.remote_mac,
784                              self.pg0.remote_hosts[1].ip4,
785                              self.pg0.local_ip4)
786
787         #
788         # validate we have not learned an ARP entry as a result of this
789         #
790         self.assertFalse(find_nbr(self,
791                                   self.pg2.sw_if_index,
792                                   self.pg0.local_ip4))
793
794         #
795         # setup a punt redirect so packets from the uplink go to the tap
796         #
797         self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
798                                    self.pg2.sw_if_index,
799                                    self.pg0.local_ip4)
800
801         p_tcp = (Ether(src=self.pg0.remote_mac,
802                        dst=self.pg0.local_mac,) /
803                  IP(src=self.pg0.remote_ip4,
804                     dst=self.pg0.local_ip4) /
805                  TCP(sport=80, dport=80) /
806                  Raw())
807         rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
808
809         # there's no ARP entry so this is an ARP req
810         self.assertTrue(rx[0].haslayer(ARP))
811
812         # and ARP entry for VPP's pg0 address on the host interface
813         n1 = VppNeighbor(self,
814                          self.pg2.sw_if_index,
815                          self.pg2.remote_mac,
816                          self.pg0.local_ip4,
817                          is_no_fib_entry=True).add_vpp_config()
818         # now the packets shold forward
819         rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
820         self.assertFalse(rx[0].haslayer(ARP))
821         self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
822
823         #
824         # flush the neighbor cache on the uplink
825         #
826         af = VppEnum.vl_api_address_family_t
827         self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
828
829         # ensure we can still resolve the ARPs on the uplink
830         self.pg0.resolve_arp()
831
832         self.assertTrue(find_nbr(self,
833                                  self.pg0.sw_if_index,
834                                  self.pg0.remote_ip4))
835
836         #
837         # cleanup
838         #
839         self.pg2.set_proxy_arp(0)
840         self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
841                                     self.pg0._local_ip4_bcast,
842                                     is_add=0)
843
844     def test_proxy_arp(self):
845         """ Proxy ARP """
846
847         self.pg1.generate_remote_hosts(2)
848
849         #
850         # Proxy ARP request packets for each interface
851         #
852         arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
853                              dst="ff:ff:ff:ff:ff:ff") /
854                        ARP(op="who-has",
855                            hwsrc=self.pg0.remote_mac,
856                            pdst="10.10.10.3",
857                            psrc=self.pg0.remote_ip4))
858         arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
859                                     dst="ff:ff:ff:ff:ff:ff") /
860                               Dot1Q(vlan=0) /
861                               ARP(op="who-has",
862                                   hwsrc=self.pg0.remote_mac,
863                                   pdst="10.10.10.3",
864                                   psrc=self.pg0.remote_ip4))
865         arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
866                              dst="ff:ff:ff:ff:ff:ff") /
867                        ARP(op="who-has",
868                            hwsrc=self.pg1.remote_mac,
869                            pdst="10.10.10.3",
870                            psrc=self.pg1.remote_ip4))
871         arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
872                              dst="ff:ff:ff:ff:ff:ff") /
873                        ARP(op="who-has",
874                            hwsrc=self.pg2.remote_mac,
875                            pdst="10.10.10.3",
876                            psrc=self.pg1.remote_hosts[1].ip4))
877         arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
878                              dst="ff:ff:ff:ff:ff:ff") /
879                        ARP(op="who-has",
880                            hwsrc=self.pg3.remote_mac,
881                            pdst="10.10.10.3",
882                            psrc=self.pg3.remote_ip4))
883
884         #
885         # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
886         #
887         self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
888                                     inet_pton(AF_INET, "10.10.10.124"))
889
890         #
891         # No responses are sent when the interfaces are not enabled for proxy
892         # ARP
893         #
894         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
895                                         "ARP req from unconfigured interface")
896         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
897                                         "ARP req from unconfigured interface")
898
899         #
900         # Make pg2 un-numbered to pg1
901         #  still won't reply.
902         #
903         self.pg2.set_unnumbered(self.pg1.sw_if_index)
904
905         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
906                                         "ARP req from unnumbered interface")
907
908         #
909         # Enable each interface to reply to proxy ARPs
910         #
911         for i in self.pg_interfaces:
912             i.set_proxy_arp()
913
914         #
915         # Now each of the interfaces should reply to a request to a proxied
916         # address
917         #
918         self.pg0.add_stream(arp_req_pg0)
919         self.pg_enable_capture(self.pg_interfaces)
920         self.pg_start()
921
922         rx = self.pg0.get_capture(1)
923         self.verify_arp_resp(rx[0],
924                              self.pg0.local_mac,
925                              self.pg0.remote_mac,
926                              "10.10.10.3",
927                              self.pg0.remote_ip4)
928
929         self.pg0.add_stream(arp_req_pg0_tagged)
930         self.pg_enable_capture(self.pg_interfaces)
931         self.pg_start()
932
933         rx = self.pg0.get_capture(1)
934         self.verify_arp_resp(rx[0],
935                              self.pg0.local_mac,
936                              self.pg0.remote_mac,
937                              "10.10.10.3",
938                              self.pg0.remote_ip4)
939
940         self.pg1.add_stream(arp_req_pg1)
941         self.pg_enable_capture(self.pg_interfaces)
942         self.pg_start()
943
944         rx = self.pg1.get_capture(1)
945         self.verify_arp_resp(rx[0],
946                              self.pg1.local_mac,
947                              self.pg1.remote_mac,
948                              "10.10.10.3",
949                              self.pg1.remote_ip4)
950
951         self.pg2.add_stream(arp_req_pg2)
952         self.pg_enable_capture(self.pg_interfaces)
953         self.pg_start()
954
955         rx = self.pg2.get_capture(1)
956         self.verify_arp_resp(rx[0],
957                              self.pg2.local_mac,
958                              self.pg2.remote_mac,
959                              "10.10.10.3",
960                              self.pg1.remote_hosts[1].ip4)
961
962         #
963         # A request for an address out of the configured range
964         #
965         arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
966                                 dst="ff:ff:ff:ff:ff:ff") /
967                           ARP(op="who-has",
968                               hwsrc=self.pg1.remote_mac,
969                               pdst="10.10.10.125",
970                               psrc=self.pg1.remote_ip4))
971         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
972                                         "ARP req out of range HI")
973         arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
974                                  dst="ff:ff:ff:ff:ff:ff") /
975                            ARP(op="who-has",
976                                hwsrc=self.pg1.remote_mac,
977                                pdst="10.10.10.1",
978                                psrc=self.pg1.remote_ip4))
979         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
980                                         "ARP req out of range Low")
981
982         #
983         # Request for an address in the proxy range but from an interface
984         # in a different VRF
985         #
986         self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
987                                         "ARP req from different VRF")
988
989         #
990         # Disable Each interface for proxy ARP
991         #  - expect none to respond
992         #
993         for i in self.pg_interfaces:
994             i.set_proxy_arp(0)
995
996         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
997                                         "ARP req from disable")
998         self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
999                                         "ARP req from disable")
1000         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
1001                                         "ARP req from disable")
1002
1003         #
1004         # clean up on interface 2
1005         #
1006         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
1007
1008     def test_mpls(self):
1009         """ MPLS """
1010
1011         #
1012         # Interface 2 does not yet have ip4 config
1013         #
1014         self.pg2.config_ip4()
1015         self.pg2.generate_remote_hosts(2)
1016
1017         #
1018         # Add a route with out going label via an ARP unresolved next-hop
1019         #
1020         ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1021                                  [VppRoutePath(self.pg2.remote_hosts[1].ip4,
1022                                                self.pg2.sw_if_index,
1023                                                labels=[55])])
1024         ip_10_0_0_1.add_vpp_config()
1025
1026         #
1027         # packets should generate an ARP request
1028         #
1029         p = (Ether(src=self.pg0.remote_mac,
1030                    dst=self.pg0.local_mac) /
1031              IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
1032              UDP(sport=1234, dport=1234) /
1033              Raw(b'\xa5' * 100))
1034
1035         self.pg0.add_stream(p)
1036         self.pg_enable_capture(self.pg_interfaces)
1037         self.pg_start()
1038
1039         rx = self.pg2.get_capture(1)
1040         self.verify_arp_req(rx[0],
1041                             self.pg2.local_mac,
1042                             self.pg2.local_ip4,
1043                             self.pg2._remote_hosts[1].ip4)
1044
1045         #
1046         # now resolve the neighbours
1047         #
1048         self.pg2.configure_ipv4_neighbors()
1049
1050         #
1051         # Now packet should be properly MPLS encapped.
1052         #  This verifies that MPLS link-type adjacencies are completed
1053         #  when the ARP entry resolves
1054         #
1055         self.pg0.add_stream(p)
1056         self.pg_enable_capture(self.pg_interfaces)
1057         self.pg_start()
1058
1059         rx = self.pg2.get_capture(1)
1060         self.verify_ip_o_mpls(rx[0],
1061                               self.pg2.local_mac,
1062                               self.pg2.remote_hosts[1].mac,
1063                               55,
1064                               self.pg0.remote_ip4,
1065                               "10.0.0.1")
1066         self.pg2.unconfig_ip4()
1067
1068     def test_arp_vrrp(self):
1069         """ ARP reply with VRRP virtual src hw addr """
1070
1071         #
1072         # IP packet destined for pg1 remote host arrives on pg0 resulting
1073         # in an ARP request for the address of the remote host on pg1
1074         #
1075         p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1076               IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1077               UDP(sport=1234, dport=1234) /
1078               Raw())
1079
1080         rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
1081
1082         self.verify_arp_req(rx1[0],
1083                             self.pg1.local_mac,
1084                             self.pg1.local_ip4,
1085                             self.pg1.remote_ip4)
1086
1087         #
1088         # ARP reply for address of pg1 remote host arrives on pg1 with
1089         # the hw src addr set to a value in the VRRP IPv4 range of
1090         # MAC addresses
1091         #
1092         p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1093               ARP(op="is-at", hwdst=self.pg1.local_mac,
1094                   hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1095                   psrc=self.pg1.remote_ip4))
1096
1097         self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1098
1099         #
1100         # IP packet destined for pg1 remote host arrives on pg0 again.
1101         # VPP should have an ARP entry for that address now and the packet
1102         # should be sent out pg1.
1103         #
1104         rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
1105
1106         self.verify_ip(rx1[0],
1107                        self.pg1.local_mac,
1108                        "00:00:5e:00:01:09",
1109                        self.pg0.remote_ip4,
1110                        self.pg1.remote_ip4)
1111
1112         self.pg1.admin_down()
1113         self.pg1.admin_up()
1114
1115     def test_arp_duplicates(self):
1116         """ ARP Duplicates"""
1117
1118         #
1119         # Generate some hosts on the LAN
1120         #
1121         self.pg1.generate_remote_hosts(3)
1122
1123         #
1124         # Add host 1 on pg1 and pg2
1125         #
1126         arp_pg1 = VppNeighbor(self,
1127                               self.pg1.sw_if_index,
1128                               self.pg1.remote_hosts[1].mac,
1129                               self.pg1.remote_hosts[1].ip4)
1130         arp_pg1.add_vpp_config()
1131         arp_pg2 = VppNeighbor(self,
1132                               self.pg2.sw_if_index,
1133                               self.pg2.remote_mac,
1134                               self.pg1.remote_hosts[1].ip4)
1135         arp_pg2.add_vpp_config()
1136
1137         #
1138         # IP packet destined for pg1 remote host arrives on pg1 again.
1139         #
1140         p = (Ether(dst=self.pg0.local_mac,
1141                    src=self.pg0.remote_mac) /
1142              IP(src=self.pg0.remote_ip4,
1143                 dst=self.pg1.remote_hosts[1].ip4) /
1144              UDP(sport=1234, dport=1234) /
1145              Raw())
1146
1147         self.pg0.add_stream(p)
1148         self.pg_enable_capture(self.pg_interfaces)
1149         self.pg_start()
1150
1151         rx1 = self.pg1.get_capture(1)
1152
1153         self.verify_ip(rx1[0],
1154                        self.pg1.local_mac,
1155                        self.pg1.remote_hosts[1].mac,
1156                        self.pg0.remote_ip4,
1157                        self.pg1.remote_hosts[1].ip4)
1158
1159         #
1160         # remove the duplicate on pg1
1161         # packet stream should generate ARPs out of pg1
1162         #
1163         arp_pg1.remove_vpp_config()
1164
1165         self.pg0.add_stream(p)
1166         self.pg_enable_capture(self.pg_interfaces)
1167         self.pg_start()
1168
1169         rx1 = self.pg1.get_capture(1)
1170
1171         self.verify_arp_req(rx1[0],
1172                             self.pg1.local_mac,
1173                             self.pg1.local_ip4,
1174                             self.pg1.remote_hosts[1].ip4)
1175
1176         #
1177         # Add it back
1178         #
1179         arp_pg1.add_vpp_config()
1180
1181         self.pg0.add_stream(p)
1182         self.pg_enable_capture(self.pg_interfaces)
1183         self.pg_start()
1184
1185         rx1 = self.pg1.get_capture(1)
1186
1187         self.verify_ip(rx1[0],
1188                        self.pg1.local_mac,
1189                        self.pg1.remote_hosts[1].mac,
1190                        self.pg0.remote_ip4,
1191                        self.pg1.remote_hosts[1].ip4)
1192
1193     def test_arp_static(self):
1194         """ ARP Static"""
1195         self.pg2.generate_remote_hosts(3)
1196
1197         #
1198         # Add a static ARP entry
1199         #
1200         static_arp = VppNeighbor(self,
1201                                  self.pg2.sw_if_index,
1202                                  self.pg2.remote_hosts[1].mac,
1203                                  self.pg2.remote_hosts[1].ip4,
1204                                  is_static=1)
1205         static_arp.add_vpp_config()
1206
1207         #
1208         # Add the connected prefix to the interface
1209         #
1210         self.pg2.config_ip4()
1211
1212         #
1213         # We should now find the adj-fib
1214         #
1215         self.assertTrue(find_nbr(self,
1216                                  self.pg2.sw_if_index,
1217                                  self.pg2.remote_hosts[1].ip4,
1218                                  is_static=1))
1219         self.assertTrue(find_route(self,
1220                                    self.pg2.remote_hosts[1].ip4,
1221                                    32))
1222
1223         #
1224         # remove the connected
1225         #
1226         self.pg2.unconfig_ip4()
1227
1228         #
1229         # put the interface into table 1
1230         #
1231         self.pg2.set_table_ip4(1)
1232
1233         #
1234         # configure the same connected and expect to find the
1235         # adj fib in the new table
1236         #
1237         self.pg2.config_ip4()
1238         self.assertTrue(find_route(self,
1239                                    self.pg2.remote_hosts[1].ip4,
1240                                    32,
1241                                    table_id=1))
1242
1243         #
1244         # clean-up
1245         #
1246         self.pg2.unconfig_ip4()
1247         static_arp.remove_vpp_config()
1248         self.pg2.set_table_ip4(0)
1249
1250     def test_arp_incomplete(self):
1251         """ ARP Incomplete"""
1252         self.pg1.generate_remote_hosts(3)
1253
1254         p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1255               IP(src=self.pg0.remote_ip4,
1256                  dst=self.pg1.remote_hosts[1].ip4) /
1257               UDP(sport=1234, dport=1234) /
1258               Raw())
1259         p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1260               IP(src=self.pg0.remote_ip4,
1261                  dst=self.pg1.remote_hosts[2].ip4) /
1262               UDP(sport=1234, dport=1234) /
1263               Raw())
1264
1265         #
1266         # a packet to an unresolved destination generates an ARP request
1267         #
1268         rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1269         self.verify_arp_req(rx[0],
1270                             self.pg1.local_mac,
1271                             self.pg1.local_ip4,
1272                             self.pg1._remote_hosts[1].ip4)
1273
1274         #
1275         # add a neighbour for remote host 1
1276         #
1277         static_arp = VppNeighbor(self,
1278                                  self.pg1.sw_if_index,
1279                                  self.pg1.remote_hosts[1].mac,
1280                                  self.pg1.remote_hosts[1].ip4,
1281                                  is_static=1)
1282         static_arp.add_vpp_config()
1283
1284         #
1285         # change the interface's MAC
1286         #
1287         mac = [scapy.compat.chb(0x00), scapy.compat.chb(0x00),
1288                scapy.compat.chb(0x00), scapy.compat.chb(0x33),
1289                scapy.compat.chb(0x33), scapy.compat.chb(0x33)]
1290         mac_string = ''.join(mac)
1291
1292         self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1293                                                mac_string)
1294
1295         #
1296         # now ARP requests come from the new source mac
1297         #
1298         rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1299         self.verify_arp_req(rx[0],
1300                             "00:00:00:33:33:33",
1301                             self.pg1.local_ip4,
1302                             self.pg1._remote_hosts[2].ip4)
1303
1304         #
1305         # packets to the resolved host also have the new source mac
1306         #
1307         rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1308         self.verify_ip(rx[0],
1309                        "00:00:00:33:33:33",
1310                        self.pg1.remote_hosts[1].mac,
1311                        self.pg0.remote_ip4,
1312                        self.pg1.remote_hosts[1].ip4)
1313
1314         #
1315         # set the mac address on the interface that does not have a
1316         # configured subnet and thus no glean
1317         #
1318         self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1319                                                mac_string)
1320
1321     def test_garp(self):
1322         """ GARP """
1323
1324         #
1325         # Generate some hosts on the LAN
1326         #
1327         self.pg1.generate_remote_hosts(4)
1328
1329         #
1330         # And an ARP entry
1331         #
1332         arp = VppNeighbor(self,
1333                           self.pg1.sw_if_index,
1334                           self.pg1.remote_hosts[1].mac,
1335                           self.pg1.remote_hosts[1].ip4)
1336         arp.add_vpp_config()
1337
1338         self.assertTrue(find_nbr(self,
1339                                  self.pg1.sw_if_index,
1340                                  self.pg1.remote_hosts[1].ip4,
1341                                  mac=self.pg1.remote_hosts[1].mac))
1342
1343         #
1344         # Send a GARP (request) to swap the host 1's address to that of host 2
1345         #
1346         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1347                     src=self.pg1.remote_hosts[2].mac) /
1348               ARP(op="who-has",
1349                   hwdst=self.pg1.local_mac,
1350                   hwsrc=self.pg1.remote_hosts[2].mac,
1351                   pdst=self.pg1.remote_hosts[1].ip4,
1352                   psrc=self.pg1.remote_hosts[1].ip4))
1353
1354         self.pg1.add_stream(p1)
1355         self.pg_enable_capture(self.pg_interfaces)
1356         self.pg_start()
1357
1358         self.assertTrue(find_nbr(self,
1359                                  self.pg1.sw_if_index,
1360                                  self.pg1.remote_hosts[1].ip4,
1361                                  mac=self.pg1.remote_hosts[2].mac))
1362
1363         #
1364         # Send a GARP (reply) to swap the host 1's address to that of host 3
1365         #
1366         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1367                     src=self.pg1.remote_hosts[3].mac) /
1368               ARP(op="is-at",
1369                   hwdst=self.pg1.local_mac,
1370                   hwsrc=self.pg1.remote_hosts[3].mac,
1371                   pdst=self.pg1.remote_hosts[1].ip4,
1372                   psrc=self.pg1.remote_hosts[1].ip4))
1373
1374         self.pg1.add_stream(p1)
1375         self.pg_enable_capture(self.pg_interfaces)
1376         self.pg_start()
1377
1378         self.assertTrue(find_nbr(self,
1379                                  self.pg1.sw_if_index,
1380                                  self.pg1.remote_hosts[1].ip4,
1381                                  mac=self.pg1.remote_hosts[3].mac))
1382
1383         #
1384         # GARPs (request nor replies) for host we don't know yet
1385         # don't result in new neighbour entries
1386         #
1387         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1388                     src=self.pg1.remote_hosts[3].mac) /
1389               ARP(op="who-has",
1390                   hwdst=self.pg1.local_mac,
1391                   hwsrc=self.pg1.remote_hosts[3].mac,
1392                   pdst=self.pg1.remote_hosts[2].ip4,
1393                   psrc=self.pg1.remote_hosts[2].ip4))
1394
1395         self.pg1.add_stream(p1)
1396         self.pg_enable_capture(self.pg_interfaces)
1397         self.pg_start()
1398
1399         self.assertFalse(find_nbr(self,
1400                                   self.pg1.sw_if_index,
1401                                   self.pg1.remote_hosts[2].ip4))
1402
1403         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1404                     src=self.pg1.remote_hosts[3].mac) /
1405               ARP(op="is-at",
1406                   hwdst=self.pg1.local_mac,
1407                   hwsrc=self.pg1.remote_hosts[3].mac,
1408                   pdst=self.pg1.remote_hosts[2].ip4,
1409                   psrc=self.pg1.remote_hosts[2].ip4))
1410
1411         self.pg1.add_stream(p1)
1412         self.pg_enable_capture(self.pg_interfaces)
1413         self.pg_start()
1414
1415         self.assertFalse(find_nbr(self,
1416                                   self.pg1.sw_if_index,
1417                                   self.pg1.remote_hosts[2].ip4))
1418
1419     def test_arp_incomplete(self):
1420         """ Incomplete Entries """
1421
1422         #
1423         # ensure that we throttle the ARP and ND requests
1424         #
1425         self.pg0.generate_remote_hosts(2)
1426
1427         #
1428         # IPv4/ARP
1429         #
1430         ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1431                                  [VppRoutePath(self.pg0.remote_hosts[1].ip4,
1432                                                self.pg0.sw_if_index)])
1433         ip_10_0_0_1.add_vpp_config()
1434
1435         p1 = (Ether(dst=self.pg1.local_mac,
1436                     src=self.pg1.remote_mac) /
1437               IP(src=self.pg1.remote_ip4,
1438                  dst="10.0.0.1") /
1439               UDP(sport=1234, dport=1234) /
1440               Raw())
1441
1442         self.pg1.add_stream(p1 * 257)
1443         self.pg_enable_capture(self.pg_interfaces)
1444         self.pg_start()
1445         rx = self.pg0._get_capture(1)
1446
1447         #
1448         # how many we get is going to be dependent on the time for packet
1449         # processing but it should be small
1450         #
1451         self.assertLess(len(rx), 64)
1452
1453         #
1454         # IPv6/ND
1455         #
1456         ip_10_1 = VppIpRoute(self, "10::1", 128,
1457                              [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1458                                            self.pg0.sw_if_index,
1459                                            proto=DpoProto.DPO_PROTO_IP6)])
1460         ip_10_1.add_vpp_config()
1461
1462         p1 = (Ether(dst=self.pg1.local_mac,
1463                     src=self.pg1.remote_mac) /
1464               IPv6(src=self.pg1.remote_ip6,
1465                    dst="10::1") /
1466               UDP(sport=1234, dport=1234) /
1467               Raw())
1468
1469         self.pg1.add_stream(p1 * 257)
1470         self.pg_enable_capture(self.pg_interfaces)
1471         self.pg_start()
1472         rx = self.pg0._get_capture(1)
1473
1474         #
1475         # how many we get is going to be dependent on the time for packet
1476         # processing but it should be small
1477         #
1478         self.assertLess(len(rx), 64)
1479
1480     def test_arp_forus(self):
1481         """ ARP for for-us """
1482
1483         #
1484         # Test that VPP responds with ARP requests to addresses that
1485         # are connected and local routes.
1486         # Use one of the 'remote' addresses in the subnet as a local address
1487         # The intention of this route is that it then acts like a secondary
1488         # address added to an interface
1489         #
1490         self.pg0.generate_remote_hosts(2)
1491
1492         forus = VppIpRoute(
1493             self, self.pg0.remote_hosts[1].ip4, 32,
1494             [VppRoutePath("0.0.0.0",
1495                           self.pg0.sw_if_index,
1496                           type=FibPathType.FIB_PATH_TYPE_LOCAL)])
1497         forus.add_vpp_config()
1498
1499         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1500                    src=self.pg0.remote_mac) /
1501              ARP(op="who-has",
1502                  hwdst=self.pg0.local_mac,
1503                  hwsrc=self.pg0.remote_mac,
1504                  pdst=self.pg0.remote_hosts[1].ip4,
1505                  psrc=self.pg0.remote_ip4))
1506
1507         rx = self.send_and_expect(self.pg0, [p], self.pg0)
1508
1509         self.verify_arp_resp(rx[0],
1510                              self.pg0.local_mac,
1511                              self.pg0.remote_mac,
1512                              self.pg0.remote_hosts[1].ip4,
1513                              self.pg0.remote_ip4)
1514
1515     def test_arp_table_swap(self):
1516         #
1517         # Generate some hosts on the LAN
1518         #
1519         N_NBRS = 4
1520         self.pg1.generate_remote_hosts(N_NBRS)
1521
1522         for n in range(N_NBRS):
1523             # a route thru each neighbour
1524             VppIpRoute(self, "10.0.0.%d" % n, 32,
1525                        [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1526                                      self.pg1.sw_if_index)]).add_vpp_config()
1527
1528             # resolve each neighbour
1529             p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1530                   ARP(op="is-at", hwdst=self.pg1.local_mac,
1531                       hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1532                       psrc=self.pg1.remote_hosts[n].ip4))
1533
1534             self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1535
1536         self.logger.info(self.vapi.cli("sh ip neighbors"))
1537
1538         #
1539         # swap the table pg1 is in
1540         #
1541         table = VppIpTable(self, 100).add_vpp_config()
1542
1543         self.pg1.unconfig_ip4()
1544         self.pg1.set_table_ip4(100)
1545         self.pg1.config_ip4()
1546
1547         #
1548         # all neighbours are cleared
1549         #
1550         for n in range(N_NBRS):
1551             self.assertFalse(find_nbr(self,
1552                                       self.pg1.sw_if_index,
1553                                       self.pg1.remote_hosts[n].ip4))
1554
1555         #
1556         # packets to all neighbours generate ARP requests
1557         #
1558         for n in range(N_NBRS):
1559             # a route thru each neighbour
1560             VppIpRoute(self, "10.0.0.%d" % n, 32,
1561                        [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1562                                      self.pg1.sw_if_index)],
1563                        table_id=100).add_vpp_config()
1564
1565             p = (Ether(src=self.pg1.remote_hosts[n].mac,
1566                        dst=self.pg1.local_mac) /
1567                  IP(src=self.pg1.remote_hosts[n].ip4,
1568                     dst="10.0.0.%d" % n) /
1569                  Raw(b'0x5' * 100))
1570             rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1571             for rx in rxs:
1572                 self.verify_arp_req(rx,
1573                                     self.pg1.local_mac,
1574                                     self.pg1.local_ip4,
1575                                     self.pg1.remote_hosts[n].ip4)
1576
1577         self.pg1.unconfig_ip4()
1578         self.pg1.set_table_ip4(0)
1579
1580
1581 class NeighborStatsTestCase(VppTestCase):
1582     """ ARP/ND Counters """
1583
1584     @classmethod
1585     def setUpClass(cls):
1586         super(NeighborStatsTestCase, cls).setUpClass()
1587
1588     @classmethod
1589     def tearDownClass(cls):
1590         super(NeighborStatsTestCase, cls).tearDownClass()
1591
1592     def setUp(self):
1593         super(NeighborStatsTestCase, self).setUp()
1594
1595         self.create_pg_interfaces(range(2))
1596
1597         # pg0 configured with ip4 and 6 addresses used for input
1598         # pg1 configured with ip4 and 6 addresses used for output
1599         # pg2 is unnumbered to pg0
1600         for i in self.pg_interfaces:
1601             i.admin_up()
1602             i.config_ip4()
1603             i.config_ip6()
1604             i.resolve_arp()
1605             i.resolve_ndp()
1606
1607     def tearDown(self):
1608         super(NeighborStatsTestCase, self).tearDown()
1609
1610         for i in self.pg_interfaces:
1611             i.unconfig_ip4()
1612             i.unconfig_ip6()
1613             i.admin_down()
1614
1615     def test_arp_stats(self):
1616         """ ARP Counters """
1617
1618         self.vapi.cli("adj counters enable")
1619         self.pg1.generate_remote_hosts(2)
1620
1621         arp1 = VppNeighbor(self,
1622                            self.pg1.sw_if_index,
1623                            self.pg1.remote_hosts[0].mac,
1624                            self.pg1.remote_hosts[0].ip4)
1625         arp1.add_vpp_config()
1626         arp2 = VppNeighbor(self,
1627                            self.pg1.sw_if_index,
1628                            self.pg1.remote_hosts[1].mac,
1629                            self.pg1.remote_hosts[1].ip4)
1630         arp2.add_vpp_config()
1631
1632         p1 = (Ether(dst=self.pg0.local_mac,
1633                     src=self.pg0.remote_mac) /
1634               IP(src=self.pg0.remote_ip4,
1635                  dst=self.pg1.remote_hosts[0].ip4) /
1636               UDP(sport=1234, dport=1234) /
1637               Raw())
1638         p2 = (Ether(dst=self.pg0.local_mac,
1639                     src=self.pg0.remote_mac) /
1640               IP(src=self.pg0.remote_ip4,
1641                  dst=self.pg1.remote_hosts[1].ip4) /
1642               UDP(sport=1234, dport=1234) /
1643               Raw())
1644
1645         rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1646         rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
1647
1648         self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1649         self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
1650
1651         rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1652         self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
1653
1654     def test_nd_stats(self):
1655         """ ND Counters """
1656
1657         self.vapi.cli("adj counters enable")
1658         self.pg0.generate_remote_hosts(3)
1659
1660         nd1 = VppNeighbor(self,
1661                           self.pg0.sw_if_index,
1662                           self.pg0.remote_hosts[1].mac,
1663                           self.pg0.remote_hosts[1].ip6)
1664         nd1.add_vpp_config()
1665         nd2 = VppNeighbor(self,
1666                           self.pg0.sw_if_index,
1667                           self.pg0.remote_hosts[2].mac,
1668                           self.pg0.remote_hosts[2].ip6)
1669         nd2.add_vpp_config()
1670
1671         p1 = (Ether(dst=self.pg1.local_mac,
1672                     src=self.pg1.remote_mac) /
1673               IPv6(src=self.pg1.remote_ip6,
1674                    dst=self.pg0.remote_hosts[1].ip6) /
1675               UDP(sport=1234, dport=1234) /
1676               Raw())
1677         p2 = (Ether(dst=self.pg1.local_mac,
1678                     src=self.pg1.remote_mac) /
1679               IPv6(src=self.pg1.remote_ip6,
1680                    dst=self.pg0.remote_hosts[2].ip6) /
1681               UDP(sport=1234, dport=1234) /
1682               Raw())
1683
1684         rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1685         rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1686
1687         self.assertEqual(16, nd1.get_stats()['packets'])
1688         self.assertEqual(16, nd2.get_stats()['packets'])
1689
1690         rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1691         self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
1692
1693
1694 class NeighborAgeTestCase(VppTestCase):
1695     """ ARP/ND Aging """
1696
1697     @classmethod
1698     def setUpClass(cls):
1699         super(NeighborAgeTestCase, cls).setUpClass()
1700
1701     @classmethod
1702     def tearDownClass(cls):
1703         super(NeighborAgeTestCase, cls).tearDownClass()
1704
1705     def setUp(self):
1706         super(NeighborAgeTestCase, self).setUp()
1707
1708         self.create_pg_interfaces(range(1))
1709
1710         # pg0 configured with ip4 and 6 addresses used for input
1711         # pg1 configured with ip4 and 6 addresses used for output
1712         # pg2 is unnumbered to pg0
1713         for i in self.pg_interfaces:
1714             i.admin_up()
1715             i.config_ip4()
1716             i.config_ip6()
1717             i.resolve_arp()
1718             i.resolve_ndp()
1719
1720     def tearDown(self):
1721         super(NeighborAgeTestCase, self).tearDown()
1722
1723         for i in self.pg_interfaces:
1724             i.unconfig_ip4()
1725             i.unconfig_ip6()
1726             i.admin_down()
1727
1728     def wait_for_no_nbr(self, intf, address,
1729                         n_tries=50, s_time=1):
1730         while (n_tries):
1731             if not find_nbr(self, intf, address):
1732                 return True
1733             n_tries = n_tries - 1
1734             self.sleep(s_time)
1735
1736         return False
1737
1738     def verify_arp_req(self, rx, smac, sip, dip):
1739         ether = rx[Ether]
1740         self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1741         self.assertEqual(ether.src, smac)
1742
1743         arp = rx[ARP]
1744         self.assertEqual(arp.hwtype, 1)
1745         self.assertEqual(arp.ptype, 0x800)
1746         self.assertEqual(arp.hwlen, 6)
1747         self.assertEqual(arp.plen, 4)
1748         self.assertEqual(arp.op, arp_opts["who-has"])
1749         self.assertEqual(arp.hwsrc, smac)
1750         self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
1751         self.assertEqual(arp.psrc, sip)
1752         self.assertEqual(arp.pdst, dip)
1753
1754     def test_age(self):
1755         """ Aging/Recycle """
1756
1757         self.vapi.cli("set logging unthrottle 0")
1758         self.vapi.cli("set logging size %d" % 0xffff)
1759
1760         self.pg0.generate_remote_hosts(201)
1761
1762         vaf = VppEnum.vl_api_address_family_t
1763
1764         #
1765         # start listening on all interfaces
1766         #
1767         self.pg_enable_capture(self.pg_interfaces)
1768
1769         #
1770         # Set the neighbor configuration:
1771         #   limi = 200
1772         #   age  = 0 seconds
1773         #   recycle = false
1774         #
1775         self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1776                                      max_number=200,
1777                                      max_age=0,
1778                                      recycle=False)
1779
1780         self.vapi.cli("sh ip neighbor-config")
1781
1782         # add the 198 neighbours that should pass (-1 for one created in setup)
1783         for ii in range(200):
1784             VppNeighbor(self,
1785                         self.pg0.sw_if_index,
1786                         self.pg0.remote_hosts[ii].mac,
1787                         self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1788
1789         # one more neighbor over the limit should fail
1790         with self.vapi.assert_negative_api_retval():
1791             VppNeighbor(self,
1792                         self.pg0.sw_if_index,
1793                         self.pg0.remote_hosts[200].mac,
1794                         self.pg0.remote_hosts[200].ip4).add_vpp_config()
1795
1796         #
1797         # change the config to allow recycling the old neighbors
1798         #
1799         self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1800                                      max_number=200,
1801                                      max_age=0,
1802                                      recycle=True)
1803
1804         # now new additions are allowed
1805         VppNeighbor(self,
1806                     self.pg0.sw_if_index,
1807                     self.pg0.remote_hosts[200].mac,
1808                     self.pg0.remote_hosts[200].ip4).add_vpp_config()
1809
1810         # add the first neighbor we configured has been re-used
1811         self.assertFalse(find_nbr(self,
1812                                   self.pg0.sw_if_index,
1813                                   self.pg0.remote_hosts[0].ip4))
1814         self.assertTrue(find_nbr(self,
1815                                  self.pg0.sw_if_index,
1816                                  self.pg0.remote_hosts[200].ip4))
1817
1818         #
1819         # change the config to age old neighbors
1820         #
1821         self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1822                                      max_number=200,
1823                                      max_age=2,
1824                                      recycle=True)
1825
1826         self.vapi.cli("sh ip4 neighbor-sorted")
1827
1828         #
1829         # expect probes from all these ARP entries as they age
1830         # 3 probes for each neighbor 3*200 = 600
1831         rxs = self.pg0.get_capture(600, timeout=8)
1832
1833         for ii in range(3):
1834             for jj in range(200):
1835                 rx = rxs[ii*200 + jj]
1836                 # rx.show()
1837
1838         #
1839         # 3 probes sent then 1 more second to see if a reply comes, before
1840         # they age out
1841         #
1842         for jj in range(1, 201):
1843             self.wait_for_no_nbr(self.pg0.sw_if_index,
1844                                  self.pg0.remote_hosts[jj].ip4)
1845
1846         self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1847                                                     af=vaf.ADDRESS_IP4))
1848
1849         #
1850         # load up some neighbours again with 2s aging enabled
1851         # they should be removed after 10s (2s age + 4s for probes + gap)
1852         #
1853         for ii in range(10):
1854             VppNeighbor(self,
1855                         self.pg0.sw_if_index,
1856                         self.pg0.remote_hosts[ii].mac,
1857                         self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1858         self.sleep(10)
1859         self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1860                                                     af=vaf.ADDRESS_IP4))
1861
1862         #
1863         # check if we can set age and recycle with empty neighbor list
1864         #
1865         self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1866                                      max_number=200,
1867                                      max_age=1000,
1868                                      recycle=True)
1869
1870         #
1871         # load up some neighbours again, then disable the aging
1872         # they should still be there in 10 seconds time
1873         #
1874         for ii in range(10):
1875             VppNeighbor(self,
1876                         self.pg0.sw_if_index,
1877                         self.pg0.remote_hosts[ii].mac,
1878                         self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1879         self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1880                                      max_number=200,
1881                                      max_age=0,
1882                                      recycle=False)
1883
1884         self.sleep(10)
1885         self.assertTrue(find_nbr(self,
1886                                  self.pg0.sw_if_index,
1887                                  self.pg0.remote_hosts[0].ip4))
1888
1889
1890 class NeighborReplaceTestCase(VppTestCase):
1891     """ ARP/ND Replacement """
1892
1893     @classmethod
1894     def setUpClass(cls):
1895         super(NeighborReplaceTestCase, cls).setUpClass()
1896
1897     @classmethod
1898     def tearDownClass(cls):
1899         super(NeighborReplaceTestCase, cls).tearDownClass()
1900
1901     def setUp(self):
1902         super(NeighborReplaceTestCase, self).setUp()
1903
1904         self.create_pg_interfaces(range(4))
1905
1906         # pg0 configured with ip4 and 6 addresses used for input
1907         # pg1 configured with ip4 and 6 addresses used for output
1908         # pg2 is unnumbered to pg0
1909         for i in self.pg_interfaces:
1910             i.admin_up()
1911             i.config_ip4()
1912             i.config_ip6()
1913             i.resolve_arp()
1914             i.resolve_ndp()
1915
1916     def tearDown(self):
1917         super(NeighborReplaceTestCase, self).tearDown()
1918
1919         for i in self.pg_interfaces:
1920             i.unconfig_ip4()
1921             i.unconfig_ip6()
1922             i.admin_down()
1923
1924     def test_replace(self):
1925         """ replace """
1926
1927         N_HOSTS = 16
1928
1929         for i in self.pg_interfaces:
1930             i.generate_remote_hosts(N_HOSTS)
1931             i.configure_ipv4_neighbors()
1932             i.configure_ipv6_neighbors()
1933
1934         # replace them all
1935         self.vapi.ip_neighbor_replace_begin()
1936         self.vapi.ip_neighbor_replace_end()
1937
1938         for i in self.pg_interfaces:
1939             for h in range(N_HOSTS):
1940                 self.assertFalse(find_nbr(self,
1941                                           self.pg0.sw_if_index,
1942                                           self.pg0.remote_hosts[h].ip4))
1943                 self.assertFalse(find_nbr(self,
1944                                           self.pg0.sw_if_index,
1945                                           self.pg0.remote_hosts[h].ip6))
1946
1947         #
1948         # and them all back via the API
1949         #
1950         for i in self.pg_interfaces:
1951             for h in range(N_HOSTS):
1952                 VppNeighbor(self,
1953                             i.sw_if_index,
1954                             i.remote_hosts[h].mac,
1955                             i.remote_hosts[h].ip4).add_vpp_config()
1956                 VppNeighbor(self,
1957                             i.sw_if_index,
1958                             i.remote_hosts[h].mac,
1959                             i.remote_hosts[h].ip6).add_vpp_config()
1960
1961         #
1962         # begin the replacement again, this time touch some
1963         # the neighbours on pg1 so they are not deleted
1964         #
1965         self.vapi.ip_neighbor_replace_begin()
1966
1967         # update from the API all neighbours on pg1
1968         for h in range(N_HOSTS):
1969             VppNeighbor(self,
1970                         self.pg1.sw_if_index,
1971                         self.pg1.remote_hosts[h].mac,
1972                         self.pg1.remote_hosts[h].ip4).add_vpp_config()
1973             VppNeighbor(self,
1974                         self.pg1.sw_if_index,
1975                         self.pg1.remote_hosts[h].mac,
1976                         self.pg1.remote_hosts[h].ip6).add_vpp_config()
1977
1978         # update from the data-plane all neighbours on pg3
1979         self.pg3.configure_ipv4_neighbors()
1980         self.pg3.configure_ipv6_neighbors()
1981
1982         # complete the replacement
1983         self.logger.info(self.vapi.cli("sh ip neighbors"))
1984         self.vapi.ip_neighbor_replace_end()
1985
1986         for i in self.pg_interfaces:
1987             if i == self.pg1 or i == self.pg3:
1988                 # neighbours on pg1 and pg3 are still present
1989                 for h in range(N_HOSTS):
1990                     self.assertTrue(find_nbr(self,
1991                                              i.sw_if_index,
1992                                              i.remote_hosts[h].ip4))
1993                     self.assertTrue(find_nbr(self,
1994                                              i.sw_if_index,
1995                                              i.remote_hosts[h].ip6))
1996             else:
1997                 # all other neighbours are toast
1998                 for h in range(N_HOSTS):
1999                     self.assertFalse(find_nbr(self,
2000                                               i.sw_if_index,
2001                                               i.remote_hosts[h].ip4))
2002                     self.assertFalse(find_nbr(self,
2003                                               i.sw_if_index,
2004                                               i.remote_hosts[h].ip6))
2005
2006
2007 class NeighborFlush(VppTestCase):
2008     """ Neighbor Flush """
2009
2010     @classmethod
2011     def setUpClass(cls):
2012         super(NeighborFlush, cls).setUpClass()
2013
2014     @classmethod
2015     def tearDownClass(cls):
2016         super(NeighborFlush, cls).tearDownClass()
2017
2018     def setUp(self):
2019         super(NeighborFlush, self).setUp()
2020
2021         self.create_pg_interfaces(range(2))
2022
2023         for i in self.pg_interfaces:
2024             i.admin_up()
2025             i.config_ip4()
2026             i.config_ip6()
2027             i.resolve_arp()
2028             i.resolve_ndp()
2029
2030     def tearDown(self):
2031         super(NeighborFlush, self).tearDown()
2032
2033         for i in self.pg_interfaces:
2034             i.unconfig_ip4()
2035             i.unconfig_ip6()
2036             i.admin_down()
2037
2038     def test_flush(self):
2039         """ Neighbour Flush """
2040
2041         e = VppEnum
2042         nf = e.vl_api_ip_neighbor_flags_t
2043         af = e.vl_api_address_family_t
2044         N_HOSTS = 16
2045         static = [False, True]
2046         self.pg0.generate_remote_hosts(N_HOSTS)
2047         self.pg1.generate_remote_hosts(N_HOSTS)
2048
2049         for s in static:
2050             # a few v4 and v6 dynamic neoghbors
2051             for n in range(N_HOSTS):
2052                 VppNeighbor(self,
2053                             self.pg0.sw_if_index,
2054                             self.pg0.remote_hosts[n].mac,
2055                             self.pg0.remote_hosts[n].ip4,
2056                             is_static=s).add_vpp_config()
2057                 VppNeighbor(self,
2058                             self.pg1.sw_if_index,
2059                             self.pg1.remote_hosts[n].mac,
2060                             self.pg1.remote_hosts[n].ip6,
2061                             is_static=s).add_vpp_config()
2062
2063             # flush the interfaces individually
2064             self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2065
2066             # check we haven't flushed that which we shouldn't
2067             for n in range(N_HOSTS):
2068                 self.assertTrue(find_nbr(self,
2069                                          self.pg1.sw_if_index,
2070                                          self.pg1.remote_hosts[n].ip6,
2071                                          is_static=s))
2072
2073             self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2074
2075             for n in range(N_HOSTS):
2076                 self.assertFalse(find_nbr(self,
2077                                           self.pg0.sw_if_index,
2078                                           self.pg0.remote_hosts[n].ip4))
2079                 self.assertFalse(find_nbr(self,
2080                                           self.pg1.sw_if_index,
2081                                           self.pg1.remote_hosts[n].ip6))
2082
2083             # add the nieghbours back
2084             for n in range(N_HOSTS):
2085                 VppNeighbor(self,
2086                             self.pg0.sw_if_index,
2087                             self.pg0.remote_hosts[n].mac,
2088                             self.pg0.remote_hosts[n].ip4,
2089                             is_static=s).add_vpp_config()
2090                 VppNeighbor(self,
2091                             self.pg1.sw_if_index,
2092                             self.pg1.remote_hosts[n].mac,
2093                             self.pg1.remote_hosts[n].ip6,
2094                             is_static=s).add_vpp_config()
2095
2096             self.logger.info(self.vapi.cli("sh ip neighbor"))
2097
2098             # flush both interfaces at the same time
2099             self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2100
2101             # check we haven't flushed that which we shouldn't
2102             for n in range(N_HOSTS):
2103                 self.assertTrue(find_nbr(self,
2104                                          self.pg0.sw_if_index,
2105                                          self.pg0.remote_hosts[n].ip4,
2106                                          is_static=s))
2107
2108             self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2109
2110             for n in range(N_HOSTS):
2111                 self.assertFalse(find_nbr(self,
2112                                           self.pg0.sw_if_index,
2113                                           self.pg0.remote_hosts[n].ip4))
2114                 self.assertFalse(find_nbr(self,
2115                                           self.pg1.sw_if_index,
2116                                           self.pg1.remote_hosts[n].ip6))
2117
2118
2119 if __name__ == '__main__':
2120     unittest.main(testRunner=VppTestRunner)