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