blob: 2dc27a83b0aa17b8af108f64de80a94ac4a7c6b8 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns39f9d8b2017-02-16 21:57:05 -08002
3import unittest
Neale Rannscbe25aa2019-09-30 10:53:31 +00004import os
Neale Ranns39f9d8b2017-02-16 21:57:05 -08005from socket import AF_INET, AF_INET6, inet_pton
6
7from framework import VppTestCase, VppTestRunner
8from vpp_neighbor import VppNeighbor, find_nbr
Neale Ranns15002542017-09-10 04:39:11 -07009from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
Neale Ranns097fa662018-05-01 05:17:55 -070010 VppIpTable, DpoProto, FibPathType
Neale Ranns37029302018-08-10 05:30:06 -070011from vpp_papi import VppEnum
Neale Ranns39f9d8b2017-02-16 21:57:05 -080012
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070013import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080014from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070015from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000016from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070017from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080018from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070019from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080020
Paul Vinciguerra4271c972019-05-14 13:25:49 -040021
22NUM_PKTS = 67
23
Neale Ranns39f9d8b2017-02-16 21:57:05 -080024# not exported by scapy, so redefined here
25arp_opts = {"who-has": 1, "is-at": 2}
26
27
28class ARPTestCase(VppTestCase):
29 """ ARP Test Case """
30
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070031 @classmethod
32 def setUpClass(cls):
33 super(ARPTestCase, cls).setUpClass()
34
35 @classmethod
36 def tearDownClass(cls):
37 super(ARPTestCase, cls).tearDownClass()
38
Neale Ranns39f9d8b2017-02-16 21:57:05 -080039 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
Neale Ranns15002542017-09-10 04:39:11 -070059 self.tbl = VppIpTable(self, 1)
60 self.tbl.add_vpp_config()
61
Neale Ranns39f9d8b2017-02-16 21:57:05 -080062 self.pg3.set_table_ip4(1)
63 self.pg3.config_ip4()
64
Neale Ranns4008ac92017-02-13 23:20:04 -080065 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080066 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()
Neale Ranns15002542017-09-10 04:39:11 -070073 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080074
Neale Ranns4008ac92017-02-13 23:20:04 -080075 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080076 i.admin_down()
77
Neale Ranns15002542017-09-10 04:39:11 -070078 super(ARPTestCase, self).tearDown()
79
Neale Ranns39f9d8b2017-02-16 21:57:05 -080080 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
Matthew Smithcb9ab472017-05-16 21:35:56 -0500112 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
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800130 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
Neale Ranns37be7362017-02-21 17:30:26 -0800139 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
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800151 def test_arp(self):
152 """ ARP """
153
154 #
155 # Generate some hosts on the LAN
156 #
Neale Rannsca193612017-06-14 06:50:08 -0700157 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800158
159 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000160 # 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 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800178 # 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()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000205 self.assertTrue(dyn_arp.query_vpp_config())
206
Neale Rannsdc617b82020-08-20 08:22:56 +0000207 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
208
Neale Rannscbe25aa2019-09-30 10:53:31 +0000209 # this matches all of the listnerers
210 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
211 for i in range(3)]
212 for e in es:
213 self.assertEqual(str(e.neighbor.ip_address),
214 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800215
216 #
217 # now we expect IP traffic forwarded
218 #
219 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
220 IP(src=self.pg0.remote_ip4,
221 dst=self.pg1._remote_hosts[1].ip4) /
222 UDP(sport=1234, dport=1234) /
223 Raw())
224
225 self.pg0.add_stream(dyn_p)
226 self.pg_enable_capture(self.pg_interfaces)
227 self.pg_start()
228
229 rx = self.pg1.get_capture(1)
230
231 self.verify_ip(rx[0],
232 self.pg1.local_mac,
233 self.pg1.remote_hosts[1].mac,
234 self.pg0.remote_ip4,
235 self.pg1._remote_hosts[1].ip4)
236
237 #
238 # And a Static ARP entry for host 2
239 #
240 static_arp = VppNeighbor(self,
241 self.pg1.sw_if_index,
242 self.pg1.remote_hosts[2].mac,
243 self.pg1.remote_hosts[2].ip4,
244 is_static=1)
245 static_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000246 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
247 for i in range(2)]
248 for e in es:
249 self.assertEqual(str(e.neighbor.ip_address),
250 self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800251
252 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
253 IP(src=self.pg0.remote_ip4,
254 dst=self.pg1._remote_hosts[2].ip4) /
255 UDP(sport=1234, dport=1234) /
256 Raw())
257
258 self.pg0.add_stream(static_p)
259 self.pg_enable_capture(self.pg_interfaces)
260 self.pg_start()
261
262 rx = self.pg1.get_capture(1)
263
264 self.verify_ip(rx[0],
265 self.pg1.local_mac,
266 self.pg1.remote_hosts[2].mac,
267 self.pg0.remote_ip4,
268 self.pg1._remote_hosts[2].ip4)
269
270 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000271 # remove all the listeners
272 #
273 self.vapi.want_ip_neighbor_events(enable=0,
274 pid=os.getpid())
275 self.vapi.want_ip_neighbor_events(enable=0,
276 pid=os.getpid(),
277 sw_if_index=self.pg1.sw_if_index)
278 self.vapi.want_ip_neighbor_events(enable=0,
279 pid=os.getpid(),
280 sw_if_index=self.pg1.sw_if_index,
281 ip=self.pg1.remote_hosts[1].ip4)
282
283 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800284 # flap the link. dynamic ARPs get flush, statics don't
285 #
286 self.pg1.admin_down()
287 self.pg1.admin_up()
288
289 self.pg0.add_stream(static_p)
290 self.pg_enable_capture(self.pg_interfaces)
291 self.pg_start()
292 rx = self.pg1.get_capture(1)
293
294 self.verify_ip(rx[0],
295 self.pg1.local_mac,
296 self.pg1.remote_hosts[2].mac,
297 self.pg0.remote_ip4,
298 self.pg1._remote_hosts[2].ip4)
299
300 self.pg0.add_stream(dyn_p)
301 self.pg_enable_capture(self.pg_interfaces)
302 self.pg_start()
303
304 rx = self.pg1.get_capture(1)
305 self.verify_arp_req(rx[0],
306 self.pg1.local_mac,
307 self.pg1.local_ip4,
308 self.pg1._remote_hosts[1].ip4)
309
Neale Rannscbe25aa2019-09-30 10:53:31 +0000310 self.assertFalse(dyn_arp.query_vpp_config())
311 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800312 #
313 # Send an ARP request from one of the so-far unlearned remote hosts
314 #
315 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
316 src=self.pg1._remote_hosts[3].mac) /
317 ARP(op="who-has",
318 hwsrc=self.pg1._remote_hosts[3].mac,
319 pdst=self.pg1.local_ip4,
320 psrc=self.pg1._remote_hosts[3].ip4))
321
322 self.pg1.add_stream(p)
323 self.pg_enable_capture(self.pg_interfaces)
324 self.pg_start()
325
326 rx = self.pg1.get_capture(1)
327 self.verify_arp_resp(rx[0],
328 self.pg1.local_mac,
329 self.pg1._remote_hosts[3].mac,
330 self.pg1.local_ip4,
331 self.pg1._remote_hosts[3].ip4)
332
333 #
334 # VPP should have learned the mapping for the remote host
335 #
336 self.assertTrue(find_nbr(self,
337 self.pg1.sw_if_index,
338 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800339 #
340 # Fire in an ARP request before the interface becomes IP enabled
341 #
342 self.pg2.generate_remote_hosts(4)
343
344 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
345 ARP(op="who-has",
346 hwsrc=self.pg2.remote_mac,
347 pdst=self.pg1.local_ip4,
348 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700349 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
350 Dot1Q(vlan=0) /
351 ARP(op="who-has",
352 hwsrc=self.pg2.remote_mac,
353 pdst=self.pg1.local_ip4,
354 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800355 self.send_and_assert_no_replies(self.pg2, p,
356 "interface not IP enabled")
357
358 #
359 # Make pg2 un-numbered to pg1
360 #
361 self.pg2.set_unnumbered(self.pg1.sw_if_index)
362
Neale Rannsac3e72c2019-10-06 01:04:26 -0700363 #
364 # test the unnumbered dump both by all interfaces and just the enabled
365 # one
366 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700367 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700368 self.assertTrue(len(unnum))
369 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
370 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
371 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
372 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700373 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
374 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
375
Neale Ranns4b919a52017-03-11 05:55:21 -0800376 #
377 # We should respond to ARP requests for the unnumbered to address
378 # once an attached route to the source is known
379 #
380 self.send_and_assert_no_replies(
381 self.pg2, p,
382 "ARP req for unnumbered address - no source")
383
384 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
385 [VppRoutePath("0.0.0.0",
386 self.pg2.sw_if_index)])
387 attached_host.add_vpp_config()
388
389 self.pg2.add_stream(p)
390 self.pg_enable_capture(self.pg_interfaces)
391 self.pg_start()
392
393 rx = self.pg2.get_capture(1)
394 self.verify_arp_resp(rx[0],
395 self.pg2.local_mac,
396 self.pg2.remote_mac,
397 self.pg1.local_ip4,
398 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800399
Neale Ranns30d0fd42017-05-30 07:30:04 -0700400 self.pg2.add_stream(pt)
401 self.pg_enable_capture(self.pg_interfaces)
402 self.pg_start()
403
404 rx = self.pg2.get_capture(1)
405 self.verify_arp_resp(rx[0],
406 self.pg2.local_mac,
407 self.pg2.remote_mac,
408 self.pg1.local_ip4,
409 self.pg2.remote_hosts[3].ip4)
410
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800411 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800412 # A neighbor entry that has no associated FIB-entry
413 #
414 arp_no_fib = VppNeighbor(self,
415 self.pg1.sw_if_index,
416 self.pg1.remote_hosts[4].mac,
417 self.pg1.remote_hosts[4].ip4,
418 is_no_fib_entry=1)
419 arp_no_fib.add_vpp_config()
420
421 #
422 # check we have the neighbor, but no route
423 #
424 self.assertTrue(find_nbr(self,
425 self.pg1.sw_if_index,
426 self.pg1._remote_hosts[4].ip4))
427 self.assertFalse(find_route(self,
428 self.pg1._remote_hosts[4].ip4,
429 32))
430 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800431 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
432 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800433 #
434 arp_unnum = VppNeighbor(self,
435 self.pg2.sw_if_index,
436 self.pg1.remote_hosts[5].mac,
437 self.pg1.remote_hosts[5].ip4)
438 arp_unnum.add_vpp_config()
439
440 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
441 IP(src=self.pg0.remote_ip4,
442 dst=self.pg1._remote_hosts[5].ip4) /
443 UDP(sport=1234, dport=1234) /
444 Raw())
445
446 self.pg0.add_stream(p)
447 self.pg_enable_capture(self.pg_interfaces)
448 self.pg_start()
449
450 rx = self.pg2.get_capture(1)
451
452 self.verify_ip(rx[0],
453 self.pg2.local_mac,
454 self.pg1.remote_hosts[5].mac,
455 self.pg0.remote_ip4,
456 self.pg1._remote_hosts[5].ip4)
457
458 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800459 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
460 # with the unnumbered interface's address as the source
461 #
462 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
463 ARP(op="who-has",
464 hwsrc=self.pg2.remote_mac,
465 pdst=self.pg1.local_ip4,
466 psrc=self.pg1.remote_hosts[6].ip4))
467
468 self.pg2.add_stream(p)
469 self.pg_enable_capture(self.pg_interfaces)
470 self.pg_start()
471
472 rx = self.pg2.get_capture(1)
473 self.verify_arp_resp(rx[0],
474 self.pg2.local_mac,
475 self.pg2.remote_mac,
476 self.pg1.local_ip4,
477 self.pg1.remote_hosts[6].ip4)
478
479 #
480 # An attached host route out of pg2 for an undiscovered hosts generates
481 # an ARP request with the unnumbered address as the source
482 #
483 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
484 [VppRoutePath("0.0.0.0",
485 self.pg2.sw_if_index)])
486 att_unnum.add_vpp_config()
487
488 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
489 IP(src=self.pg0.remote_ip4,
490 dst=self.pg1._remote_hosts[7].ip4) /
491 UDP(sport=1234, dport=1234) /
492 Raw())
493
494 self.pg0.add_stream(p)
495 self.pg_enable_capture(self.pg_interfaces)
496 self.pg_start()
497
498 rx = self.pg2.get_capture(1)
499
500 self.verify_arp_req(rx[0],
501 self.pg2.local_mac,
502 self.pg1.local_ip4,
503 self.pg1._remote_hosts[7].ip4)
504
505 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
506 ARP(op="who-has",
507 hwsrc=self.pg2.remote_mac,
508 pdst=self.pg1.local_ip4,
509 psrc=self.pg1.remote_hosts[7].ip4))
510
511 self.pg2.add_stream(p)
512 self.pg_enable_capture(self.pg_interfaces)
513 self.pg_start()
514
515 rx = self.pg2.get_capture(1)
516 self.verify_arp_resp(rx[0],
517 self.pg2.local_mac,
518 self.pg2.remote_mac,
519 self.pg1.local_ip4,
520 self.pg1.remote_hosts[7].ip4)
521
522 #
523 # An attached host route as yet unresolved out of pg2 for an
524 # undiscovered host, an ARP requests begets a response.
525 #
526 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
527 [VppRoutePath("0.0.0.0",
528 self.pg2.sw_if_index)])
529 att_unnum1.add_vpp_config()
530
531 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
532 ARP(op="who-has",
533 hwsrc=self.pg2.remote_mac,
534 pdst=self.pg1.local_ip4,
535 psrc=self.pg1.remote_hosts[8].ip4))
536
537 self.pg2.add_stream(p)
538 self.pg_enable_capture(self.pg_interfaces)
539 self.pg_start()
540
541 rx = self.pg2.get_capture(1)
542 self.verify_arp_resp(rx[0],
543 self.pg2.local_mac,
544 self.pg2.remote_mac,
545 self.pg1.local_ip4,
546 self.pg1.remote_hosts[8].ip4)
547
548 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700549 # Send an ARP request from one of the so-far unlearned remote hosts
550 # with a VLAN0 tag
551 #
552 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
553 src=self.pg1._remote_hosts[9].mac) /
554 Dot1Q(vlan=0) /
555 ARP(op="who-has",
556 hwsrc=self.pg1._remote_hosts[9].mac,
557 pdst=self.pg1.local_ip4,
558 psrc=self.pg1._remote_hosts[9].ip4))
559
560 self.pg1.add_stream(p)
561 self.pg_enable_capture(self.pg_interfaces)
562 self.pg_start()
563
564 rx = self.pg1.get_capture(1)
565 self.verify_arp_resp(rx[0],
566 self.pg1.local_mac,
567 self.pg1._remote_hosts[9].mac,
568 self.pg1.local_ip4,
569 self.pg1._remote_hosts[9].ip4)
570
571 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700572 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700573 # Should still get an ARP resp since the cover is attached
574 #
575 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
576 ARP(op="who-has",
577 hwsrc=self.pg1.remote_mac,
578 pdst=self.pg1.local_ip4,
579 psrc=self.pg1.remote_hosts[10].ip4))
580
581 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
582 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
583 self.pg1.sw_if_index)])
584 r1.add_vpp_config()
585
586 self.pg1.add_stream(p)
587 self.pg_enable_capture(self.pg_interfaces)
588 self.pg_start()
589 rx = self.pg1.get_capture(1)
590 self.verify_arp_resp(rx[0],
591 self.pg1.local_mac,
592 self.pg1.remote_mac,
593 self.pg1.local_ip4,
594 self.pg1.remote_hosts[10].ip4)
595
596 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
597 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
598 self.pg1.sw_if_index)])
599 r2.add_vpp_config()
600
601 self.pg1.add_stream(p)
602 self.pg_enable_capture(self.pg_interfaces)
603 self.pg_start()
604 rx = self.pg1.get_capture(1)
605 self.verify_arp_resp(rx[0],
606 self.pg1.local_mac,
607 self.pg1.remote_mac,
608 self.pg1.local_ip4,
609 self.pg1.remote_hosts[10].ip4)
610
611 #
612 # add an ARP entry that's not on the sub-net and so whose
613 # adj-fib fails the refinement check. then send an ARP request
614 # from that source
615 #
616 a1 = VppNeighbor(self,
617 self.pg0.sw_if_index,
618 self.pg0.remote_mac,
619 "100.100.100.50")
620 a1.add_vpp_config()
621
622 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
623 ARP(op="who-has",
624 hwsrc=self.pg0.remote_mac,
625 psrc="100.100.100.50",
626 pdst=self.pg0.remote_ip4))
627 self.send_and_assert_no_replies(self.pg0, p,
628 "ARP req for from failed adj-fib")
629
630 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800631 # ERROR Cases
632 # 1 - don't respond to ARP request for address not within the
633 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700634 # 1b - nor within the unnumbered subnet
635 # 1c - nor within the subnet of a different interface
636 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800637 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
638 ARP(op="who-has",
639 hwsrc=self.pg0.remote_mac,
640 pdst="10.10.10.3",
641 psrc=self.pg0.remote_ip4))
642 self.send_and_assert_no_replies(self.pg0, p,
643 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700644 self.assertFalse(find_nbr(self,
645 self.pg0.sw_if_index,
646 "10.10.10.3"))
647
Neale Ranns4b919a52017-03-11 05:55:21 -0800648 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
649 ARP(op="who-has",
650 hwsrc=self.pg2.remote_mac,
651 pdst="10.10.10.3",
652 psrc=self.pg1.remote_hosts[7].ip4))
653 self.send_and_assert_no_replies(
654 self.pg0, p,
655 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800656
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700657 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
658 ARP(op="who-has",
659 hwsrc=self.pg0.remote_mac,
660 pdst=self.pg1.local_ip4,
661 psrc=self.pg1.remote_ip4))
662 self.send_and_assert_no_replies(self.pg0, p,
663 "ARP req diff sub-net")
664 self.assertFalse(find_nbr(self,
665 self.pg0.sw_if_index,
666 self.pg1.remote_ip4))
667
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800668 #
669 # 2 - don't respond to ARP request from an address not within the
670 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700671 # 2b - to a proxied address
672 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800673 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
674 ARP(op="who-has",
675 hwsrc=self.pg0.remote_mac,
676 psrc="10.10.10.3",
677 pdst=self.pg0.local_ip4))
678 self.send_and_assert_no_replies(self.pg0, p,
679 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800680 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
681 ARP(op="who-has",
682 hwsrc=self.pg2.remote_mac,
683 psrc="10.10.10.3",
684 pdst=self.pg0.local_ip4))
685 self.send_and_assert_no_replies(
686 self.pg0, p,
687 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700688 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
689 ARP(op="who-has",
690 hwsrc=self.pg0.remote_mac,
691 psrc=self.pg1.remote_ip4,
692 pdst=self.pg0.local_ip4))
693 self.send_and_assert_no_replies(self.pg0, p,
694 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800695
696 #
697 # 3 - don't respond to ARP request from an address that belongs to
698 # the router
699 #
700 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
701 ARP(op="who-has",
702 hwsrc=self.pg0.remote_mac,
703 psrc=self.pg0.local_ip4,
704 pdst=self.pg0.local_ip4))
705 self.send_and_assert_no_replies(self.pg0, p,
706 "ARP req for non-local source")
707
708 #
709 # 4 - don't respond to ARP requests that has mac source different
710 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800711 #
712 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
713 ARP(op="who-has",
714 hwsrc="00:00:00:DE:AD:BE",
715 psrc=self.pg0.remote_ip4,
716 pdst=self.pg0.local_ip4))
717 self.send_and_assert_no_replies(self.pg0, p,
718 "ARP req for non-local source")
719
720 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800721 # 5 - don't respond to ARP requests for address within the
722 # interface's sub-net but not the interface's address
723 #
724 self.pg0.generate_remote_hosts(2)
725 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
726 ARP(op="who-has",
727 hwsrc=self.pg0.remote_mac,
728 psrc=self.pg0.remote_hosts[0].ip4,
729 pdst=self.pg0.remote_hosts[1].ip4))
730 self.send_and_assert_no_replies(self.pg0, p,
731 "ARP req for non-local destination")
732
733 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800734 # cleanup
735 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800736 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800737 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800738
Neale Ranns4b919a52017-03-11 05:55:21 -0800739 # need this to flush the adj-fibs
740 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
741 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700742 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800743
Neale Ranns24b170a2017-08-15 05:33:11 -0700744 def test_proxy_mirror_arp(self):
745 """ Interface Mirror Proxy ARP """
746
747 #
748 # When VPP has an interface whose address is also applied to a TAP
749 # interface on the host, then VPP's TAP interface will be unnumbered
750 # to the 'real' interface and do proxy ARP from the host.
751 # the curious aspect of this setup is that ARP requests from the host
752 # will come from the VPP's own address.
753 #
754 self.pg0.generate_remote_hosts(2)
755
756 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
757 dst="ff:ff:ff:ff:ff:ff") /
758 ARP(op="who-has",
759 hwsrc=self.pg2.remote_mac,
760 pdst=self.pg0.remote_hosts[1].ip4,
761 psrc=self.pg0.local_ip4))
762
763 #
764 # Configure Proxy ARP for the subnet on PG0addresses on pg0
765 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100766 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
767 'low': self.pg0._local_ip4_subnet,
768 'hi': self.pg0._local_ip4_bcast},
769 is_add=1)
Neale Ranns24b170a2017-08-15 05:33:11 -0700770
771 # Make pg2 un-numbered to pg0
772 #
773 self.pg2.set_unnumbered(self.pg0.sw_if_index)
774
775 #
776 # Enable pg2 for proxy ARP
777 #
778 self.pg2.set_proxy_arp()
779
780 #
781 # Send the ARP request with an originating address that
782 # is VPP's own address
783 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000784 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Neale Ranns24b170a2017-08-15 05:33:11 -0700785 self.verify_arp_resp(rx[0],
786 self.pg2.local_mac,
787 self.pg2.remote_mac,
788 self.pg0.remote_hosts[1].ip4,
789 self.pg0.local_ip4)
790
791 #
792 # validate we have not learned an ARP entry as a result of this
793 #
794 self.assertFalse(find_nbr(self,
795 self.pg2.sw_if_index,
796 self.pg0.local_ip4))
797
798 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000799 # setup a punt redirect so packets from the uplink go to the tap
800 #
801 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
802 self.pg2.sw_if_index,
803 self.pg0.local_ip4)
804
805 p_tcp = (Ether(src=self.pg0.remote_mac,
806 dst=self.pg0.local_mac,) /
807 IP(src=self.pg0.remote_ip4,
808 dst=self.pg0.local_ip4) /
809 TCP(sport=80, dport=80) /
810 Raw())
811 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
812
813 # there's no ARP entry so this is an ARP req
814 self.assertTrue(rx[0].haslayer(ARP))
815
816 # and ARP entry for VPP's pg0 address on the host interface
817 n1 = VppNeighbor(self,
818 self.pg2.sw_if_index,
819 self.pg2.remote_mac,
820 self.pg0.local_ip4,
821 is_no_fib_entry=True).add_vpp_config()
822 # now the packets shold forward
823 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
824 self.assertFalse(rx[0].haslayer(ARP))
825 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
826
827 #
828 # flush the neighbor cache on the uplink
829 #
830 af = VppEnum.vl_api_address_family_t
831 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
832
833 # ensure we can still resolve the ARPs on the uplink
834 self.pg0.resolve_arp()
835
836 self.assertTrue(find_nbr(self,
837 self.pg0.sw_if_index,
838 self.pg0.remote_ip4))
839
840 #
Neale Ranns24b170a2017-08-15 05:33:11 -0700841 # cleanup
842 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100843 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
844 'low': self.pg0._local_ip4_subnet,
845 'hi': self.pg0._local_ip4_bcast},
Neale Ranns24b170a2017-08-15 05:33:11 -0700846 is_add=0)
847
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800848 def test_proxy_arp(self):
849 """ Proxy ARP """
850
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700851 self.pg1.generate_remote_hosts(2)
852
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800853 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700854 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800855 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800856 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
857 dst="ff:ff:ff:ff:ff:ff") /
858 ARP(op="who-has",
859 hwsrc=self.pg0.remote_mac,
860 pdst="10.10.10.3",
861 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700862 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
863 dst="ff:ff:ff:ff:ff:ff") /
864 Dot1Q(vlan=0) /
865 ARP(op="who-has",
866 hwsrc=self.pg0.remote_mac,
867 pdst="10.10.10.3",
868 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800869 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
870 dst="ff:ff:ff:ff:ff:ff") /
871 ARP(op="who-has",
872 hwsrc=self.pg1.remote_mac,
873 pdst="10.10.10.3",
874 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700875 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
876 dst="ff:ff:ff:ff:ff:ff") /
877 ARP(op="who-has",
878 hwsrc=self.pg2.remote_mac,
879 pdst="10.10.10.3",
880 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800881 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
882 dst="ff:ff:ff:ff:ff:ff") /
883 ARP(op="who-has",
884 hwsrc=self.pg3.remote_mac,
885 pdst="10.10.10.3",
886 psrc=self.pg3.remote_ip4))
887
888 #
889 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
890 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100891 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
892 'low': "10.10.10.2",
893 'hi': "10.10.10.124"},
894 is_add=1)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800895
896 #
897 # No responses are sent when the interfaces are not enabled for proxy
898 # ARP
899 #
900 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
901 "ARP req from unconfigured interface")
902 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
903 "ARP req from unconfigured interface")
904
905 #
906 # Make pg2 un-numbered to pg1
907 # still won't reply.
908 #
909 self.pg2.set_unnumbered(self.pg1.sw_if_index)
910
911 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
912 "ARP req from unnumbered interface")
913
914 #
915 # Enable each interface to reply to proxy ARPs
916 #
917 for i in self.pg_interfaces:
918 i.set_proxy_arp()
919
920 #
921 # Now each of the interfaces should reply to a request to a proxied
922 # address
923 #
924 self.pg0.add_stream(arp_req_pg0)
925 self.pg_enable_capture(self.pg_interfaces)
926 self.pg_start()
927
928 rx = self.pg0.get_capture(1)
929 self.verify_arp_resp(rx[0],
930 self.pg0.local_mac,
931 self.pg0.remote_mac,
932 "10.10.10.3",
933 self.pg0.remote_ip4)
934
Neale Ranns30d0fd42017-05-30 07:30:04 -0700935 self.pg0.add_stream(arp_req_pg0_tagged)
936 self.pg_enable_capture(self.pg_interfaces)
937 self.pg_start()
938
939 rx = self.pg0.get_capture(1)
940 self.verify_arp_resp(rx[0],
941 self.pg0.local_mac,
942 self.pg0.remote_mac,
943 "10.10.10.3",
944 self.pg0.remote_ip4)
945
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800946 self.pg1.add_stream(arp_req_pg1)
947 self.pg_enable_capture(self.pg_interfaces)
948 self.pg_start()
949
950 rx = self.pg1.get_capture(1)
951 self.verify_arp_resp(rx[0],
952 self.pg1.local_mac,
953 self.pg1.remote_mac,
954 "10.10.10.3",
955 self.pg1.remote_ip4)
956
957 self.pg2.add_stream(arp_req_pg2)
958 self.pg_enable_capture(self.pg_interfaces)
959 self.pg_start()
960
961 rx = self.pg2.get_capture(1)
962 self.verify_arp_resp(rx[0],
963 self.pg2.local_mac,
964 self.pg2.remote_mac,
965 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700966 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800967
968 #
969 # A request for an address out of the configured range
970 #
971 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
972 dst="ff:ff:ff:ff:ff:ff") /
973 ARP(op="who-has",
974 hwsrc=self.pg1.remote_mac,
975 pdst="10.10.10.125",
976 psrc=self.pg1.remote_ip4))
977 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
978 "ARP req out of range HI")
979 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
980 dst="ff:ff:ff:ff:ff:ff") /
981 ARP(op="who-has",
982 hwsrc=self.pg1.remote_mac,
983 pdst="10.10.10.1",
984 psrc=self.pg1.remote_ip4))
985 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
986 "ARP req out of range Low")
987
988 #
989 # Request for an address in the proxy range but from an interface
990 # in a different VRF
991 #
992 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
993 "ARP req from different VRF")
994
995 #
996 # Disable Each interface for proxy ARP
997 # - expect none to respond
998 #
999 for i in self.pg_interfaces:
1000 i.set_proxy_arp(0)
1001
1002 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
1003 "ARP req from disable")
1004 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
1005 "ARP req from disable")
1006 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
1007 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001008
1009 #
1010 # clean up on interface 2
1011 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001012 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001013
1014 def test_mpls(self):
1015 """ MPLS """
1016
1017 #
1018 # Interface 2 does not yet have ip4 config
1019 #
1020 self.pg2.config_ip4()
1021 self.pg2.generate_remote_hosts(2)
1022
1023 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001024 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001025 #
1026 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1027 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
1028 self.pg2.sw_if_index,
1029 labels=[55])])
1030 ip_10_0_0_1.add_vpp_config()
1031
1032 #
1033 # packets should generate an ARP request
1034 #
1035 p = (Ether(src=self.pg0.remote_mac,
1036 dst=self.pg0.local_mac) /
1037 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
1038 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001039 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -08001040
1041 self.pg0.add_stream(p)
1042 self.pg_enable_capture(self.pg_interfaces)
1043 self.pg_start()
1044
1045 rx = self.pg2.get_capture(1)
1046 self.verify_arp_req(rx[0],
1047 self.pg2.local_mac,
1048 self.pg2.local_ip4,
1049 self.pg2._remote_hosts[1].ip4)
1050
1051 #
1052 # now resolve the neighbours
1053 #
1054 self.pg2.configure_ipv4_neighbors()
1055
1056 #
1057 # Now packet should be properly MPLS encapped.
1058 # This verifies that MPLS link-type adjacencies are completed
1059 # when the ARP entry resolves
1060 #
1061 self.pg0.add_stream(p)
1062 self.pg_enable_capture(self.pg_interfaces)
1063 self.pg_start()
1064
1065 rx = self.pg2.get_capture(1)
1066 self.verify_ip_o_mpls(rx[0],
1067 self.pg2.local_mac,
1068 self.pg2.remote_hosts[1].mac,
1069 55,
1070 self.pg0.remote_ip4,
1071 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -08001072 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001073
Matthew Smithcb9ab472017-05-16 21:35:56 -05001074 def test_arp_vrrp(self):
1075 """ ARP reply with VRRP virtual src hw addr """
1076
1077 #
1078 # IP packet destined for pg1 remote host arrives on pg0 resulting
1079 # in an ARP request for the address of the remote host on pg1
1080 #
1081 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1082 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1083 UDP(sport=1234, dport=1234) /
1084 Raw())
1085
Neale Ranns37029302018-08-10 05:30:06 -07001086 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001087
1088 self.verify_arp_req(rx1[0],
1089 self.pg1.local_mac,
1090 self.pg1.local_ip4,
1091 self.pg1.remote_ip4)
1092
1093 #
1094 # ARP reply for address of pg1 remote host arrives on pg1 with
1095 # the hw src addr set to a value in the VRRP IPv4 range of
1096 # MAC addresses
1097 #
1098 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1099 ARP(op="is-at", hwdst=self.pg1.local_mac,
1100 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1101 psrc=self.pg1.remote_ip4))
1102
Neale Ranns37029302018-08-10 05:30:06 -07001103 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001104
1105 #
1106 # IP packet destined for pg1 remote host arrives on pg0 again.
1107 # VPP should have an ARP entry for that address now and the packet
1108 # should be sent out pg1.
1109 #
Neale Ranns37029302018-08-10 05:30:06 -07001110 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001111
1112 self.verify_ip(rx1[0],
1113 self.pg1.local_mac,
1114 "00:00:5e:00:01:09",
1115 self.pg0.remote_ip4,
1116 self.pg1.remote_ip4)
1117
1118 self.pg1.admin_down()
1119 self.pg1.admin_up()
1120
Neale Rannsdcd6d622017-05-26 02:59:16 -07001121 def test_arp_duplicates(self):
1122 """ ARP Duplicates"""
1123
1124 #
1125 # Generate some hosts on the LAN
1126 #
1127 self.pg1.generate_remote_hosts(3)
1128
1129 #
1130 # Add host 1 on pg1 and pg2
1131 #
1132 arp_pg1 = VppNeighbor(self,
1133 self.pg1.sw_if_index,
1134 self.pg1.remote_hosts[1].mac,
1135 self.pg1.remote_hosts[1].ip4)
1136 arp_pg1.add_vpp_config()
1137 arp_pg2 = VppNeighbor(self,
1138 self.pg2.sw_if_index,
1139 self.pg2.remote_mac,
1140 self.pg1.remote_hosts[1].ip4)
1141 arp_pg2.add_vpp_config()
1142
1143 #
1144 # IP packet destined for pg1 remote host arrives on pg1 again.
1145 #
1146 p = (Ether(dst=self.pg0.local_mac,
1147 src=self.pg0.remote_mac) /
1148 IP(src=self.pg0.remote_ip4,
1149 dst=self.pg1.remote_hosts[1].ip4) /
1150 UDP(sport=1234, dport=1234) /
1151 Raw())
1152
1153 self.pg0.add_stream(p)
1154 self.pg_enable_capture(self.pg_interfaces)
1155 self.pg_start()
1156
1157 rx1 = self.pg1.get_capture(1)
1158
1159 self.verify_ip(rx1[0],
1160 self.pg1.local_mac,
1161 self.pg1.remote_hosts[1].mac,
1162 self.pg0.remote_ip4,
1163 self.pg1.remote_hosts[1].ip4)
1164
1165 #
1166 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001167 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001168 #
1169 arp_pg1.remove_vpp_config()
1170
1171 self.pg0.add_stream(p)
1172 self.pg_enable_capture(self.pg_interfaces)
1173 self.pg_start()
1174
1175 rx1 = self.pg1.get_capture(1)
1176
1177 self.verify_arp_req(rx1[0],
1178 self.pg1.local_mac,
1179 self.pg1.local_ip4,
1180 self.pg1.remote_hosts[1].ip4)
1181
1182 #
1183 # Add it back
1184 #
1185 arp_pg1.add_vpp_config()
1186
1187 self.pg0.add_stream(p)
1188 self.pg_enable_capture(self.pg_interfaces)
1189 self.pg_start()
1190
1191 rx1 = self.pg1.get_capture(1)
1192
1193 self.verify_ip(rx1[0],
1194 self.pg1.local_mac,
1195 self.pg1.remote_hosts[1].mac,
1196 self.pg0.remote_ip4,
1197 self.pg1.remote_hosts[1].ip4)
1198
Neale Ranns15002542017-09-10 04:39:11 -07001199 def test_arp_static(self):
1200 """ ARP Static"""
1201 self.pg2.generate_remote_hosts(3)
1202
1203 #
1204 # Add a static ARP entry
1205 #
1206 static_arp = VppNeighbor(self,
1207 self.pg2.sw_if_index,
1208 self.pg2.remote_hosts[1].mac,
1209 self.pg2.remote_hosts[1].ip4,
1210 is_static=1)
1211 static_arp.add_vpp_config()
1212
1213 #
1214 # Add the connected prefix to the interface
1215 #
1216 self.pg2.config_ip4()
1217
1218 #
1219 # We should now find the adj-fib
1220 #
1221 self.assertTrue(find_nbr(self,
1222 self.pg2.sw_if_index,
1223 self.pg2.remote_hosts[1].ip4,
1224 is_static=1))
1225 self.assertTrue(find_route(self,
1226 self.pg2.remote_hosts[1].ip4,
1227 32))
1228
1229 #
1230 # remove the connected
1231 #
1232 self.pg2.unconfig_ip4()
1233
1234 #
1235 # put the interface into table 1
1236 #
1237 self.pg2.set_table_ip4(1)
1238
1239 #
1240 # configure the same connected and expect to find the
1241 # adj fib in the new table
1242 #
1243 self.pg2.config_ip4()
1244 self.assertTrue(find_route(self,
1245 self.pg2.remote_hosts[1].ip4,
1246 32,
1247 table_id=1))
1248
1249 #
1250 # clean-up
1251 #
1252 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001253 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001254 self.pg2.set_table_ip4(0)
1255
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001256 def test_arp_static_replace_dynamic_same_mac(self):
1257 """ ARP Static can replace Dynamic (same mac) """
1258 self.pg2.generate_remote_hosts(1)
1259
1260 dyn_arp = VppNeighbor(self,
1261 self.pg2.sw_if_index,
1262 self.pg2.remote_hosts[0].mac,
1263 self.pg2.remote_hosts[0].ip4)
1264 static_arp = VppNeighbor(self,
1265 self.pg2.sw_if_index,
1266 self.pg2.remote_hosts[0].mac,
1267 self.pg2.remote_hosts[0].ip4,
1268 is_static=1)
1269
1270 #
1271 # Add a dynamic ARP entry
1272 #
1273 dyn_arp.add_vpp_config()
1274
1275 #
1276 # We should find the dynamic nbr
1277 #
1278 self.assertFalse(find_nbr(self,
1279 self.pg2.sw_if_index,
1280 self.pg2.remote_hosts[0].ip4,
1281 is_static=1))
1282 self.assertTrue(find_nbr(self,
1283 self.pg2.sw_if_index,
1284 self.pg2.remote_hosts[0].ip4,
1285 is_static=0,
1286 mac=self.pg2.remote_hosts[0].mac))
1287
1288 #
1289 # Add a static ARP entry with the same mac
1290 #
1291 static_arp.add_vpp_config()
1292
1293 #
1294 # We should now find the static nbr with the same mac
1295 #
1296 self.assertFalse(find_nbr(self,
1297 self.pg2.sw_if_index,
1298 self.pg2.remote_hosts[0].ip4,
1299 is_static=0))
1300 self.assertTrue(find_nbr(self,
1301 self.pg2.sw_if_index,
1302 self.pg2.remote_hosts[0].ip4,
1303 is_static=1,
1304 mac=self.pg2.remote_hosts[0].mac))
1305
1306 #
1307 # clean-up
1308 #
1309 static_arp.remove_vpp_config()
1310
1311 def test_arp_static_replace_dynamic_diff_mac(self):
1312 """ ARP Static can replace Dynamic (diff mac) """
1313 self.pg2.generate_remote_hosts(2)
1314
1315 dyn_arp = VppNeighbor(self,
1316 self.pg2.sw_if_index,
1317 self.pg2.remote_hosts[0].mac,
1318 self.pg2.remote_hosts[0].ip4)
1319 static_arp = VppNeighbor(self,
1320 self.pg2.sw_if_index,
1321 self.pg2.remote_hosts[1].mac,
1322 self.pg2.remote_hosts[0].ip4,
1323 is_static=1)
1324
1325 #
1326 # Add a dynamic ARP entry
1327 #
1328 dyn_arp.add_vpp_config()
1329
1330 #
1331 # We should find the dynamic nbr
1332 #
1333 self.assertFalse(find_nbr(self,
1334 self.pg2.sw_if_index,
1335 self.pg2.remote_hosts[0].ip4,
1336 is_static=1))
1337 self.assertTrue(find_nbr(self,
1338 self.pg2.sw_if_index,
1339 self.pg2.remote_hosts[0].ip4,
1340 is_static=0,
1341 mac=self.pg2.remote_hosts[0].mac))
1342
1343 #
1344 # Add a static ARP entry with a changed mac
1345 #
1346 static_arp.add_vpp_config()
1347
1348 #
1349 # We should now find the static nbr with a changed mac
1350 #
1351 self.assertFalse(find_nbr(self,
1352 self.pg2.sw_if_index,
1353 self.pg2.remote_hosts[0].ip4,
1354 is_static=0))
1355 self.assertTrue(find_nbr(self,
1356 self.pg2.sw_if_index,
1357 self.pg2.remote_hosts[0].ip4,
1358 is_static=1,
1359 mac=self.pg2.remote_hosts[1].mac))
1360
1361 #
1362 # clean-up
1363 #
1364 static_arp.remove_vpp_config()
1365
Neale Rannsc819fc62018-02-16 02:44:05 -08001366 def test_arp_incomplete(self):
1367 """ ARP Incomplete"""
1368 self.pg1.generate_remote_hosts(3)
1369
1370 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1371 IP(src=self.pg0.remote_ip4,
1372 dst=self.pg1.remote_hosts[1].ip4) /
1373 UDP(sport=1234, dport=1234) /
1374 Raw())
1375 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1376 IP(src=self.pg0.remote_ip4,
1377 dst=self.pg1.remote_hosts[2].ip4) /
1378 UDP(sport=1234, dport=1234) /
1379 Raw())
1380
1381 #
1382 # a packet to an unresolved destination generates an ARP request
1383 #
1384 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1385 self.verify_arp_req(rx[0],
1386 self.pg1.local_mac,
1387 self.pg1.local_ip4,
1388 self.pg1._remote_hosts[1].ip4)
1389
1390 #
1391 # add a neighbour for remote host 1
1392 #
1393 static_arp = VppNeighbor(self,
1394 self.pg1.sw_if_index,
1395 self.pg1.remote_hosts[1].mac,
1396 self.pg1.remote_hosts[1].ip4,
1397 is_static=1)
1398 static_arp.add_vpp_config()
1399
1400 #
1401 # change the interface's MAC
1402 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001403 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001404 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001405
1406 #
1407 # now ARP requests come from the new source mac
1408 #
1409 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1410 self.verify_arp_req(rx[0],
1411 "00:00:00:33:33:33",
1412 self.pg1.local_ip4,
1413 self.pg1._remote_hosts[2].ip4)
1414
1415 #
1416 # packets to the resolved host also have the new source mac
1417 #
1418 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1419 self.verify_ip(rx[0],
1420 "00:00:00:33:33:33",
1421 self.pg1.remote_hosts[1].mac,
1422 self.pg0.remote_ip4,
1423 self.pg1.remote_hosts[1].ip4)
1424
1425 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001426 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001427 # configured subnet and thus no glean
1428 #
1429 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001430 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001431
Neale Ranns59ae61e2018-06-07 18:09:49 -07001432 def test_garp(self):
1433 """ GARP """
1434
1435 #
1436 # Generate some hosts on the LAN
1437 #
1438 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001439 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001440
1441 #
1442 # And an ARP entry
1443 #
1444 arp = VppNeighbor(self,
1445 self.pg1.sw_if_index,
1446 self.pg1.remote_hosts[1].mac,
1447 self.pg1.remote_hosts[1].ip4)
1448 arp.add_vpp_config()
1449
1450 self.assertTrue(find_nbr(self,
1451 self.pg1.sw_if_index,
1452 self.pg1.remote_hosts[1].ip4,
1453 mac=self.pg1.remote_hosts[1].mac))
1454
1455 #
1456 # Send a GARP (request) to swap the host 1's address to that of host 2
1457 #
1458 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1459 src=self.pg1.remote_hosts[2].mac) /
1460 ARP(op="who-has",
1461 hwdst=self.pg1.local_mac,
1462 hwsrc=self.pg1.remote_hosts[2].mac,
1463 pdst=self.pg1.remote_hosts[1].ip4,
1464 psrc=self.pg1.remote_hosts[1].ip4))
1465
1466 self.pg1.add_stream(p1)
1467 self.pg_enable_capture(self.pg_interfaces)
1468 self.pg_start()
1469
1470 self.assertTrue(find_nbr(self,
1471 self.pg1.sw_if_index,
1472 self.pg1.remote_hosts[1].ip4,
1473 mac=self.pg1.remote_hosts[2].mac))
1474
1475 #
1476 # Send a GARP (reply) to swap the host 1's address to that of host 3
1477 #
1478 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1479 src=self.pg1.remote_hosts[3].mac) /
1480 ARP(op="is-at",
1481 hwdst=self.pg1.local_mac,
1482 hwsrc=self.pg1.remote_hosts[3].mac,
1483 pdst=self.pg1.remote_hosts[1].ip4,
1484 psrc=self.pg1.remote_hosts[1].ip4))
1485
1486 self.pg1.add_stream(p1)
1487 self.pg_enable_capture(self.pg_interfaces)
1488 self.pg_start()
1489
1490 self.assertTrue(find_nbr(self,
1491 self.pg1.sw_if_index,
1492 self.pg1.remote_hosts[1].ip4,
1493 mac=self.pg1.remote_hosts[3].mac))
1494
1495 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001496 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001497 # don't result in new neighbour entries
1498 #
1499 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1500 src=self.pg1.remote_hosts[3].mac) /
1501 ARP(op="who-has",
1502 hwdst=self.pg1.local_mac,
1503 hwsrc=self.pg1.remote_hosts[3].mac,
1504 pdst=self.pg1.remote_hosts[2].ip4,
1505 psrc=self.pg1.remote_hosts[2].ip4))
1506
1507 self.pg1.add_stream(p1)
1508 self.pg_enable_capture(self.pg_interfaces)
1509 self.pg_start()
1510
1511 self.assertFalse(find_nbr(self,
1512 self.pg1.sw_if_index,
1513 self.pg1.remote_hosts[2].ip4))
1514
1515 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1516 src=self.pg1.remote_hosts[3].mac) /
1517 ARP(op="is-at",
1518 hwdst=self.pg1.local_mac,
1519 hwsrc=self.pg1.remote_hosts[3].mac,
1520 pdst=self.pg1.remote_hosts[2].ip4,
1521 psrc=self.pg1.remote_hosts[2].ip4))
1522
1523 self.pg1.add_stream(p1)
1524 self.pg_enable_capture(self.pg_interfaces)
1525 self.pg_start()
1526
1527 self.assertFalse(find_nbr(self,
1528 self.pg1.sw_if_index,
1529 self.pg1.remote_hosts[2].ip4))
1530
Neale Ranns22eefd72020-09-23 11:25:21 +00001531 #
1532 # IP address in different subnets are not learnt
1533 #
1534 self.pg2.configure_ipv4_neighbors()
1535
1536 for op in ["is-at", "who-has"]:
1537 p1 = [(Ether(dst="ff:ff:ff:ff:ff:ff",
1538 src=self.pg2.remote_hosts[1].mac) /
1539 ARP(op=op,
1540 hwdst=self.pg2.local_mac,
1541 hwsrc=self.pg2.remote_hosts[1].mac,
1542 pdst=self.pg2.remote_hosts[1].ip4,
1543 psrc=self.pg2.remote_hosts[1].ip4)),
1544 (Ether(dst="ff:ff:ff:ff:ff:ff",
1545 src=self.pg2.remote_hosts[1].mac) /
1546 ARP(op=op,
1547 hwdst="ff:ff:ff:ff:ff:ff",
1548 hwsrc=self.pg2.remote_hosts[1].mac,
1549 pdst=self.pg2.remote_hosts[1].ip4,
1550 psrc=self.pg2.remote_hosts[1].ip4))]
1551
1552 self.send_and_assert_no_replies(self.pg1, p1)
1553 self.assertFalse(find_nbr(self,
1554 self.pg1.sw_if_index,
1555 self.pg2.remote_hosts[1].ip4))
1556
1557 # they are all dropped because the subnet's don't match
1558 self.assertEqual(4, self.statistics.get_err_counter(
1559 "/err/arp-reply/IP4 destination address not local to subnet"))
1560
Neale Ranns77f91622020-11-23 16:25:27 +00001561 def test_arp_incomplete2(self):
Neale Ranns14260392018-09-28 05:00:57 -07001562 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001563
1564 #
Neale Rannscd35e532018-08-31 02:51:45 -07001565 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001566 #
1567 self.pg0.generate_remote_hosts(2)
1568
Neale Rannscd35e532018-08-31 02:51:45 -07001569 #
1570 # IPv4/ARP
1571 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001572 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1573 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001574 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001575 ip_10_0_0_1.add_vpp_config()
1576
1577 p1 = (Ether(dst=self.pg1.local_mac,
1578 src=self.pg1.remote_mac) /
1579 IP(src=self.pg1.remote_ip4,
1580 dst="10.0.0.1") /
1581 UDP(sport=1234, dport=1234) /
1582 Raw())
1583
1584 self.pg1.add_stream(p1 * 257)
1585 self.pg_enable_capture(self.pg_interfaces)
1586 self.pg_start()
1587 rx = self.pg0._get_capture(1)
1588
1589 #
1590 # how many we get is going to be dependent on the time for packet
1591 # processing but it should be small
1592 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001593 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001594
Neale Rannscd35e532018-08-31 02:51:45 -07001595 #
1596 # IPv6/ND
1597 #
1598 ip_10_1 = VppIpRoute(self, "10::1", 128,
1599 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1600 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001601 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001602 ip_10_1.add_vpp_config()
1603
1604 p1 = (Ether(dst=self.pg1.local_mac,
1605 src=self.pg1.remote_mac) /
1606 IPv6(src=self.pg1.remote_ip6,
1607 dst="10::1") /
1608 UDP(sport=1234, dport=1234) /
1609 Raw())
1610
1611 self.pg1.add_stream(p1 * 257)
1612 self.pg_enable_capture(self.pg_interfaces)
1613 self.pg_start()
1614 rx = self.pg0._get_capture(1)
1615
1616 #
1617 # how many we get is going to be dependent on the time for packet
1618 # processing but it should be small
1619 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001620 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001621
Neale Ranns7425f922019-01-23 00:36:16 -08001622 def test_arp_forus(self):
1623 """ ARP for for-us """
1624
1625 #
1626 # Test that VPP responds with ARP requests to addresses that
1627 # are connected and local routes.
1628 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001629 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001630 # address added to an interface
1631 #
1632 self.pg0.generate_remote_hosts(2)
1633
Neale Ranns097fa662018-05-01 05:17:55 -07001634 forus = VppIpRoute(
1635 self, self.pg0.remote_hosts[1].ip4, 32,
1636 [VppRoutePath("0.0.0.0",
1637 self.pg0.sw_if_index,
1638 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001639 forus.add_vpp_config()
1640
1641 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1642 src=self.pg0.remote_mac) /
1643 ARP(op="who-has",
1644 hwdst=self.pg0.local_mac,
1645 hwsrc=self.pg0.remote_mac,
1646 pdst=self.pg0.remote_hosts[1].ip4,
1647 psrc=self.pg0.remote_ip4))
1648
1649 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1650
1651 self.verify_arp_resp(rx[0],
1652 self.pg0.local_mac,
1653 self.pg0.remote_mac,
1654 self.pg0.remote_hosts[1].ip4,
1655 self.pg0.remote_ip4)
1656
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001657 def test_arp_table_swap(self):
1658 #
1659 # Generate some hosts on the LAN
1660 #
1661 N_NBRS = 4
1662 self.pg1.generate_remote_hosts(N_NBRS)
1663
1664 for n in range(N_NBRS):
1665 # a route thru each neighbour
1666 VppIpRoute(self, "10.0.0.%d" % n, 32,
1667 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1668 self.pg1.sw_if_index)]).add_vpp_config()
1669
1670 # resolve each neighbour
1671 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1672 ARP(op="is-at", hwdst=self.pg1.local_mac,
1673 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1674 psrc=self.pg1.remote_hosts[n].ip4))
1675
1676 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1677
1678 self.logger.info(self.vapi.cli("sh ip neighbors"))
1679
1680 #
1681 # swap the table pg1 is in
1682 #
1683 table = VppIpTable(self, 100).add_vpp_config()
1684
1685 self.pg1.unconfig_ip4()
1686 self.pg1.set_table_ip4(100)
1687 self.pg1.config_ip4()
1688
1689 #
1690 # all neighbours are cleared
1691 #
1692 for n in range(N_NBRS):
1693 self.assertFalse(find_nbr(self,
1694 self.pg1.sw_if_index,
1695 self.pg1.remote_hosts[n].ip4))
1696
1697 #
1698 # packets to all neighbours generate ARP requests
1699 #
1700 for n in range(N_NBRS):
1701 # a route thru each neighbour
1702 VppIpRoute(self, "10.0.0.%d" % n, 32,
1703 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1704 self.pg1.sw_if_index)],
1705 table_id=100).add_vpp_config()
1706
1707 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1708 dst=self.pg1.local_mac) /
1709 IP(src=self.pg1.remote_hosts[n].ip4,
1710 dst="10.0.0.%d" % n) /
1711 Raw(b'0x5' * 100))
1712 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1713 for rx in rxs:
1714 self.verify_arp_req(rx,
1715 self.pg1.local_mac,
1716 self.pg1.local_ip4,
1717 self.pg1.remote_hosts[n].ip4)
1718
1719 self.pg1.unconfig_ip4()
1720 self.pg1.set_table_ip4(0)
1721
Neale Rannsdcd6d622017-05-26 02:59:16 -07001722
Neale Ranns14260392018-09-28 05:00:57 -07001723class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001724 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001725
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001726 @classmethod
1727 def setUpClass(cls):
1728 super(NeighborStatsTestCase, cls).setUpClass()
1729
1730 @classmethod
1731 def tearDownClass(cls):
1732 super(NeighborStatsTestCase, cls).tearDownClass()
1733
Neale Ranns14260392018-09-28 05:00:57 -07001734 def setUp(self):
1735 super(NeighborStatsTestCase, self).setUp()
1736
1737 self.create_pg_interfaces(range(2))
1738
1739 # pg0 configured with ip4 and 6 addresses used for input
1740 # pg1 configured with ip4 and 6 addresses used for output
1741 # pg2 is unnumbered to pg0
1742 for i in self.pg_interfaces:
1743 i.admin_up()
1744 i.config_ip4()
1745 i.config_ip6()
1746 i.resolve_arp()
1747 i.resolve_ndp()
1748
1749 def tearDown(self):
1750 super(NeighborStatsTestCase, self).tearDown()
1751
1752 for i in self.pg_interfaces:
1753 i.unconfig_ip4()
1754 i.unconfig_ip6()
1755 i.admin_down()
1756
1757 def test_arp_stats(self):
1758 """ ARP Counters """
1759
1760 self.vapi.cli("adj counters enable")
1761 self.pg1.generate_remote_hosts(2)
1762
1763 arp1 = VppNeighbor(self,
1764 self.pg1.sw_if_index,
1765 self.pg1.remote_hosts[0].mac,
1766 self.pg1.remote_hosts[0].ip4)
1767 arp1.add_vpp_config()
1768 arp2 = VppNeighbor(self,
1769 self.pg1.sw_if_index,
1770 self.pg1.remote_hosts[1].mac,
1771 self.pg1.remote_hosts[1].ip4)
1772 arp2.add_vpp_config()
1773
1774 p1 = (Ether(dst=self.pg0.local_mac,
1775 src=self.pg0.remote_mac) /
1776 IP(src=self.pg0.remote_ip4,
1777 dst=self.pg1.remote_hosts[0].ip4) /
1778 UDP(sport=1234, dport=1234) /
1779 Raw())
1780 p2 = (Ether(dst=self.pg0.local_mac,
1781 src=self.pg0.remote_mac) /
1782 IP(src=self.pg0.remote_ip4,
1783 dst=self.pg1.remote_hosts[1].ip4) /
1784 UDP(sport=1234, dport=1234) /
1785 Raw())
1786
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001787 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1788 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001789
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001790 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1791 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001792
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001793 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1794 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001795
1796 def test_nd_stats(self):
1797 """ ND Counters """
1798
1799 self.vapi.cli("adj counters enable")
1800 self.pg0.generate_remote_hosts(3)
1801
1802 nd1 = VppNeighbor(self,
1803 self.pg0.sw_if_index,
1804 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001805 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001806 nd1.add_vpp_config()
1807 nd2 = VppNeighbor(self,
1808 self.pg0.sw_if_index,
1809 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001810 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001811 nd2.add_vpp_config()
1812
1813 p1 = (Ether(dst=self.pg1.local_mac,
1814 src=self.pg1.remote_mac) /
1815 IPv6(src=self.pg1.remote_ip6,
1816 dst=self.pg0.remote_hosts[1].ip6) /
1817 UDP(sport=1234, dport=1234) /
1818 Raw())
1819 p2 = (Ether(dst=self.pg1.local_mac,
1820 src=self.pg1.remote_mac) /
1821 IPv6(src=self.pg1.remote_ip6,
1822 dst=self.pg0.remote_hosts[2].ip6) /
1823 UDP(sport=1234, dport=1234) /
1824 Raw())
1825
1826 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1827 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1828
1829 self.assertEqual(16, nd1.get_stats()['packets'])
1830 self.assertEqual(16, nd2.get_stats()['packets'])
1831
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001832 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1833 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001834
1835
Neale Rannscbe25aa2019-09-30 10:53:31 +00001836class NeighborAgeTestCase(VppTestCase):
1837 """ ARP/ND Aging """
1838
1839 @classmethod
1840 def setUpClass(cls):
1841 super(NeighborAgeTestCase, cls).setUpClass()
1842
1843 @classmethod
1844 def tearDownClass(cls):
1845 super(NeighborAgeTestCase, cls).tearDownClass()
1846
1847 def setUp(self):
1848 super(NeighborAgeTestCase, self).setUp()
1849
1850 self.create_pg_interfaces(range(1))
1851
1852 # pg0 configured with ip4 and 6 addresses used for input
1853 # pg1 configured with ip4 and 6 addresses used for output
1854 # pg2 is unnumbered to pg0
1855 for i in self.pg_interfaces:
1856 i.admin_up()
1857 i.config_ip4()
1858 i.config_ip6()
1859 i.resolve_arp()
1860 i.resolve_ndp()
1861
1862 def tearDown(self):
1863 super(NeighborAgeTestCase, self).tearDown()
1864
1865 for i in self.pg_interfaces:
1866 i.unconfig_ip4()
1867 i.unconfig_ip6()
1868 i.admin_down()
1869
1870 def wait_for_no_nbr(self, intf, address,
1871 n_tries=50, s_time=1):
1872 while (n_tries):
1873 if not find_nbr(self, intf, address):
1874 return True
1875 n_tries = n_tries - 1
1876 self.sleep(s_time)
1877
1878 return False
1879
1880 def verify_arp_req(self, rx, smac, sip, dip):
1881 ether = rx[Ether]
1882 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1883 self.assertEqual(ether.src, smac)
1884
1885 arp = rx[ARP]
1886 self.assertEqual(arp.hwtype, 1)
1887 self.assertEqual(arp.ptype, 0x800)
1888 self.assertEqual(arp.hwlen, 6)
1889 self.assertEqual(arp.plen, 4)
1890 self.assertEqual(arp.op, arp_opts["who-has"])
1891 self.assertEqual(arp.hwsrc, smac)
1892 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
1893 self.assertEqual(arp.psrc, sip)
1894 self.assertEqual(arp.pdst, dip)
1895
1896 def test_age(self):
1897 """ Aging/Recycle """
1898
1899 self.vapi.cli("set logging unthrottle 0")
1900 self.vapi.cli("set logging size %d" % 0xffff)
1901
1902 self.pg0.generate_remote_hosts(201)
1903
1904 vaf = VppEnum.vl_api_address_family_t
1905
1906 #
1907 # start listening on all interfaces
1908 #
1909 self.pg_enable_capture(self.pg_interfaces)
1910
1911 #
1912 # Set the neighbor configuration:
1913 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001914 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00001915 # recycle = false
1916 #
1917 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1918 max_number=200,
1919 max_age=0,
1920 recycle=False)
1921
1922 self.vapi.cli("sh ip neighbor-config")
1923
1924 # add the 198 neighbours that should pass (-1 for one created in setup)
1925 for ii in range(200):
1926 VppNeighbor(self,
1927 self.pg0.sw_if_index,
1928 self.pg0.remote_hosts[ii].mac,
1929 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1930
1931 # one more neighbor over the limit should fail
1932 with self.vapi.assert_negative_api_retval():
1933 VppNeighbor(self,
1934 self.pg0.sw_if_index,
1935 self.pg0.remote_hosts[200].mac,
1936 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1937
1938 #
1939 # change the config to allow recycling the old neighbors
1940 #
1941 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1942 max_number=200,
1943 max_age=0,
1944 recycle=True)
1945
1946 # now new additions are allowed
1947 VppNeighbor(self,
1948 self.pg0.sw_if_index,
1949 self.pg0.remote_hosts[200].mac,
1950 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1951
1952 # add the first neighbor we configured has been re-used
1953 self.assertFalse(find_nbr(self,
1954 self.pg0.sw_if_index,
1955 self.pg0.remote_hosts[0].ip4))
1956 self.assertTrue(find_nbr(self,
1957 self.pg0.sw_if_index,
1958 self.pg0.remote_hosts[200].ip4))
1959
1960 #
1961 # change the config to age old neighbors
1962 #
1963 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1964 max_number=200,
1965 max_age=2,
1966 recycle=True)
1967
1968 self.vapi.cli("sh ip4 neighbor-sorted")
1969
1970 #
1971 # expect probes from all these ARP entries as they age
1972 # 3 probes for each neighbor 3*200 = 600
1973 rxs = self.pg0.get_capture(600, timeout=8)
1974
1975 for ii in range(3):
1976 for jj in range(200):
1977 rx = rxs[ii*200 + jj]
1978 # rx.show()
1979
1980 #
1981 # 3 probes sent then 1 more second to see if a reply comes, before
1982 # they age out
1983 #
1984 for jj in range(1, 201):
1985 self.wait_for_no_nbr(self.pg0.sw_if_index,
1986 self.pg0.remote_hosts[jj].ip4)
1987
1988 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1989 af=vaf.ADDRESS_IP4))
1990
1991 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001992 # load up some neighbours again with 2s aging enabled
1993 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00001994 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001995 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00001996 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
1997
1998 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001999 for ii in range(10):
2000 VppNeighbor(self,
2001 self.pg0.sw_if_index,
2002 self.pg0.remote_hosts[ii].mac,
2003 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002004
2005 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2006 self.assertEqual(e.flags,
2007 enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2008 self.assertEqual(str(e.neighbor.ip_address),
2009 self.pg0.remote_hosts[ii].ip4)
2010 self.assertEqual(e.neighbor.mac_address,
2011 self.pg0.remote_hosts[ii].mac)
2012
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002013 self.sleep(10)
2014 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2015 af=vaf.ADDRESS_IP4))
2016
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002017 evs = []
2018 for ii in range(10):
2019 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2020 self.assertEqual(e.flags,
2021 enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
2022 evs.append(e)
2023
2024 # check we got the correct mac/ip pairs - done separately
2025 # because we don't care about the order the remove notifications
2026 # arrive
2027 for ii in range(10):
2028 found = False
2029 mac = self.pg0.remote_hosts[ii].mac
2030 ip = self.pg0.remote_hosts[ii].ip4
2031
2032 for e in evs:
2033 if (e.neighbor.mac_address == mac and
2034 str(e.neighbor.ip_address) == ip):
2035 found = True
2036 break
2037 self.assertTrue(found)
2038
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002039 #
2040 # check if we can set age and recycle with empty neighbor list
2041 #
2042 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2043 max_number=200,
2044 max_age=1000,
2045 recycle=True)
2046
2047 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002048 # load up some neighbours again, then disable the aging
2049 # they should still be there in 10 seconds time
2050 #
2051 for ii in range(10):
2052 VppNeighbor(self,
2053 self.pg0.sw_if_index,
2054 self.pg0.remote_hosts[ii].mac,
2055 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2056 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2057 max_number=200,
2058 max_age=0,
2059 recycle=False)
2060
2061 self.sleep(10)
2062 self.assertTrue(find_nbr(self,
2063 self.pg0.sw_if_index,
2064 self.pg0.remote_hosts[0].ip4))
2065
2066
Neale Rannsc87fbb42020-04-02 17:08:28 +00002067class NeighborReplaceTestCase(VppTestCase):
2068 """ ARP/ND Replacement """
2069
2070 @classmethod
2071 def setUpClass(cls):
2072 super(NeighborReplaceTestCase, cls).setUpClass()
2073
2074 @classmethod
2075 def tearDownClass(cls):
2076 super(NeighborReplaceTestCase, cls).tearDownClass()
2077
2078 def setUp(self):
2079 super(NeighborReplaceTestCase, self).setUp()
2080
2081 self.create_pg_interfaces(range(4))
2082
2083 # pg0 configured with ip4 and 6 addresses used for input
2084 # pg1 configured with ip4 and 6 addresses used for output
2085 # pg2 is unnumbered to pg0
2086 for i in self.pg_interfaces:
2087 i.admin_up()
2088 i.config_ip4()
2089 i.config_ip6()
2090 i.resolve_arp()
2091 i.resolve_ndp()
2092
2093 def tearDown(self):
2094 super(NeighborReplaceTestCase, self).tearDown()
2095
2096 for i in self.pg_interfaces:
2097 i.unconfig_ip4()
2098 i.unconfig_ip6()
2099 i.admin_down()
2100
2101 def test_replace(self):
2102 """ replace """
2103
2104 N_HOSTS = 16
2105
2106 for i in self.pg_interfaces:
2107 i.generate_remote_hosts(N_HOSTS)
2108 i.configure_ipv4_neighbors()
2109 i.configure_ipv6_neighbors()
2110
2111 # replace them all
2112 self.vapi.ip_neighbor_replace_begin()
2113 self.vapi.ip_neighbor_replace_end()
2114
2115 for i in self.pg_interfaces:
2116 for h in range(N_HOSTS):
2117 self.assertFalse(find_nbr(self,
2118 self.pg0.sw_if_index,
2119 self.pg0.remote_hosts[h].ip4))
2120 self.assertFalse(find_nbr(self,
2121 self.pg0.sw_if_index,
2122 self.pg0.remote_hosts[h].ip6))
2123
2124 #
2125 # and them all back via the API
2126 #
2127 for i in self.pg_interfaces:
2128 for h in range(N_HOSTS):
2129 VppNeighbor(self,
2130 i.sw_if_index,
2131 i.remote_hosts[h].mac,
2132 i.remote_hosts[h].ip4).add_vpp_config()
2133 VppNeighbor(self,
2134 i.sw_if_index,
2135 i.remote_hosts[h].mac,
2136 i.remote_hosts[h].ip6).add_vpp_config()
2137
2138 #
2139 # begin the replacement again, this time touch some
2140 # the neighbours on pg1 so they are not deleted
2141 #
2142 self.vapi.ip_neighbor_replace_begin()
2143
2144 # update from the API all neighbours on pg1
2145 for h in range(N_HOSTS):
2146 VppNeighbor(self,
2147 self.pg1.sw_if_index,
2148 self.pg1.remote_hosts[h].mac,
2149 self.pg1.remote_hosts[h].ip4).add_vpp_config()
2150 VppNeighbor(self,
2151 self.pg1.sw_if_index,
2152 self.pg1.remote_hosts[h].mac,
2153 self.pg1.remote_hosts[h].ip6).add_vpp_config()
2154
2155 # update from the data-plane all neighbours on pg3
2156 self.pg3.configure_ipv4_neighbors()
2157 self.pg3.configure_ipv6_neighbors()
2158
2159 # complete the replacement
2160 self.logger.info(self.vapi.cli("sh ip neighbors"))
2161 self.vapi.ip_neighbor_replace_end()
2162
2163 for i in self.pg_interfaces:
2164 if i == self.pg1 or i == self.pg3:
2165 # neighbours on pg1 and pg3 are still present
2166 for h in range(N_HOSTS):
2167 self.assertTrue(find_nbr(self,
2168 i.sw_if_index,
2169 i.remote_hosts[h].ip4))
2170 self.assertTrue(find_nbr(self,
2171 i.sw_if_index,
2172 i.remote_hosts[h].ip6))
2173 else:
2174 # all other neighbours are toast
2175 for h in range(N_HOSTS):
2176 self.assertFalse(find_nbr(self,
2177 i.sw_if_index,
2178 i.remote_hosts[h].ip4))
2179 self.assertFalse(find_nbr(self,
2180 i.sw_if_index,
2181 i.remote_hosts[h].ip6))
2182
2183
Neale Ranns240dcb22020-04-23 09:04:59 +00002184class NeighborFlush(VppTestCase):
2185 """ Neighbor Flush """
2186
2187 @classmethod
2188 def setUpClass(cls):
2189 super(NeighborFlush, cls).setUpClass()
2190
2191 @classmethod
2192 def tearDownClass(cls):
2193 super(NeighborFlush, cls).tearDownClass()
2194
2195 def setUp(self):
2196 super(NeighborFlush, self).setUp()
2197
2198 self.create_pg_interfaces(range(2))
2199
2200 for i in self.pg_interfaces:
2201 i.admin_up()
2202 i.config_ip4()
2203 i.config_ip6()
2204 i.resolve_arp()
2205 i.resolve_ndp()
2206
2207 def tearDown(self):
2208 super(NeighborFlush, self).tearDown()
2209
2210 for i in self.pg_interfaces:
2211 i.unconfig_ip4()
2212 i.unconfig_ip6()
2213 i.admin_down()
2214
2215 def test_flush(self):
2216 """ Neighbour Flush """
2217
2218 e = VppEnum
2219 nf = e.vl_api_ip_neighbor_flags_t
2220 af = e.vl_api_address_family_t
2221 N_HOSTS = 16
2222 static = [False, True]
2223 self.pg0.generate_remote_hosts(N_HOSTS)
2224 self.pg1.generate_remote_hosts(N_HOSTS)
2225
2226 for s in static:
2227 # a few v4 and v6 dynamic neoghbors
2228 for n in range(N_HOSTS):
2229 VppNeighbor(self,
2230 self.pg0.sw_if_index,
2231 self.pg0.remote_hosts[n].mac,
2232 self.pg0.remote_hosts[n].ip4,
2233 is_static=s).add_vpp_config()
2234 VppNeighbor(self,
2235 self.pg1.sw_if_index,
2236 self.pg1.remote_hosts[n].mac,
2237 self.pg1.remote_hosts[n].ip6,
2238 is_static=s).add_vpp_config()
2239
2240 # flush the interfaces individually
2241 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2242
2243 # check we haven't flushed that which we shouldn't
2244 for n in range(N_HOSTS):
2245 self.assertTrue(find_nbr(self,
2246 self.pg1.sw_if_index,
2247 self.pg1.remote_hosts[n].ip6,
2248 is_static=s))
2249
2250 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2251
2252 for n in range(N_HOSTS):
2253 self.assertFalse(find_nbr(self,
2254 self.pg0.sw_if_index,
2255 self.pg0.remote_hosts[n].ip4))
2256 self.assertFalse(find_nbr(self,
2257 self.pg1.sw_if_index,
2258 self.pg1.remote_hosts[n].ip6))
2259
2260 # add the nieghbours back
2261 for n in range(N_HOSTS):
2262 VppNeighbor(self,
2263 self.pg0.sw_if_index,
2264 self.pg0.remote_hosts[n].mac,
2265 self.pg0.remote_hosts[n].ip4,
2266 is_static=s).add_vpp_config()
2267 VppNeighbor(self,
2268 self.pg1.sw_if_index,
2269 self.pg1.remote_hosts[n].mac,
2270 self.pg1.remote_hosts[n].ip6,
2271 is_static=s).add_vpp_config()
2272
2273 self.logger.info(self.vapi.cli("sh ip neighbor"))
2274
2275 # flush both interfaces at the same time
2276 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2277
2278 # check we haven't flushed that which we shouldn't
2279 for n in range(N_HOSTS):
2280 self.assertTrue(find_nbr(self,
2281 self.pg0.sw_if_index,
2282 self.pg0.remote_hosts[n].ip4,
2283 is_static=s))
2284
2285 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2286
2287 for n in range(N_HOSTS):
2288 self.assertFalse(find_nbr(self,
2289 self.pg0.sw_if_index,
2290 self.pg0.remote_hosts[n].ip4))
2291 self.assertFalse(find_nbr(self,
2292 self.pg1.sw_if_index,
2293 self.pg1.remote_hosts[n].ip6))
2294
2295
Neale Ranns37be7362017-02-21 17:30:26 -08002296if __name__ == '__main__':
2297 unittest.main(testRunner=VppTestRunner)