blob: f69a2634686f7aef996789978deee917358c3247 [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 Rannse2fe0972020-11-26 08:37:27 +000010 VppIpTable, DpoProto, FibPathType, VppIpInterfaceAddress
Neale Ranns37029302018-08-10 05:30:06 -070011from vpp_papi import VppEnum
Jakub Grajciar2df2f752020-12-01 11:23:44 +010012from vpp_ip import VppIpPuntRedirect
Neale Ranns39f9d8b2017-02-16 21:57:05 -080013
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070014import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080015from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070016from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000017from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070018from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080019from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070020from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080021
Paul Vinciguerra4271c972019-05-14 13:25:49 -040022
23NUM_PKTS = 67
24
Neale Ranns39f9d8b2017-02-16 21:57:05 -080025# not exported by scapy, so redefined here
26arp_opts = {"who-has": 1, "is-at": 2}
27
28
29class ARPTestCase(VppTestCase):
30 """ ARP Test Case """
31
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070032 @classmethod
33 def setUpClass(cls):
34 super(ARPTestCase, cls).setUpClass()
35
36 @classmethod
37 def tearDownClass(cls):
38 super(ARPTestCase, cls).tearDownClass()
39
Neale Ranns39f9d8b2017-02-16 21:57:05 -080040 def setUp(self):
41 super(ARPTestCase, self).setUp()
42
43 # create 3 pg interfaces
44 self.create_pg_interfaces(range(4))
45
46 # pg0 configured with ip4 and 6 addresses used for input
47 # pg1 configured with ip4 and 6 addresses used for output
48 # pg2 is unnumbered to pg0
49 for i in self.pg_interfaces:
50 i.admin_up()
51
52 self.pg0.config_ip4()
53 self.pg0.config_ip6()
54 self.pg0.resolve_arp()
55
56 self.pg1.config_ip4()
57 self.pg1.config_ip6()
58
59 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070060 self.tbl = VppIpTable(self, 1)
61 self.tbl.add_vpp_config()
62
Neale Ranns39f9d8b2017-02-16 21:57:05 -080063 self.pg3.set_table_ip4(1)
64 self.pg3.config_ip4()
65
Neale Ranns4008ac92017-02-13 23:20:04 -080066 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080067 self.pg0.unconfig_ip4()
68 self.pg0.unconfig_ip6()
69
70 self.pg1.unconfig_ip4()
71 self.pg1.unconfig_ip6()
72
73 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070074 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080075
Neale Ranns4008ac92017-02-13 23:20:04 -080076 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080077 i.admin_down()
78
Neale Ranns15002542017-09-10 04:39:11 -070079 super(ARPTestCase, self).tearDown()
80
Neale Ranns39f9d8b2017-02-16 21:57:05 -080081 def verify_arp_req(self, rx, smac, sip, dip):
82 ether = rx[Ether]
83 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
84 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +010085 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -080086
87 arp = rx[ARP]
88 self.assertEqual(arp.hwtype, 1)
89 self.assertEqual(arp.ptype, 0x800)
90 self.assertEqual(arp.hwlen, 6)
91 self.assertEqual(arp.plen, 4)
92 self.assertEqual(arp.op, arp_opts["who-has"])
93 self.assertEqual(arp.hwsrc, smac)
94 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
95 self.assertEqual(arp.psrc, sip)
96 self.assertEqual(arp.pdst, dip)
97
98 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
99 ether = rx[Ether]
100 self.assertEqual(ether.dst, dmac)
101 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100102 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800103
104 arp = rx[ARP]
105 self.assertEqual(arp.hwtype, 1)
106 self.assertEqual(arp.ptype, 0x800)
107 self.assertEqual(arp.hwlen, 6)
108 self.assertEqual(arp.plen, 4)
109 self.assertEqual(arp.op, arp_opts["is-at"])
110 self.assertEqual(arp.hwsrc, smac)
111 self.assertEqual(arp.hwdst, dmac)
112 self.assertEqual(arp.psrc, sip)
113 self.assertEqual(arp.pdst, dip)
114
Matthew Smithcb9ab472017-05-16 21:35:56 -0500115 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
116 ether = rx[Ether]
117 self.assertEqual(ether.dst, dmac)
118 self.assertEqual(ether.src, smac)
119
120 arp = rx[ARP]
121 self.assertEqual(arp.hwtype, 1)
122 self.assertEqual(arp.ptype, 0x800)
123 self.assertEqual(arp.hwlen, 6)
124 self.assertEqual(arp.plen, 4)
125 self.assertEqual(arp.op, arp_opts["is-at"])
126 self.assertNotEqual(arp.hwsrc, smac)
127 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
128 "00:00:5E:00:01" in arp.hwsrc)
129 self.assertEqual(arp.hwdst, dmac)
130 self.assertEqual(arp.psrc, sip)
131 self.assertEqual(arp.pdst, dip)
132
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800133 def verify_ip(self, rx, smac, dmac, sip, dip):
134 ether = rx[Ether]
135 self.assertEqual(ether.dst, dmac)
136 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100137 self.assertEqual(ether.type, 0x0800)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800138
139 ip = rx[IP]
140 self.assertEqual(ip.src, sip)
141 self.assertEqual(ip.dst, dip)
142
Neale Ranns37be7362017-02-21 17:30:26 -0800143 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
144 ether = rx[Ether]
145 self.assertEqual(ether.dst, dmac)
146 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100147 self.assertEqual(ether.type, 0x8847)
Neale Ranns37be7362017-02-21 17:30:26 -0800148
149 mpls = rx[MPLS]
150 self.assertTrue(mpls.label, label)
151
152 ip = rx[IP]
153 self.assertEqual(ip.src, sip)
154 self.assertEqual(ip.dst, dip)
155
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800156 def test_arp(self):
157 """ ARP """
158
159 #
160 # Generate some hosts on the LAN
161 #
Neale Rannsca193612017-06-14 06:50:08 -0700162 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800163
164 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000165 # watch for:
166 # - all neighbour events
167 # - all neighbor events on pg1
168 # - neighbor events for host[1] on pg1
169 #
170 self.vapi.want_ip_neighbor_events(enable=1,
171 pid=os.getpid())
172 self.vapi.want_ip_neighbor_events(enable=1,
173 pid=os.getpid(),
174 sw_if_index=self.pg1.sw_if_index)
175 self.vapi.want_ip_neighbor_events(enable=1,
176 pid=os.getpid(),
177 sw_if_index=self.pg1.sw_if_index,
178 ip=self.pg1.remote_hosts[1].ip4)
179
180 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
181
182 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800183 # Send IP traffic to one of these unresolved hosts.
184 # expect the generation of an ARP request
185 #
186 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
187 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
188 UDP(sport=1234, dport=1234) /
189 Raw())
190
191 self.pg0.add_stream(p)
192 self.pg_enable_capture(self.pg_interfaces)
193 self.pg_start()
194
195 rx = self.pg1.get_capture(1)
196
197 self.verify_arp_req(rx[0],
198 self.pg1.local_mac,
199 self.pg1.local_ip4,
200 self.pg1._remote_hosts[1].ip4)
201
202 #
203 # And a dynamic ARP entry for host 1
204 #
205 dyn_arp = VppNeighbor(self,
206 self.pg1.sw_if_index,
207 self.pg1.remote_hosts[1].mac,
208 self.pg1.remote_hosts[1].ip4)
209 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000210 self.assertTrue(dyn_arp.query_vpp_config())
211
Neale Rannsdc617b82020-08-20 08:22:56 +0000212 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
213
Neale Rannscbe25aa2019-09-30 10:53:31 +0000214 # this matches all of the listnerers
215 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
216 for i in range(3)]
217 for e in es:
218 self.assertEqual(str(e.neighbor.ip_address),
219 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800220
221 #
222 # now we expect IP traffic forwarded
223 #
224 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
225 IP(src=self.pg0.remote_ip4,
226 dst=self.pg1._remote_hosts[1].ip4) /
227 UDP(sport=1234, dport=1234) /
228 Raw())
229
230 self.pg0.add_stream(dyn_p)
231 self.pg_enable_capture(self.pg_interfaces)
232 self.pg_start()
233
234 rx = self.pg1.get_capture(1)
235
236 self.verify_ip(rx[0],
237 self.pg1.local_mac,
238 self.pg1.remote_hosts[1].mac,
239 self.pg0.remote_ip4,
240 self.pg1._remote_hosts[1].ip4)
241
242 #
243 # And a Static ARP entry for host 2
244 #
245 static_arp = VppNeighbor(self,
246 self.pg1.sw_if_index,
247 self.pg1.remote_hosts[2].mac,
248 self.pg1.remote_hosts[2].ip4,
249 is_static=1)
250 static_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000251 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
252 for i in range(2)]
253 for e in es:
254 self.assertEqual(str(e.neighbor.ip_address),
255 self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800256
257 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
258 IP(src=self.pg0.remote_ip4,
259 dst=self.pg1._remote_hosts[2].ip4) /
260 UDP(sport=1234, dport=1234) /
261 Raw())
262
263 self.pg0.add_stream(static_p)
264 self.pg_enable_capture(self.pg_interfaces)
265 self.pg_start()
266
267 rx = self.pg1.get_capture(1)
268
269 self.verify_ip(rx[0],
270 self.pg1.local_mac,
271 self.pg1.remote_hosts[2].mac,
272 self.pg0.remote_ip4,
273 self.pg1._remote_hosts[2].ip4)
274
275 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000276 # remove all the listeners
277 #
278 self.vapi.want_ip_neighbor_events(enable=0,
279 pid=os.getpid())
280 self.vapi.want_ip_neighbor_events(enable=0,
281 pid=os.getpid(),
282 sw_if_index=self.pg1.sw_if_index)
283 self.vapi.want_ip_neighbor_events(enable=0,
284 pid=os.getpid(),
285 sw_if_index=self.pg1.sw_if_index,
286 ip=self.pg1.remote_hosts[1].ip4)
287
288 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800289 # flap the link. dynamic ARPs get flush, statics don't
290 #
291 self.pg1.admin_down()
292 self.pg1.admin_up()
293
294 self.pg0.add_stream(static_p)
295 self.pg_enable_capture(self.pg_interfaces)
296 self.pg_start()
297 rx = self.pg1.get_capture(1)
298
299 self.verify_ip(rx[0],
300 self.pg1.local_mac,
301 self.pg1.remote_hosts[2].mac,
302 self.pg0.remote_ip4,
303 self.pg1._remote_hosts[2].ip4)
304
305 self.pg0.add_stream(dyn_p)
306 self.pg_enable_capture(self.pg_interfaces)
307 self.pg_start()
308
309 rx = self.pg1.get_capture(1)
310 self.verify_arp_req(rx[0],
311 self.pg1.local_mac,
312 self.pg1.local_ip4,
313 self.pg1._remote_hosts[1].ip4)
314
Neale Rannscbe25aa2019-09-30 10:53:31 +0000315 self.assertFalse(dyn_arp.query_vpp_config())
316 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800317 #
318 # Send an ARP request from one of the so-far unlearned remote hosts
319 #
320 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
321 src=self.pg1._remote_hosts[3].mac) /
322 ARP(op="who-has",
323 hwsrc=self.pg1._remote_hosts[3].mac,
324 pdst=self.pg1.local_ip4,
325 psrc=self.pg1._remote_hosts[3].ip4))
326
327 self.pg1.add_stream(p)
328 self.pg_enable_capture(self.pg_interfaces)
329 self.pg_start()
330
331 rx = self.pg1.get_capture(1)
332 self.verify_arp_resp(rx[0],
333 self.pg1.local_mac,
334 self.pg1._remote_hosts[3].mac,
335 self.pg1.local_ip4,
336 self.pg1._remote_hosts[3].ip4)
337
338 #
339 # VPP should have learned the mapping for the remote host
340 #
341 self.assertTrue(find_nbr(self,
342 self.pg1.sw_if_index,
343 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800344 #
345 # Fire in an ARP request before the interface becomes IP enabled
346 #
347 self.pg2.generate_remote_hosts(4)
348
349 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
350 ARP(op="who-has",
351 hwsrc=self.pg2.remote_mac,
352 pdst=self.pg1.local_ip4,
353 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700354 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
355 Dot1Q(vlan=0) /
356 ARP(op="who-has",
357 hwsrc=self.pg2.remote_mac,
358 pdst=self.pg1.local_ip4,
359 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800360 self.send_and_assert_no_replies(self.pg2, p,
361 "interface not IP enabled")
362
363 #
364 # Make pg2 un-numbered to pg1
365 #
366 self.pg2.set_unnumbered(self.pg1.sw_if_index)
367
Neale Rannsac3e72c2019-10-06 01:04:26 -0700368 #
369 # test the unnumbered dump both by all interfaces and just the enabled
370 # one
371 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700372 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700373 self.assertTrue(len(unnum))
374 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
375 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
376 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
377 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700378 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
379 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
380
Neale Ranns4b919a52017-03-11 05:55:21 -0800381 #
382 # We should respond to ARP requests for the unnumbered to address
383 # once an attached route to the source is known
384 #
385 self.send_and_assert_no_replies(
386 self.pg2, p,
387 "ARP req for unnumbered address - no source")
388
389 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
390 [VppRoutePath("0.0.0.0",
391 self.pg2.sw_if_index)])
392 attached_host.add_vpp_config()
393
394 self.pg2.add_stream(p)
395 self.pg_enable_capture(self.pg_interfaces)
396 self.pg_start()
397
398 rx = self.pg2.get_capture(1)
399 self.verify_arp_resp(rx[0],
400 self.pg2.local_mac,
401 self.pg2.remote_mac,
402 self.pg1.local_ip4,
403 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800404
Neale Ranns30d0fd42017-05-30 07:30:04 -0700405 self.pg2.add_stream(pt)
406 self.pg_enable_capture(self.pg_interfaces)
407 self.pg_start()
408
409 rx = self.pg2.get_capture(1)
410 self.verify_arp_resp(rx[0],
411 self.pg2.local_mac,
412 self.pg2.remote_mac,
413 self.pg1.local_ip4,
414 self.pg2.remote_hosts[3].ip4)
415
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800416 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800417 # A neighbor entry that has no associated FIB-entry
418 #
419 arp_no_fib = VppNeighbor(self,
420 self.pg1.sw_if_index,
421 self.pg1.remote_hosts[4].mac,
422 self.pg1.remote_hosts[4].ip4,
423 is_no_fib_entry=1)
424 arp_no_fib.add_vpp_config()
425
426 #
427 # check we have the neighbor, but no route
428 #
429 self.assertTrue(find_nbr(self,
430 self.pg1.sw_if_index,
431 self.pg1._remote_hosts[4].ip4))
432 self.assertFalse(find_route(self,
433 self.pg1._remote_hosts[4].ip4,
434 32))
435 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800436 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
437 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800438 #
439 arp_unnum = VppNeighbor(self,
440 self.pg2.sw_if_index,
441 self.pg1.remote_hosts[5].mac,
442 self.pg1.remote_hosts[5].ip4)
443 arp_unnum.add_vpp_config()
444
445 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
446 IP(src=self.pg0.remote_ip4,
447 dst=self.pg1._remote_hosts[5].ip4) /
448 UDP(sport=1234, dport=1234) /
449 Raw())
450
451 self.pg0.add_stream(p)
452 self.pg_enable_capture(self.pg_interfaces)
453 self.pg_start()
454
455 rx = self.pg2.get_capture(1)
456
457 self.verify_ip(rx[0],
458 self.pg2.local_mac,
459 self.pg1.remote_hosts[5].mac,
460 self.pg0.remote_ip4,
461 self.pg1._remote_hosts[5].ip4)
462
463 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800464 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
465 # with the unnumbered interface's address as the source
466 #
467 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
468 ARP(op="who-has",
469 hwsrc=self.pg2.remote_mac,
470 pdst=self.pg1.local_ip4,
471 psrc=self.pg1.remote_hosts[6].ip4))
472
473 self.pg2.add_stream(p)
474 self.pg_enable_capture(self.pg_interfaces)
475 self.pg_start()
476
477 rx = self.pg2.get_capture(1)
478 self.verify_arp_resp(rx[0],
479 self.pg2.local_mac,
480 self.pg2.remote_mac,
481 self.pg1.local_ip4,
482 self.pg1.remote_hosts[6].ip4)
483
484 #
485 # An attached host route out of pg2 for an undiscovered hosts generates
486 # an ARP request with the unnumbered address as the source
487 #
488 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
489 [VppRoutePath("0.0.0.0",
490 self.pg2.sw_if_index)])
491 att_unnum.add_vpp_config()
492
493 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
494 IP(src=self.pg0.remote_ip4,
495 dst=self.pg1._remote_hosts[7].ip4) /
496 UDP(sport=1234, dport=1234) /
497 Raw())
498
499 self.pg0.add_stream(p)
500 self.pg_enable_capture(self.pg_interfaces)
501 self.pg_start()
502
503 rx = self.pg2.get_capture(1)
504
505 self.verify_arp_req(rx[0],
506 self.pg2.local_mac,
507 self.pg1.local_ip4,
508 self.pg1._remote_hosts[7].ip4)
509
510 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
511 ARP(op="who-has",
512 hwsrc=self.pg2.remote_mac,
513 pdst=self.pg1.local_ip4,
514 psrc=self.pg1.remote_hosts[7].ip4))
515
516 self.pg2.add_stream(p)
517 self.pg_enable_capture(self.pg_interfaces)
518 self.pg_start()
519
520 rx = self.pg2.get_capture(1)
521 self.verify_arp_resp(rx[0],
522 self.pg2.local_mac,
523 self.pg2.remote_mac,
524 self.pg1.local_ip4,
525 self.pg1.remote_hosts[7].ip4)
526
527 #
528 # An attached host route as yet unresolved out of pg2 for an
529 # undiscovered host, an ARP requests begets a response.
530 #
531 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
532 [VppRoutePath("0.0.0.0",
533 self.pg2.sw_if_index)])
534 att_unnum1.add_vpp_config()
535
536 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
537 ARP(op="who-has",
538 hwsrc=self.pg2.remote_mac,
539 pdst=self.pg1.local_ip4,
540 psrc=self.pg1.remote_hosts[8].ip4))
541
542 self.pg2.add_stream(p)
543 self.pg_enable_capture(self.pg_interfaces)
544 self.pg_start()
545
546 rx = self.pg2.get_capture(1)
547 self.verify_arp_resp(rx[0],
548 self.pg2.local_mac,
549 self.pg2.remote_mac,
550 self.pg1.local_ip4,
551 self.pg1.remote_hosts[8].ip4)
552
553 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700554 # Send an ARP request from one of the so-far unlearned remote hosts
555 # with a VLAN0 tag
556 #
557 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
558 src=self.pg1._remote_hosts[9].mac) /
559 Dot1Q(vlan=0) /
560 ARP(op="who-has",
561 hwsrc=self.pg1._remote_hosts[9].mac,
562 pdst=self.pg1.local_ip4,
563 psrc=self.pg1._remote_hosts[9].ip4))
564
565 self.pg1.add_stream(p)
566 self.pg_enable_capture(self.pg_interfaces)
567 self.pg_start()
568
569 rx = self.pg1.get_capture(1)
570 self.verify_arp_resp(rx[0],
571 self.pg1.local_mac,
572 self.pg1._remote_hosts[9].mac,
573 self.pg1.local_ip4,
574 self.pg1._remote_hosts[9].ip4)
575
576 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700577 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700578 # Should still get an ARP resp since the cover is attached
579 #
580 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
581 ARP(op="who-has",
582 hwsrc=self.pg1.remote_mac,
583 pdst=self.pg1.local_ip4,
584 psrc=self.pg1.remote_hosts[10].ip4))
585
586 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
587 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
588 self.pg1.sw_if_index)])
589 r1.add_vpp_config()
590
591 self.pg1.add_stream(p)
592 self.pg_enable_capture(self.pg_interfaces)
593 self.pg_start()
594 rx = self.pg1.get_capture(1)
595 self.verify_arp_resp(rx[0],
596 self.pg1.local_mac,
597 self.pg1.remote_mac,
598 self.pg1.local_ip4,
599 self.pg1.remote_hosts[10].ip4)
600
601 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
602 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
603 self.pg1.sw_if_index)])
604 r2.add_vpp_config()
605
606 self.pg1.add_stream(p)
607 self.pg_enable_capture(self.pg_interfaces)
608 self.pg_start()
609 rx = self.pg1.get_capture(1)
610 self.verify_arp_resp(rx[0],
611 self.pg1.local_mac,
612 self.pg1.remote_mac,
613 self.pg1.local_ip4,
614 self.pg1.remote_hosts[10].ip4)
615
616 #
617 # add an ARP entry that's not on the sub-net and so whose
618 # adj-fib fails the refinement check. then send an ARP request
619 # from that source
620 #
621 a1 = VppNeighbor(self,
622 self.pg0.sw_if_index,
623 self.pg0.remote_mac,
624 "100.100.100.50")
625 a1.add_vpp_config()
626
627 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
628 ARP(op="who-has",
629 hwsrc=self.pg0.remote_mac,
630 psrc="100.100.100.50",
631 pdst=self.pg0.remote_ip4))
632 self.send_and_assert_no_replies(self.pg0, p,
633 "ARP req for from failed adj-fib")
634
635 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800636 # ERROR Cases
637 # 1 - don't respond to ARP request for address not within the
638 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700639 # 1b - nor within the unnumbered subnet
640 # 1c - nor within the subnet of a different interface
641 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800642 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
643 ARP(op="who-has",
644 hwsrc=self.pg0.remote_mac,
645 pdst="10.10.10.3",
646 psrc=self.pg0.remote_ip4))
647 self.send_and_assert_no_replies(self.pg0, p,
648 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700649 self.assertFalse(find_nbr(self,
650 self.pg0.sw_if_index,
651 "10.10.10.3"))
652
Neale Ranns4b919a52017-03-11 05:55:21 -0800653 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
654 ARP(op="who-has",
655 hwsrc=self.pg2.remote_mac,
656 pdst="10.10.10.3",
657 psrc=self.pg1.remote_hosts[7].ip4))
658 self.send_and_assert_no_replies(
659 self.pg0, p,
660 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800661
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700662 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
663 ARP(op="who-has",
664 hwsrc=self.pg0.remote_mac,
665 pdst=self.pg1.local_ip4,
666 psrc=self.pg1.remote_ip4))
667 self.send_and_assert_no_replies(self.pg0, p,
668 "ARP req diff sub-net")
669 self.assertFalse(find_nbr(self,
670 self.pg0.sw_if_index,
671 self.pg1.remote_ip4))
672
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800673 #
674 # 2 - don't respond to ARP request from an address not within the
675 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700676 # 2b - to a proxied address
677 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800678 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
679 ARP(op="who-has",
680 hwsrc=self.pg0.remote_mac,
681 psrc="10.10.10.3",
682 pdst=self.pg0.local_ip4))
683 self.send_and_assert_no_replies(self.pg0, p,
684 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800685 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
686 ARP(op="who-has",
687 hwsrc=self.pg2.remote_mac,
688 psrc="10.10.10.3",
689 pdst=self.pg0.local_ip4))
690 self.send_and_assert_no_replies(
691 self.pg0, p,
692 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700693 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
694 ARP(op="who-has",
695 hwsrc=self.pg0.remote_mac,
696 psrc=self.pg1.remote_ip4,
697 pdst=self.pg0.local_ip4))
698 self.send_and_assert_no_replies(self.pg0, p,
699 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800700
701 #
702 # 3 - don't respond to ARP request from an address that belongs to
703 # the router
704 #
705 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
706 ARP(op="who-has",
707 hwsrc=self.pg0.remote_mac,
708 psrc=self.pg0.local_ip4,
709 pdst=self.pg0.local_ip4))
710 self.send_and_assert_no_replies(self.pg0, p,
711 "ARP req for non-local source")
712
713 #
714 # 4 - don't respond to ARP requests that has mac source different
715 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800716 #
717 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
718 ARP(op="who-has",
719 hwsrc="00:00:00:DE:AD:BE",
720 psrc=self.pg0.remote_ip4,
721 pdst=self.pg0.local_ip4))
722 self.send_and_assert_no_replies(self.pg0, p,
723 "ARP req for non-local source")
724
725 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800726 # 5 - don't respond to ARP requests for address within the
727 # interface's sub-net but not the interface's address
728 #
729 self.pg0.generate_remote_hosts(2)
730 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
731 ARP(op="who-has",
732 hwsrc=self.pg0.remote_mac,
733 psrc=self.pg0.remote_hosts[0].ip4,
734 pdst=self.pg0.remote_hosts[1].ip4))
735 self.send_and_assert_no_replies(self.pg0, p,
736 "ARP req for non-local destination")
737
738 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800739 # cleanup
740 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800741 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800742 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800743
Neale Ranns4b919a52017-03-11 05:55:21 -0800744 # need this to flush the adj-fibs
745 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
746 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700747 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800748
Neale Ranns24b170a2017-08-15 05:33:11 -0700749 def test_proxy_mirror_arp(self):
750 """ Interface Mirror Proxy ARP """
751
752 #
753 # When VPP has an interface whose address is also applied to a TAP
754 # interface on the host, then VPP's TAP interface will be unnumbered
755 # to the 'real' interface and do proxy ARP from the host.
756 # the curious aspect of this setup is that ARP requests from the host
757 # will come from the VPP's own address.
758 #
759 self.pg0.generate_remote_hosts(2)
760
761 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
762 dst="ff:ff:ff:ff:ff:ff") /
763 ARP(op="who-has",
764 hwsrc=self.pg2.remote_mac,
765 pdst=self.pg0.remote_hosts[1].ip4,
766 psrc=self.pg0.local_ip4))
767
768 #
769 # Configure Proxy ARP for the subnet on PG0addresses on pg0
770 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100771 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
772 'low': self.pg0._local_ip4_subnet,
773 'hi': self.pg0._local_ip4_bcast},
774 is_add=1)
Neale Ranns24b170a2017-08-15 05:33:11 -0700775
776 # Make pg2 un-numbered to pg0
777 #
778 self.pg2.set_unnumbered(self.pg0.sw_if_index)
779
780 #
781 # Enable pg2 for proxy ARP
782 #
783 self.pg2.set_proxy_arp()
784
785 #
786 # Send the ARP request with an originating address that
787 # is VPP's own address
788 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000789 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Neale Ranns24b170a2017-08-15 05:33:11 -0700790 self.verify_arp_resp(rx[0],
791 self.pg2.local_mac,
792 self.pg2.remote_mac,
793 self.pg0.remote_hosts[1].ip4,
794 self.pg0.local_ip4)
795
796 #
797 # validate we have not learned an ARP entry as a result of this
798 #
799 self.assertFalse(find_nbr(self,
800 self.pg2.sw_if_index,
801 self.pg0.local_ip4))
802
803 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000804 # setup a punt redirect so packets from the uplink go to the tap
805 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100806 redirect = VppIpPuntRedirect(self, self.pg0.sw_if_index,
807 self.pg2.sw_if_index, self.pg0.local_ip4)
808 redirect.add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +0000809
810 p_tcp = (Ether(src=self.pg0.remote_mac,
811 dst=self.pg0.local_mac,) /
812 IP(src=self.pg0.remote_ip4,
813 dst=self.pg0.local_ip4) /
814 TCP(sport=80, dport=80) /
815 Raw())
816 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
817
818 # there's no ARP entry so this is an ARP req
819 self.assertTrue(rx[0].haslayer(ARP))
820
821 # and ARP entry for VPP's pg0 address on the host interface
822 n1 = VppNeighbor(self,
823 self.pg2.sw_if_index,
824 self.pg2.remote_mac,
825 self.pg0.local_ip4,
826 is_no_fib_entry=True).add_vpp_config()
827 # now the packets shold forward
828 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
829 self.assertFalse(rx[0].haslayer(ARP))
830 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
831
832 #
833 # flush the neighbor cache on the uplink
834 #
835 af = VppEnum.vl_api_address_family_t
836 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
837
838 # ensure we can still resolve the ARPs on the uplink
839 self.pg0.resolve_arp()
840
841 self.assertTrue(find_nbr(self,
842 self.pg0.sw_if_index,
843 self.pg0.remote_ip4))
844
845 #
Neale Ranns24b170a2017-08-15 05:33:11 -0700846 # cleanup
847 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100848 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
849 'low': self.pg0._local_ip4_subnet,
850 'hi': self.pg0._local_ip4_bcast},
Neale Ranns24b170a2017-08-15 05:33:11 -0700851 is_add=0)
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100852 redirect.remove_vpp_config()
Neale Ranns24b170a2017-08-15 05:33:11 -0700853
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800854 def test_proxy_arp(self):
855 """ Proxy ARP """
856
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700857 self.pg1.generate_remote_hosts(2)
858
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800859 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700860 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800861 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800862 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
863 dst="ff:ff:ff:ff:ff:ff") /
864 ARP(op="who-has",
865 hwsrc=self.pg0.remote_mac,
866 pdst="10.10.10.3",
867 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700868 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
869 dst="ff:ff:ff:ff:ff:ff") /
870 Dot1Q(vlan=0) /
871 ARP(op="who-has",
872 hwsrc=self.pg0.remote_mac,
873 pdst="10.10.10.3",
874 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800875 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
876 dst="ff:ff:ff:ff:ff:ff") /
877 ARP(op="who-has",
878 hwsrc=self.pg1.remote_mac,
879 pdst="10.10.10.3",
880 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700881 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
882 dst="ff:ff:ff:ff:ff:ff") /
883 ARP(op="who-has",
884 hwsrc=self.pg2.remote_mac,
885 pdst="10.10.10.3",
886 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800887 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
888 dst="ff:ff:ff:ff:ff:ff") /
889 ARP(op="who-has",
890 hwsrc=self.pg3.remote_mac,
891 pdst="10.10.10.3",
892 psrc=self.pg3.remote_ip4))
893
894 #
895 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
896 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100897 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
898 'low': "10.10.10.2",
899 'hi': "10.10.10.124"},
900 is_add=1)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800901
902 #
903 # No responses are sent when the interfaces are not enabled for proxy
904 # ARP
905 #
906 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
907 "ARP req from unconfigured interface")
908 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
909 "ARP req from unconfigured interface")
910
911 #
912 # Make pg2 un-numbered to pg1
913 # still won't reply.
914 #
915 self.pg2.set_unnumbered(self.pg1.sw_if_index)
916
917 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
918 "ARP req from unnumbered interface")
919
920 #
921 # Enable each interface to reply to proxy ARPs
922 #
923 for i in self.pg_interfaces:
924 i.set_proxy_arp()
925
926 #
927 # Now each of the interfaces should reply to a request to a proxied
928 # address
929 #
930 self.pg0.add_stream(arp_req_pg0)
931 self.pg_enable_capture(self.pg_interfaces)
932 self.pg_start()
933
934 rx = self.pg0.get_capture(1)
935 self.verify_arp_resp(rx[0],
936 self.pg0.local_mac,
937 self.pg0.remote_mac,
938 "10.10.10.3",
939 self.pg0.remote_ip4)
940
Neale Ranns30d0fd42017-05-30 07:30:04 -0700941 self.pg0.add_stream(arp_req_pg0_tagged)
942 self.pg_enable_capture(self.pg_interfaces)
943 self.pg_start()
944
945 rx = self.pg0.get_capture(1)
946 self.verify_arp_resp(rx[0],
947 self.pg0.local_mac,
948 self.pg0.remote_mac,
949 "10.10.10.3",
950 self.pg0.remote_ip4)
951
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800952 self.pg1.add_stream(arp_req_pg1)
953 self.pg_enable_capture(self.pg_interfaces)
954 self.pg_start()
955
956 rx = self.pg1.get_capture(1)
957 self.verify_arp_resp(rx[0],
958 self.pg1.local_mac,
959 self.pg1.remote_mac,
960 "10.10.10.3",
961 self.pg1.remote_ip4)
962
963 self.pg2.add_stream(arp_req_pg2)
964 self.pg_enable_capture(self.pg_interfaces)
965 self.pg_start()
966
967 rx = self.pg2.get_capture(1)
968 self.verify_arp_resp(rx[0],
969 self.pg2.local_mac,
970 self.pg2.remote_mac,
971 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700972 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800973
974 #
975 # A request for an address out of the configured range
976 #
977 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
978 dst="ff:ff:ff:ff:ff:ff") /
979 ARP(op="who-has",
980 hwsrc=self.pg1.remote_mac,
981 pdst="10.10.10.125",
982 psrc=self.pg1.remote_ip4))
983 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
984 "ARP req out of range HI")
985 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
986 dst="ff:ff:ff:ff:ff:ff") /
987 ARP(op="who-has",
988 hwsrc=self.pg1.remote_mac,
989 pdst="10.10.10.1",
990 psrc=self.pg1.remote_ip4))
991 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
992 "ARP req out of range Low")
993
994 #
995 # Request for an address in the proxy range but from an interface
996 # in a different VRF
997 #
998 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
999 "ARP req from different VRF")
1000
1001 #
1002 # Disable Each interface for proxy ARP
1003 # - expect none to respond
1004 #
1005 for i in self.pg_interfaces:
1006 i.set_proxy_arp(0)
1007
1008 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
1009 "ARP req from disable")
1010 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
1011 "ARP req from disable")
1012 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
1013 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001014
1015 #
1016 # clean up on interface 2
1017 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001018 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001019
1020 def test_mpls(self):
1021 """ MPLS """
1022
1023 #
1024 # Interface 2 does not yet have ip4 config
1025 #
1026 self.pg2.config_ip4()
1027 self.pg2.generate_remote_hosts(2)
1028
1029 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001030 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001031 #
1032 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1033 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
1034 self.pg2.sw_if_index,
1035 labels=[55])])
1036 ip_10_0_0_1.add_vpp_config()
1037
1038 #
1039 # packets should generate an ARP request
1040 #
1041 p = (Ether(src=self.pg0.remote_mac,
1042 dst=self.pg0.local_mac) /
1043 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
1044 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001045 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -08001046
1047 self.pg0.add_stream(p)
1048 self.pg_enable_capture(self.pg_interfaces)
1049 self.pg_start()
1050
1051 rx = self.pg2.get_capture(1)
1052 self.verify_arp_req(rx[0],
1053 self.pg2.local_mac,
1054 self.pg2.local_ip4,
1055 self.pg2._remote_hosts[1].ip4)
1056
1057 #
1058 # now resolve the neighbours
1059 #
1060 self.pg2.configure_ipv4_neighbors()
1061
1062 #
1063 # Now packet should be properly MPLS encapped.
1064 # This verifies that MPLS link-type adjacencies are completed
1065 # when the ARP entry resolves
1066 #
1067 self.pg0.add_stream(p)
1068 self.pg_enable_capture(self.pg_interfaces)
1069 self.pg_start()
1070
1071 rx = self.pg2.get_capture(1)
1072 self.verify_ip_o_mpls(rx[0],
1073 self.pg2.local_mac,
1074 self.pg2.remote_hosts[1].mac,
1075 55,
1076 self.pg0.remote_ip4,
1077 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -08001078 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001079
Matthew Smithcb9ab472017-05-16 21:35:56 -05001080 def test_arp_vrrp(self):
1081 """ ARP reply with VRRP virtual src hw addr """
1082
1083 #
1084 # IP packet destined for pg1 remote host arrives on pg0 resulting
1085 # in an ARP request for the address of the remote host on pg1
1086 #
1087 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1088 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1089 UDP(sport=1234, dport=1234) /
1090 Raw())
1091
Neale Ranns37029302018-08-10 05:30:06 -07001092 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001093
1094 self.verify_arp_req(rx1[0],
1095 self.pg1.local_mac,
1096 self.pg1.local_ip4,
1097 self.pg1.remote_ip4)
1098
1099 #
1100 # ARP reply for address of pg1 remote host arrives on pg1 with
1101 # the hw src addr set to a value in the VRRP IPv4 range of
1102 # MAC addresses
1103 #
1104 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1105 ARP(op="is-at", hwdst=self.pg1.local_mac,
1106 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1107 psrc=self.pg1.remote_ip4))
1108
Neale Ranns37029302018-08-10 05:30:06 -07001109 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001110
1111 #
1112 # IP packet destined for pg1 remote host arrives on pg0 again.
1113 # VPP should have an ARP entry for that address now and the packet
1114 # should be sent out pg1.
1115 #
Neale Ranns37029302018-08-10 05:30:06 -07001116 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001117
1118 self.verify_ip(rx1[0],
1119 self.pg1.local_mac,
1120 "00:00:5e:00:01:09",
1121 self.pg0.remote_ip4,
1122 self.pg1.remote_ip4)
1123
1124 self.pg1.admin_down()
1125 self.pg1.admin_up()
1126
Neale Rannsdcd6d622017-05-26 02:59:16 -07001127 def test_arp_duplicates(self):
1128 """ ARP Duplicates"""
1129
1130 #
1131 # Generate some hosts on the LAN
1132 #
1133 self.pg1.generate_remote_hosts(3)
1134
1135 #
1136 # Add host 1 on pg1 and pg2
1137 #
1138 arp_pg1 = VppNeighbor(self,
1139 self.pg1.sw_if_index,
1140 self.pg1.remote_hosts[1].mac,
1141 self.pg1.remote_hosts[1].ip4)
1142 arp_pg1.add_vpp_config()
1143 arp_pg2 = VppNeighbor(self,
1144 self.pg2.sw_if_index,
1145 self.pg2.remote_mac,
1146 self.pg1.remote_hosts[1].ip4)
1147 arp_pg2.add_vpp_config()
1148
1149 #
1150 # IP packet destined for pg1 remote host arrives on pg1 again.
1151 #
1152 p = (Ether(dst=self.pg0.local_mac,
1153 src=self.pg0.remote_mac) /
1154 IP(src=self.pg0.remote_ip4,
1155 dst=self.pg1.remote_hosts[1].ip4) /
1156 UDP(sport=1234, dport=1234) /
1157 Raw())
1158
1159 self.pg0.add_stream(p)
1160 self.pg_enable_capture(self.pg_interfaces)
1161 self.pg_start()
1162
1163 rx1 = self.pg1.get_capture(1)
1164
1165 self.verify_ip(rx1[0],
1166 self.pg1.local_mac,
1167 self.pg1.remote_hosts[1].mac,
1168 self.pg0.remote_ip4,
1169 self.pg1.remote_hosts[1].ip4)
1170
1171 #
1172 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001173 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001174 #
1175 arp_pg1.remove_vpp_config()
1176
1177 self.pg0.add_stream(p)
1178 self.pg_enable_capture(self.pg_interfaces)
1179 self.pg_start()
1180
1181 rx1 = self.pg1.get_capture(1)
1182
1183 self.verify_arp_req(rx1[0],
1184 self.pg1.local_mac,
1185 self.pg1.local_ip4,
1186 self.pg1.remote_hosts[1].ip4)
1187
1188 #
1189 # Add it back
1190 #
1191 arp_pg1.add_vpp_config()
1192
1193 self.pg0.add_stream(p)
1194 self.pg_enable_capture(self.pg_interfaces)
1195 self.pg_start()
1196
1197 rx1 = self.pg1.get_capture(1)
1198
1199 self.verify_ip(rx1[0],
1200 self.pg1.local_mac,
1201 self.pg1.remote_hosts[1].mac,
1202 self.pg0.remote_ip4,
1203 self.pg1.remote_hosts[1].ip4)
1204
Neale Ranns15002542017-09-10 04:39:11 -07001205 def test_arp_static(self):
1206 """ ARP Static"""
1207 self.pg2.generate_remote_hosts(3)
1208
1209 #
1210 # Add a static ARP entry
1211 #
1212 static_arp = VppNeighbor(self,
1213 self.pg2.sw_if_index,
1214 self.pg2.remote_hosts[1].mac,
1215 self.pg2.remote_hosts[1].ip4,
1216 is_static=1)
1217 static_arp.add_vpp_config()
1218
1219 #
1220 # Add the connected prefix to the interface
1221 #
1222 self.pg2.config_ip4()
1223
1224 #
1225 # We should now find the adj-fib
1226 #
1227 self.assertTrue(find_nbr(self,
1228 self.pg2.sw_if_index,
1229 self.pg2.remote_hosts[1].ip4,
1230 is_static=1))
1231 self.assertTrue(find_route(self,
1232 self.pg2.remote_hosts[1].ip4,
1233 32))
1234
1235 #
1236 # remove the connected
1237 #
1238 self.pg2.unconfig_ip4()
1239
1240 #
1241 # put the interface into table 1
1242 #
1243 self.pg2.set_table_ip4(1)
1244
1245 #
1246 # configure the same connected and expect to find the
1247 # adj fib in the new table
1248 #
1249 self.pg2.config_ip4()
1250 self.assertTrue(find_route(self,
1251 self.pg2.remote_hosts[1].ip4,
1252 32,
1253 table_id=1))
1254
1255 #
1256 # clean-up
1257 #
1258 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001259 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001260 self.pg2.set_table_ip4(0)
1261
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001262 def test_arp_static_replace_dynamic_same_mac(self):
1263 """ ARP Static can replace Dynamic (same mac) """
1264 self.pg2.generate_remote_hosts(1)
1265
1266 dyn_arp = VppNeighbor(self,
1267 self.pg2.sw_if_index,
1268 self.pg2.remote_hosts[0].mac,
1269 self.pg2.remote_hosts[0].ip4)
1270 static_arp = VppNeighbor(self,
1271 self.pg2.sw_if_index,
1272 self.pg2.remote_hosts[0].mac,
1273 self.pg2.remote_hosts[0].ip4,
1274 is_static=1)
1275
1276 #
1277 # Add a dynamic ARP entry
1278 #
1279 dyn_arp.add_vpp_config()
1280
1281 #
1282 # We should find the dynamic nbr
1283 #
1284 self.assertFalse(find_nbr(self,
1285 self.pg2.sw_if_index,
1286 self.pg2.remote_hosts[0].ip4,
1287 is_static=1))
1288 self.assertTrue(find_nbr(self,
1289 self.pg2.sw_if_index,
1290 self.pg2.remote_hosts[0].ip4,
1291 is_static=0,
1292 mac=self.pg2.remote_hosts[0].mac))
1293
1294 #
1295 # Add a static ARP entry with the same mac
1296 #
1297 static_arp.add_vpp_config()
1298
1299 #
1300 # We should now find the static nbr with the same mac
1301 #
1302 self.assertFalse(find_nbr(self,
1303 self.pg2.sw_if_index,
1304 self.pg2.remote_hosts[0].ip4,
1305 is_static=0))
1306 self.assertTrue(find_nbr(self,
1307 self.pg2.sw_if_index,
1308 self.pg2.remote_hosts[0].ip4,
1309 is_static=1,
1310 mac=self.pg2.remote_hosts[0].mac))
1311
1312 #
1313 # clean-up
1314 #
1315 static_arp.remove_vpp_config()
1316
1317 def test_arp_static_replace_dynamic_diff_mac(self):
1318 """ ARP Static can replace Dynamic (diff mac) """
1319 self.pg2.generate_remote_hosts(2)
1320
1321 dyn_arp = VppNeighbor(self,
1322 self.pg2.sw_if_index,
1323 self.pg2.remote_hosts[0].mac,
1324 self.pg2.remote_hosts[0].ip4)
1325 static_arp = VppNeighbor(self,
1326 self.pg2.sw_if_index,
1327 self.pg2.remote_hosts[1].mac,
1328 self.pg2.remote_hosts[0].ip4,
1329 is_static=1)
1330
1331 #
1332 # Add a dynamic ARP entry
1333 #
1334 dyn_arp.add_vpp_config()
1335
1336 #
1337 # We should find the dynamic nbr
1338 #
1339 self.assertFalse(find_nbr(self,
1340 self.pg2.sw_if_index,
1341 self.pg2.remote_hosts[0].ip4,
1342 is_static=1))
1343 self.assertTrue(find_nbr(self,
1344 self.pg2.sw_if_index,
1345 self.pg2.remote_hosts[0].ip4,
1346 is_static=0,
1347 mac=self.pg2.remote_hosts[0].mac))
1348
1349 #
1350 # Add a static ARP entry with a changed mac
1351 #
1352 static_arp.add_vpp_config()
1353
1354 #
1355 # We should now find the static nbr with a changed mac
1356 #
1357 self.assertFalse(find_nbr(self,
1358 self.pg2.sw_if_index,
1359 self.pg2.remote_hosts[0].ip4,
1360 is_static=0))
1361 self.assertTrue(find_nbr(self,
1362 self.pg2.sw_if_index,
1363 self.pg2.remote_hosts[0].ip4,
1364 is_static=1,
1365 mac=self.pg2.remote_hosts[1].mac))
1366
1367 #
1368 # clean-up
1369 #
1370 static_arp.remove_vpp_config()
1371
Neale Rannsc819fc62018-02-16 02:44:05 -08001372 def test_arp_incomplete(self):
1373 """ ARP Incomplete"""
1374 self.pg1.generate_remote_hosts(3)
1375
1376 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1377 IP(src=self.pg0.remote_ip4,
1378 dst=self.pg1.remote_hosts[1].ip4) /
1379 UDP(sport=1234, dport=1234) /
1380 Raw())
1381 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1382 IP(src=self.pg0.remote_ip4,
1383 dst=self.pg1.remote_hosts[2].ip4) /
1384 UDP(sport=1234, dport=1234) /
1385 Raw())
1386
1387 #
1388 # a packet to an unresolved destination generates an ARP request
1389 #
1390 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1391 self.verify_arp_req(rx[0],
1392 self.pg1.local_mac,
1393 self.pg1.local_ip4,
1394 self.pg1._remote_hosts[1].ip4)
1395
1396 #
1397 # add a neighbour for remote host 1
1398 #
1399 static_arp = VppNeighbor(self,
1400 self.pg1.sw_if_index,
1401 self.pg1.remote_hosts[1].mac,
1402 self.pg1.remote_hosts[1].ip4,
1403 is_static=1)
1404 static_arp.add_vpp_config()
1405
1406 #
1407 # change the interface's MAC
1408 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001409 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001410 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001411
1412 #
1413 # now ARP requests come from the new source mac
1414 #
1415 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1416 self.verify_arp_req(rx[0],
1417 "00:00:00:33:33:33",
1418 self.pg1.local_ip4,
1419 self.pg1._remote_hosts[2].ip4)
1420
1421 #
1422 # packets to the resolved host also have the new source mac
1423 #
1424 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1425 self.verify_ip(rx[0],
1426 "00:00:00:33:33:33",
1427 self.pg1.remote_hosts[1].mac,
1428 self.pg0.remote_ip4,
1429 self.pg1.remote_hosts[1].ip4)
1430
1431 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001432 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001433 # configured subnet and thus no glean
1434 #
1435 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001436 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001437
Neale Ranns59ae61e2018-06-07 18:09:49 -07001438 def test_garp(self):
1439 """ GARP """
1440
1441 #
1442 # Generate some hosts on the LAN
1443 #
1444 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001445 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001446
1447 #
1448 # And an ARP entry
1449 #
1450 arp = VppNeighbor(self,
1451 self.pg1.sw_if_index,
1452 self.pg1.remote_hosts[1].mac,
1453 self.pg1.remote_hosts[1].ip4)
1454 arp.add_vpp_config()
1455
1456 self.assertTrue(find_nbr(self,
1457 self.pg1.sw_if_index,
1458 self.pg1.remote_hosts[1].ip4,
1459 mac=self.pg1.remote_hosts[1].mac))
1460
1461 #
1462 # Send a GARP (request) to swap the host 1's address to that of host 2
1463 #
1464 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1465 src=self.pg1.remote_hosts[2].mac) /
1466 ARP(op="who-has",
1467 hwdst=self.pg1.local_mac,
1468 hwsrc=self.pg1.remote_hosts[2].mac,
1469 pdst=self.pg1.remote_hosts[1].ip4,
1470 psrc=self.pg1.remote_hosts[1].ip4))
1471
1472 self.pg1.add_stream(p1)
1473 self.pg_enable_capture(self.pg_interfaces)
1474 self.pg_start()
1475
1476 self.assertTrue(find_nbr(self,
1477 self.pg1.sw_if_index,
1478 self.pg1.remote_hosts[1].ip4,
1479 mac=self.pg1.remote_hosts[2].mac))
1480
1481 #
1482 # Send a GARP (reply) to swap the host 1's address to that of host 3
1483 #
1484 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1485 src=self.pg1.remote_hosts[3].mac) /
1486 ARP(op="is-at",
1487 hwdst=self.pg1.local_mac,
1488 hwsrc=self.pg1.remote_hosts[3].mac,
1489 pdst=self.pg1.remote_hosts[1].ip4,
1490 psrc=self.pg1.remote_hosts[1].ip4))
1491
1492 self.pg1.add_stream(p1)
1493 self.pg_enable_capture(self.pg_interfaces)
1494 self.pg_start()
1495
1496 self.assertTrue(find_nbr(self,
1497 self.pg1.sw_if_index,
1498 self.pg1.remote_hosts[1].ip4,
1499 mac=self.pg1.remote_hosts[3].mac))
1500
1501 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001502 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001503 # don't result in new neighbour entries
1504 #
1505 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1506 src=self.pg1.remote_hosts[3].mac) /
1507 ARP(op="who-has",
1508 hwdst=self.pg1.local_mac,
1509 hwsrc=self.pg1.remote_hosts[3].mac,
1510 pdst=self.pg1.remote_hosts[2].ip4,
1511 psrc=self.pg1.remote_hosts[2].ip4))
1512
1513 self.pg1.add_stream(p1)
1514 self.pg_enable_capture(self.pg_interfaces)
1515 self.pg_start()
1516
1517 self.assertFalse(find_nbr(self,
1518 self.pg1.sw_if_index,
1519 self.pg1.remote_hosts[2].ip4))
1520
1521 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1522 src=self.pg1.remote_hosts[3].mac) /
1523 ARP(op="is-at",
1524 hwdst=self.pg1.local_mac,
1525 hwsrc=self.pg1.remote_hosts[3].mac,
1526 pdst=self.pg1.remote_hosts[2].ip4,
1527 psrc=self.pg1.remote_hosts[2].ip4))
1528
1529 self.pg1.add_stream(p1)
1530 self.pg_enable_capture(self.pg_interfaces)
1531 self.pg_start()
1532
1533 self.assertFalse(find_nbr(self,
1534 self.pg1.sw_if_index,
1535 self.pg1.remote_hosts[2].ip4))
1536
Neale Ranns22eefd72020-09-23 11:25:21 +00001537 #
1538 # IP address in different subnets are not learnt
1539 #
1540 self.pg2.configure_ipv4_neighbors()
1541
1542 for op in ["is-at", "who-has"]:
1543 p1 = [(Ether(dst="ff:ff:ff:ff:ff:ff",
1544 src=self.pg2.remote_hosts[1].mac) /
1545 ARP(op=op,
1546 hwdst=self.pg2.local_mac,
1547 hwsrc=self.pg2.remote_hosts[1].mac,
1548 pdst=self.pg2.remote_hosts[1].ip4,
1549 psrc=self.pg2.remote_hosts[1].ip4)),
1550 (Ether(dst="ff:ff:ff:ff:ff:ff",
1551 src=self.pg2.remote_hosts[1].mac) /
1552 ARP(op=op,
1553 hwdst="ff:ff:ff:ff:ff:ff",
1554 hwsrc=self.pg2.remote_hosts[1].mac,
1555 pdst=self.pg2.remote_hosts[1].ip4,
1556 psrc=self.pg2.remote_hosts[1].ip4))]
1557
1558 self.send_and_assert_no_replies(self.pg1, p1)
1559 self.assertFalse(find_nbr(self,
1560 self.pg1.sw_if_index,
1561 self.pg2.remote_hosts[1].ip4))
1562
1563 # they are all dropped because the subnet's don't match
1564 self.assertEqual(4, self.statistics.get_err_counter(
1565 "/err/arp-reply/IP4 destination address not local to subnet"))
1566
Neale Ranns77f91622020-11-23 16:25:27 +00001567 def test_arp_incomplete2(self):
Neale Ranns14260392018-09-28 05:00:57 -07001568 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001569
1570 #
Neale Rannscd35e532018-08-31 02:51:45 -07001571 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001572 #
1573 self.pg0.generate_remote_hosts(2)
1574
Neale Rannscd35e532018-08-31 02:51:45 -07001575 #
1576 # IPv4/ARP
1577 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001578 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1579 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001580 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001581 ip_10_0_0_1.add_vpp_config()
1582
1583 p1 = (Ether(dst=self.pg1.local_mac,
1584 src=self.pg1.remote_mac) /
1585 IP(src=self.pg1.remote_ip4,
1586 dst="10.0.0.1") /
1587 UDP(sport=1234, dport=1234) /
1588 Raw())
1589
1590 self.pg1.add_stream(p1 * 257)
1591 self.pg_enable_capture(self.pg_interfaces)
1592 self.pg_start()
1593 rx = self.pg0._get_capture(1)
1594
1595 #
1596 # how many we get is going to be dependent on the time for packet
1597 # processing but it should be small
1598 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001599 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001600
Neale Rannscd35e532018-08-31 02:51:45 -07001601 #
1602 # IPv6/ND
1603 #
1604 ip_10_1 = VppIpRoute(self, "10::1", 128,
1605 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1606 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001607 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001608 ip_10_1.add_vpp_config()
1609
1610 p1 = (Ether(dst=self.pg1.local_mac,
1611 src=self.pg1.remote_mac) /
1612 IPv6(src=self.pg1.remote_ip6,
1613 dst="10::1") /
1614 UDP(sport=1234, dport=1234) /
1615 Raw())
1616
1617 self.pg1.add_stream(p1 * 257)
1618 self.pg_enable_capture(self.pg_interfaces)
1619 self.pg_start()
1620 rx = self.pg0._get_capture(1)
1621
1622 #
1623 # how many we get is going to be dependent on the time for packet
1624 # processing but it should be small
1625 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001626 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001627
Neale Ranns7425f922019-01-23 00:36:16 -08001628 def test_arp_forus(self):
1629 """ ARP for for-us """
1630
1631 #
1632 # Test that VPP responds with ARP requests to addresses that
1633 # are connected and local routes.
1634 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001635 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001636 # address added to an interface
1637 #
1638 self.pg0.generate_remote_hosts(2)
1639
Neale Ranns097fa662018-05-01 05:17:55 -07001640 forus = VppIpRoute(
1641 self, self.pg0.remote_hosts[1].ip4, 32,
1642 [VppRoutePath("0.0.0.0",
1643 self.pg0.sw_if_index,
1644 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001645 forus.add_vpp_config()
1646
1647 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1648 src=self.pg0.remote_mac) /
1649 ARP(op="who-has",
1650 hwdst=self.pg0.local_mac,
1651 hwsrc=self.pg0.remote_mac,
1652 pdst=self.pg0.remote_hosts[1].ip4,
1653 psrc=self.pg0.remote_ip4))
1654
1655 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1656
1657 self.verify_arp_resp(rx[0],
1658 self.pg0.local_mac,
1659 self.pg0.remote_mac,
1660 self.pg0.remote_hosts[1].ip4,
1661 self.pg0.remote_ip4)
1662
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001663 def test_arp_table_swap(self):
1664 #
1665 # Generate some hosts on the LAN
1666 #
1667 N_NBRS = 4
1668 self.pg1.generate_remote_hosts(N_NBRS)
1669
1670 for n in range(N_NBRS):
1671 # a route thru each neighbour
1672 VppIpRoute(self, "10.0.0.%d" % n, 32,
1673 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1674 self.pg1.sw_if_index)]).add_vpp_config()
1675
1676 # resolve each neighbour
1677 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1678 ARP(op="is-at", hwdst=self.pg1.local_mac,
1679 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1680 psrc=self.pg1.remote_hosts[n].ip4))
1681
1682 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1683
1684 self.logger.info(self.vapi.cli("sh ip neighbors"))
1685
1686 #
1687 # swap the table pg1 is in
1688 #
1689 table = VppIpTable(self, 100).add_vpp_config()
1690
1691 self.pg1.unconfig_ip4()
1692 self.pg1.set_table_ip4(100)
1693 self.pg1.config_ip4()
1694
1695 #
1696 # all neighbours are cleared
1697 #
1698 for n in range(N_NBRS):
1699 self.assertFalse(find_nbr(self,
1700 self.pg1.sw_if_index,
1701 self.pg1.remote_hosts[n].ip4))
1702
1703 #
1704 # packets to all neighbours generate ARP requests
1705 #
1706 for n in range(N_NBRS):
1707 # a route thru each neighbour
1708 VppIpRoute(self, "10.0.0.%d" % n, 32,
1709 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1710 self.pg1.sw_if_index)],
1711 table_id=100).add_vpp_config()
1712
1713 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1714 dst=self.pg1.local_mac) /
1715 IP(src=self.pg1.remote_hosts[n].ip4,
1716 dst="10.0.0.%d" % n) /
1717 Raw(b'0x5' * 100))
1718 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1719 for rx in rxs:
1720 self.verify_arp_req(rx,
1721 self.pg1.local_mac,
1722 self.pg1.local_ip4,
1723 self.pg1.remote_hosts[n].ip4)
1724
1725 self.pg1.unconfig_ip4()
1726 self.pg1.set_table_ip4(0)
1727
Neale Rannse2fe0972020-11-26 08:37:27 +00001728 def test_glean_src_select(self):
1729 """ Multi Connecteds """
1730
1731 #
1732 # configure multiple connected subnets on an interface
1733 # and ensure that ARP requests for hosts on those subnets
1734 # pick up the correct source address
1735 #
1736 conn1 = VppIpInterfaceAddress(self, self.pg1,
1737 "10.0.0.1", 24).add_vpp_config()
1738 conn2 = VppIpInterfaceAddress(self, self.pg1,
1739 "10.0.1.1", 24).add_vpp_config()
1740
1741 p1 = (Ether(src=self.pg0.remote_mac,
1742 dst=self.pg0.local_mac) /
1743 IP(src=self.pg1.remote_ip4,
1744 dst="10.0.0.128") /
1745 Raw(b'0x5' * 100))
1746
1747 rxs = self.send_and_expect(self.pg0, [p1], self.pg1)
1748 for rx in rxs:
1749 self.verify_arp_req(rx,
1750 self.pg1.local_mac,
1751 "10.0.0.1",
1752 "10.0.0.128")
1753
1754 p2 = (Ether(src=self.pg0.remote_mac,
1755 dst=self.pg0.local_mac) /
1756 IP(src=self.pg1.remote_ip4,
1757 dst="10.0.1.128") /
1758 Raw(b'0x5' * 100))
1759
1760 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1761 for rx in rxs:
1762 self.verify_arp_req(rx,
1763 self.pg1.local_mac,
1764 "10.0.1.1",
1765 "10.0.1.128")
1766
1767 #
1768 # add a local address in the same subnet
1769 # the source addresses are equivalent. VPP happens to
1770 # choose the last one that was added
1771 conn3 = VppIpInterfaceAddress(self, self.pg1,
1772 "10.0.1.2", 24).add_vpp_config()
1773
1774 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1775 for rx in rxs:
1776 self.verify_arp_req(rx,
1777 self.pg1.local_mac,
1778 "10.0.1.2",
1779 "10.0.1.128")
1780
1781 #
1782 # remove
1783 #
1784 conn3.remove_vpp_config()
1785 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1786 for rx in rxs:
1787 self.verify_arp_req(rx,
1788 self.pg1.local_mac,
1789 "10.0.1.1",
1790 "10.0.1.128")
1791
1792 #
1793 # add back, this time remove the first one
1794 #
1795 conn3 = VppIpInterfaceAddress(self, self.pg1,
1796 "10.0.1.2", 24).add_vpp_config()
1797
1798 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1799 for rx in rxs:
1800 self.verify_arp_req(rx,
1801 self.pg1.local_mac,
1802 "10.0.1.2",
1803 "10.0.1.128")
1804
1805 conn1.remove_vpp_config()
1806 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1807 for rx in rxs:
1808 self.verify_arp_req(rx,
1809 self.pg1.local_mac,
1810 "10.0.1.2",
1811 "10.0.1.128")
1812
1813 # cleanup
1814 conn3.remove_vpp_config()
1815 conn2.remove_vpp_config()
1816
Neale Rannsdcd6d622017-05-26 02:59:16 -07001817
Neale Ranns14260392018-09-28 05:00:57 -07001818class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001819 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001820
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001821 @classmethod
1822 def setUpClass(cls):
1823 super(NeighborStatsTestCase, cls).setUpClass()
1824
1825 @classmethod
1826 def tearDownClass(cls):
1827 super(NeighborStatsTestCase, cls).tearDownClass()
1828
Neale Ranns14260392018-09-28 05:00:57 -07001829 def setUp(self):
1830 super(NeighborStatsTestCase, self).setUp()
1831
1832 self.create_pg_interfaces(range(2))
1833
1834 # pg0 configured with ip4 and 6 addresses used for input
1835 # pg1 configured with ip4 and 6 addresses used for output
1836 # pg2 is unnumbered to pg0
1837 for i in self.pg_interfaces:
1838 i.admin_up()
1839 i.config_ip4()
1840 i.config_ip6()
1841 i.resolve_arp()
1842 i.resolve_ndp()
1843
1844 def tearDown(self):
1845 super(NeighborStatsTestCase, self).tearDown()
1846
1847 for i in self.pg_interfaces:
1848 i.unconfig_ip4()
1849 i.unconfig_ip6()
1850 i.admin_down()
1851
1852 def test_arp_stats(self):
1853 """ ARP Counters """
1854
1855 self.vapi.cli("adj counters enable")
1856 self.pg1.generate_remote_hosts(2)
1857
1858 arp1 = VppNeighbor(self,
1859 self.pg1.sw_if_index,
1860 self.pg1.remote_hosts[0].mac,
1861 self.pg1.remote_hosts[0].ip4)
1862 arp1.add_vpp_config()
1863 arp2 = VppNeighbor(self,
1864 self.pg1.sw_if_index,
1865 self.pg1.remote_hosts[1].mac,
1866 self.pg1.remote_hosts[1].ip4)
1867 arp2.add_vpp_config()
1868
1869 p1 = (Ether(dst=self.pg0.local_mac,
1870 src=self.pg0.remote_mac) /
1871 IP(src=self.pg0.remote_ip4,
1872 dst=self.pg1.remote_hosts[0].ip4) /
1873 UDP(sport=1234, dport=1234) /
1874 Raw())
1875 p2 = (Ether(dst=self.pg0.local_mac,
1876 src=self.pg0.remote_mac) /
1877 IP(src=self.pg0.remote_ip4,
1878 dst=self.pg1.remote_hosts[1].ip4) /
1879 UDP(sport=1234, dport=1234) /
1880 Raw())
1881
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001882 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1883 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001884
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001885 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1886 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001887
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001888 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1889 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001890
1891 def test_nd_stats(self):
1892 """ ND Counters """
1893
1894 self.vapi.cli("adj counters enable")
1895 self.pg0.generate_remote_hosts(3)
1896
1897 nd1 = VppNeighbor(self,
1898 self.pg0.sw_if_index,
1899 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001900 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001901 nd1.add_vpp_config()
1902 nd2 = VppNeighbor(self,
1903 self.pg0.sw_if_index,
1904 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001905 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001906 nd2.add_vpp_config()
1907
1908 p1 = (Ether(dst=self.pg1.local_mac,
1909 src=self.pg1.remote_mac) /
1910 IPv6(src=self.pg1.remote_ip6,
1911 dst=self.pg0.remote_hosts[1].ip6) /
1912 UDP(sport=1234, dport=1234) /
1913 Raw())
1914 p2 = (Ether(dst=self.pg1.local_mac,
1915 src=self.pg1.remote_mac) /
1916 IPv6(src=self.pg1.remote_ip6,
1917 dst=self.pg0.remote_hosts[2].ip6) /
1918 UDP(sport=1234, dport=1234) /
1919 Raw())
1920
1921 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1922 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1923
1924 self.assertEqual(16, nd1.get_stats()['packets'])
1925 self.assertEqual(16, nd2.get_stats()['packets'])
1926
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001927 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1928 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001929
1930
Neale Rannscbe25aa2019-09-30 10:53:31 +00001931class NeighborAgeTestCase(VppTestCase):
1932 """ ARP/ND Aging """
1933
1934 @classmethod
1935 def setUpClass(cls):
1936 super(NeighborAgeTestCase, cls).setUpClass()
1937
1938 @classmethod
1939 def tearDownClass(cls):
1940 super(NeighborAgeTestCase, cls).tearDownClass()
1941
1942 def setUp(self):
1943 super(NeighborAgeTestCase, self).setUp()
1944
1945 self.create_pg_interfaces(range(1))
1946
1947 # pg0 configured with ip4 and 6 addresses used for input
1948 # pg1 configured with ip4 and 6 addresses used for output
1949 # pg2 is unnumbered to pg0
1950 for i in self.pg_interfaces:
1951 i.admin_up()
1952 i.config_ip4()
1953 i.config_ip6()
1954 i.resolve_arp()
1955 i.resolve_ndp()
1956
1957 def tearDown(self):
1958 super(NeighborAgeTestCase, self).tearDown()
1959
1960 for i in self.pg_interfaces:
1961 i.unconfig_ip4()
1962 i.unconfig_ip6()
1963 i.admin_down()
1964
1965 def wait_for_no_nbr(self, intf, address,
1966 n_tries=50, s_time=1):
1967 while (n_tries):
1968 if not find_nbr(self, intf, address):
1969 return True
1970 n_tries = n_tries - 1
1971 self.sleep(s_time)
1972
1973 return False
1974
1975 def verify_arp_req(self, rx, smac, sip, dip):
1976 ether = rx[Ether]
1977 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1978 self.assertEqual(ether.src, smac)
1979
1980 arp = rx[ARP]
1981 self.assertEqual(arp.hwtype, 1)
1982 self.assertEqual(arp.ptype, 0x800)
1983 self.assertEqual(arp.hwlen, 6)
1984 self.assertEqual(arp.plen, 4)
1985 self.assertEqual(arp.op, arp_opts["who-has"])
1986 self.assertEqual(arp.hwsrc, smac)
1987 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
1988 self.assertEqual(arp.psrc, sip)
1989 self.assertEqual(arp.pdst, dip)
1990
1991 def test_age(self):
1992 """ Aging/Recycle """
1993
1994 self.vapi.cli("set logging unthrottle 0")
1995 self.vapi.cli("set logging size %d" % 0xffff)
1996
1997 self.pg0.generate_remote_hosts(201)
1998
1999 vaf = VppEnum.vl_api_address_family_t
2000
2001 #
2002 # start listening on all interfaces
2003 #
2004 self.pg_enable_capture(self.pg_interfaces)
2005
2006 #
2007 # Set the neighbor configuration:
2008 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002009 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00002010 # recycle = false
2011 #
2012 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2013 max_number=200,
2014 max_age=0,
2015 recycle=False)
2016
2017 self.vapi.cli("sh ip neighbor-config")
2018
2019 # add the 198 neighbours that should pass (-1 for one created in setup)
2020 for ii in range(200):
2021 VppNeighbor(self,
2022 self.pg0.sw_if_index,
2023 self.pg0.remote_hosts[ii].mac,
2024 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2025
2026 # one more neighbor over the limit should fail
2027 with self.vapi.assert_negative_api_retval():
2028 VppNeighbor(self,
2029 self.pg0.sw_if_index,
2030 self.pg0.remote_hosts[200].mac,
2031 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2032
2033 #
2034 # change the config to allow recycling the old neighbors
2035 #
2036 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2037 max_number=200,
2038 max_age=0,
2039 recycle=True)
2040
2041 # now new additions are allowed
2042 VppNeighbor(self,
2043 self.pg0.sw_if_index,
2044 self.pg0.remote_hosts[200].mac,
2045 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2046
2047 # add the first neighbor we configured has been re-used
2048 self.assertFalse(find_nbr(self,
2049 self.pg0.sw_if_index,
2050 self.pg0.remote_hosts[0].ip4))
2051 self.assertTrue(find_nbr(self,
2052 self.pg0.sw_if_index,
2053 self.pg0.remote_hosts[200].ip4))
2054
2055 #
2056 # change the config to age old neighbors
2057 #
2058 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2059 max_number=200,
2060 max_age=2,
2061 recycle=True)
2062
2063 self.vapi.cli("sh ip4 neighbor-sorted")
2064
2065 #
2066 # expect probes from all these ARP entries as they age
2067 # 3 probes for each neighbor 3*200 = 600
2068 rxs = self.pg0.get_capture(600, timeout=8)
2069
2070 for ii in range(3):
2071 for jj in range(200):
2072 rx = rxs[ii*200 + jj]
2073 # rx.show()
2074
2075 #
2076 # 3 probes sent then 1 more second to see if a reply comes, before
2077 # they age out
2078 #
2079 for jj in range(1, 201):
2080 self.wait_for_no_nbr(self.pg0.sw_if_index,
2081 self.pg0.remote_hosts[jj].ip4)
2082
2083 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2084 af=vaf.ADDRESS_IP4))
2085
2086 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002087 # load up some neighbours again with 2s aging enabled
2088 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002089 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002090 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002091 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2092
2093 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002094 for ii in range(10):
2095 VppNeighbor(self,
2096 self.pg0.sw_if_index,
2097 self.pg0.remote_hosts[ii].mac,
2098 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002099
2100 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2101 self.assertEqual(e.flags,
2102 enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2103 self.assertEqual(str(e.neighbor.ip_address),
2104 self.pg0.remote_hosts[ii].ip4)
2105 self.assertEqual(e.neighbor.mac_address,
2106 self.pg0.remote_hosts[ii].mac)
2107
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002108 self.sleep(10)
2109 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2110 af=vaf.ADDRESS_IP4))
2111
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002112 evs = []
2113 for ii in range(10):
2114 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2115 self.assertEqual(e.flags,
2116 enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
2117 evs.append(e)
2118
2119 # check we got the correct mac/ip pairs - done separately
2120 # because we don't care about the order the remove notifications
2121 # arrive
2122 for ii in range(10):
2123 found = False
2124 mac = self.pg0.remote_hosts[ii].mac
2125 ip = self.pg0.remote_hosts[ii].ip4
2126
2127 for e in evs:
2128 if (e.neighbor.mac_address == mac and
2129 str(e.neighbor.ip_address) == ip):
2130 found = True
2131 break
2132 self.assertTrue(found)
2133
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002134 #
2135 # check if we can set age and recycle with empty neighbor list
2136 #
2137 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2138 max_number=200,
2139 max_age=1000,
2140 recycle=True)
2141
2142 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002143 # load up some neighbours again, then disable the aging
2144 # they should still be there in 10 seconds time
2145 #
2146 for ii in range(10):
2147 VppNeighbor(self,
2148 self.pg0.sw_if_index,
2149 self.pg0.remote_hosts[ii].mac,
2150 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2151 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2152 max_number=200,
2153 max_age=0,
2154 recycle=False)
2155
2156 self.sleep(10)
2157 self.assertTrue(find_nbr(self,
2158 self.pg0.sw_if_index,
2159 self.pg0.remote_hosts[0].ip4))
2160
2161
Neale Rannsc87fbb42020-04-02 17:08:28 +00002162class NeighborReplaceTestCase(VppTestCase):
2163 """ ARP/ND Replacement """
2164
2165 @classmethod
2166 def setUpClass(cls):
2167 super(NeighborReplaceTestCase, cls).setUpClass()
2168
2169 @classmethod
2170 def tearDownClass(cls):
2171 super(NeighborReplaceTestCase, cls).tearDownClass()
2172
2173 def setUp(self):
2174 super(NeighborReplaceTestCase, self).setUp()
2175
2176 self.create_pg_interfaces(range(4))
2177
2178 # pg0 configured with ip4 and 6 addresses used for input
2179 # pg1 configured with ip4 and 6 addresses used for output
2180 # pg2 is unnumbered to pg0
2181 for i in self.pg_interfaces:
2182 i.admin_up()
2183 i.config_ip4()
2184 i.config_ip6()
2185 i.resolve_arp()
2186 i.resolve_ndp()
2187
2188 def tearDown(self):
2189 super(NeighborReplaceTestCase, self).tearDown()
2190
2191 for i in self.pg_interfaces:
2192 i.unconfig_ip4()
2193 i.unconfig_ip6()
2194 i.admin_down()
2195
2196 def test_replace(self):
2197 """ replace """
2198
2199 N_HOSTS = 16
2200
2201 for i in self.pg_interfaces:
2202 i.generate_remote_hosts(N_HOSTS)
2203 i.configure_ipv4_neighbors()
2204 i.configure_ipv6_neighbors()
2205
2206 # replace them all
2207 self.vapi.ip_neighbor_replace_begin()
2208 self.vapi.ip_neighbor_replace_end()
2209
2210 for i in self.pg_interfaces:
2211 for h in range(N_HOSTS):
2212 self.assertFalse(find_nbr(self,
2213 self.pg0.sw_if_index,
2214 self.pg0.remote_hosts[h].ip4))
2215 self.assertFalse(find_nbr(self,
2216 self.pg0.sw_if_index,
2217 self.pg0.remote_hosts[h].ip6))
2218
2219 #
2220 # and them all back via the API
2221 #
2222 for i in self.pg_interfaces:
2223 for h in range(N_HOSTS):
2224 VppNeighbor(self,
2225 i.sw_if_index,
2226 i.remote_hosts[h].mac,
2227 i.remote_hosts[h].ip4).add_vpp_config()
2228 VppNeighbor(self,
2229 i.sw_if_index,
2230 i.remote_hosts[h].mac,
2231 i.remote_hosts[h].ip6).add_vpp_config()
2232
2233 #
2234 # begin the replacement again, this time touch some
2235 # the neighbours on pg1 so they are not deleted
2236 #
2237 self.vapi.ip_neighbor_replace_begin()
2238
2239 # update from the API all neighbours on pg1
2240 for h in range(N_HOSTS):
2241 VppNeighbor(self,
2242 self.pg1.sw_if_index,
2243 self.pg1.remote_hosts[h].mac,
2244 self.pg1.remote_hosts[h].ip4).add_vpp_config()
2245 VppNeighbor(self,
2246 self.pg1.sw_if_index,
2247 self.pg1.remote_hosts[h].mac,
2248 self.pg1.remote_hosts[h].ip6).add_vpp_config()
2249
2250 # update from the data-plane all neighbours on pg3
2251 self.pg3.configure_ipv4_neighbors()
2252 self.pg3.configure_ipv6_neighbors()
2253
2254 # complete the replacement
2255 self.logger.info(self.vapi.cli("sh ip neighbors"))
2256 self.vapi.ip_neighbor_replace_end()
2257
2258 for i in self.pg_interfaces:
2259 if i == self.pg1 or i == self.pg3:
2260 # neighbours on pg1 and pg3 are still present
2261 for h in range(N_HOSTS):
2262 self.assertTrue(find_nbr(self,
2263 i.sw_if_index,
2264 i.remote_hosts[h].ip4))
2265 self.assertTrue(find_nbr(self,
2266 i.sw_if_index,
2267 i.remote_hosts[h].ip6))
2268 else:
2269 # all other neighbours are toast
2270 for h in range(N_HOSTS):
2271 self.assertFalse(find_nbr(self,
2272 i.sw_if_index,
2273 i.remote_hosts[h].ip4))
2274 self.assertFalse(find_nbr(self,
2275 i.sw_if_index,
2276 i.remote_hosts[h].ip6))
2277
2278
Neale Ranns240dcb22020-04-23 09:04:59 +00002279class NeighborFlush(VppTestCase):
2280 """ Neighbor Flush """
2281
2282 @classmethod
2283 def setUpClass(cls):
2284 super(NeighborFlush, cls).setUpClass()
2285
2286 @classmethod
2287 def tearDownClass(cls):
2288 super(NeighborFlush, cls).tearDownClass()
2289
2290 def setUp(self):
2291 super(NeighborFlush, self).setUp()
2292
2293 self.create_pg_interfaces(range(2))
2294
2295 for i in self.pg_interfaces:
2296 i.admin_up()
2297 i.config_ip4()
2298 i.config_ip6()
2299 i.resolve_arp()
2300 i.resolve_ndp()
2301
2302 def tearDown(self):
2303 super(NeighborFlush, self).tearDown()
2304
2305 for i in self.pg_interfaces:
2306 i.unconfig_ip4()
2307 i.unconfig_ip6()
2308 i.admin_down()
2309
2310 def test_flush(self):
2311 """ Neighbour Flush """
2312
2313 e = VppEnum
2314 nf = e.vl_api_ip_neighbor_flags_t
2315 af = e.vl_api_address_family_t
2316 N_HOSTS = 16
2317 static = [False, True]
2318 self.pg0.generate_remote_hosts(N_HOSTS)
2319 self.pg1.generate_remote_hosts(N_HOSTS)
2320
2321 for s in static:
2322 # a few v4 and v6 dynamic neoghbors
2323 for n in range(N_HOSTS):
2324 VppNeighbor(self,
2325 self.pg0.sw_if_index,
2326 self.pg0.remote_hosts[n].mac,
2327 self.pg0.remote_hosts[n].ip4,
2328 is_static=s).add_vpp_config()
2329 VppNeighbor(self,
2330 self.pg1.sw_if_index,
2331 self.pg1.remote_hosts[n].mac,
2332 self.pg1.remote_hosts[n].ip6,
2333 is_static=s).add_vpp_config()
2334
2335 # flush the interfaces individually
2336 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2337
2338 # check we haven't flushed that which we shouldn't
2339 for n in range(N_HOSTS):
2340 self.assertTrue(find_nbr(self,
2341 self.pg1.sw_if_index,
2342 self.pg1.remote_hosts[n].ip6,
2343 is_static=s))
2344
2345 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2346
2347 for n in range(N_HOSTS):
2348 self.assertFalse(find_nbr(self,
2349 self.pg0.sw_if_index,
2350 self.pg0.remote_hosts[n].ip4))
2351 self.assertFalse(find_nbr(self,
2352 self.pg1.sw_if_index,
2353 self.pg1.remote_hosts[n].ip6))
2354
2355 # add the nieghbours back
2356 for n in range(N_HOSTS):
2357 VppNeighbor(self,
2358 self.pg0.sw_if_index,
2359 self.pg0.remote_hosts[n].mac,
2360 self.pg0.remote_hosts[n].ip4,
2361 is_static=s).add_vpp_config()
2362 VppNeighbor(self,
2363 self.pg1.sw_if_index,
2364 self.pg1.remote_hosts[n].mac,
2365 self.pg1.remote_hosts[n].ip6,
2366 is_static=s).add_vpp_config()
2367
2368 self.logger.info(self.vapi.cli("sh ip neighbor"))
2369
2370 # flush both interfaces at the same time
2371 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2372
2373 # check we haven't flushed that which we shouldn't
2374 for n in range(N_HOSTS):
2375 self.assertTrue(find_nbr(self,
2376 self.pg0.sw_if_index,
2377 self.pg0.remote_hosts[n].ip4,
2378 is_static=s))
2379
2380 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2381
2382 for n in range(N_HOSTS):
2383 self.assertFalse(find_nbr(self,
2384 self.pg0.sw_if_index,
2385 self.pg0.remote_hosts[n].ip4))
2386 self.assertFalse(find_nbr(self,
2387 self.pg1.sw_if_index,
2388 self.pg1.remote_hosts[n].ip6))
2389
2390
Neale Ranns37be7362017-02-21 17:30:26 -08002391if __name__ == '__main__':
2392 unittest.main(testRunner=VppTestRunner)