blob: 0cbaf062f12a88bc347614c8908e29da1e318a1c [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
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00007from framework import tag_fixme_vpp_workers
Neale Ranns39f9d8b2017-02-16 21:57:05 -08008from framework import VppTestCase, VppTestRunner
9from vpp_neighbor import VppNeighbor, find_nbr
Neale Ranns15002542017-09-10 04:39:11 -070010from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
Neale Rannse2fe0972020-11-26 08:37:27 +000011 VppIpTable, DpoProto, FibPathType, VppIpInterfaceAddress
Neale Ranns37029302018-08-10 05:30:06 -070012from vpp_papi import VppEnum
Jakub Grajciar2df2f752020-12-01 11:23:44 +010013from vpp_ip import VppIpPuntRedirect
Neale Ranns39f9d8b2017-02-16 21:57:05 -080014
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070015import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080016from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070017from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000018from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070019from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080020from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070021from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080022
Paul Vinciguerra4271c972019-05-14 13:25:49 -040023
24NUM_PKTS = 67
25
Neale Ranns39f9d8b2017-02-16 21:57:05 -080026# not exported by scapy, so redefined here
27arp_opts = {"who-has": 1, "is-at": 2}
28
29
30class ARPTestCase(VppTestCase):
31 """ ARP Test Case """
32
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070033 @classmethod
34 def setUpClass(cls):
35 super(ARPTestCase, cls).setUpClass()
36
37 @classmethod
38 def tearDownClass(cls):
39 super(ARPTestCase, cls).tearDownClass()
40
Neale Ranns39f9d8b2017-02-16 21:57:05 -080041 def setUp(self):
42 super(ARPTestCase, self).setUp()
43
44 # create 3 pg interfaces
45 self.create_pg_interfaces(range(4))
46
47 # pg0 configured with ip4 and 6 addresses used for input
48 # pg1 configured with ip4 and 6 addresses used for output
49 # pg2 is unnumbered to pg0
50 for i in self.pg_interfaces:
51 i.admin_up()
52
53 self.pg0.config_ip4()
54 self.pg0.config_ip6()
55 self.pg0.resolve_arp()
56
57 self.pg1.config_ip4()
58 self.pg1.config_ip6()
59
60 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070061 self.tbl = VppIpTable(self, 1)
62 self.tbl.add_vpp_config()
63
Neale Ranns39f9d8b2017-02-16 21:57:05 -080064 self.pg3.set_table_ip4(1)
65 self.pg3.config_ip4()
66
Neale Ranns4008ac92017-02-13 23:20:04 -080067 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080068 self.pg0.unconfig_ip4()
69 self.pg0.unconfig_ip6()
70
71 self.pg1.unconfig_ip4()
72 self.pg1.unconfig_ip6()
73
74 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070075 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080076
Neale Ranns4008ac92017-02-13 23:20:04 -080077 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080078 i.admin_down()
79
Neale Ranns15002542017-09-10 04:39:11 -070080 super(ARPTestCase, self).tearDown()
81
Neale Ranns39f9d8b2017-02-16 21:57:05 -080082 def verify_arp_req(self, rx, smac, sip, dip):
83 ether = rx[Ether]
84 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
85 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +010086 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -080087
88 arp = rx[ARP]
89 self.assertEqual(arp.hwtype, 1)
90 self.assertEqual(arp.ptype, 0x800)
91 self.assertEqual(arp.hwlen, 6)
92 self.assertEqual(arp.plen, 4)
93 self.assertEqual(arp.op, arp_opts["who-has"])
94 self.assertEqual(arp.hwsrc, smac)
95 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
96 self.assertEqual(arp.psrc, sip)
97 self.assertEqual(arp.pdst, dip)
98
99 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
100 ether = rx[Ether]
101 self.assertEqual(ether.dst, dmac)
102 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100103 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800104
105 arp = rx[ARP]
106 self.assertEqual(arp.hwtype, 1)
107 self.assertEqual(arp.ptype, 0x800)
108 self.assertEqual(arp.hwlen, 6)
109 self.assertEqual(arp.plen, 4)
110 self.assertEqual(arp.op, arp_opts["is-at"])
111 self.assertEqual(arp.hwsrc, smac)
112 self.assertEqual(arp.hwdst, dmac)
113 self.assertEqual(arp.psrc, sip)
114 self.assertEqual(arp.pdst, dip)
115
Matthew Smithcb9ab472017-05-16 21:35:56 -0500116 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
117 ether = rx[Ether]
118 self.assertEqual(ether.dst, dmac)
119 self.assertEqual(ether.src, smac)
120
121 arp = rx[ARP]
122 self.assertEqual(arp.hwtype, 1)
123 self.assertEqual(arp.ptype, 0x800)
124 self.assertEqual(arp.hwlen, 6)
125 self.assertEqual(arp.plen, 4)
126 self.assertEqual(arp.op, arp_opts["is-at"])
127 self.assertNotEqual(arp.hwsrc, smac)
128 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
129 "00:00:5E:00:01" in arp.hwsrc)
130 self.assertEqual(arp.hwdst, dmac)
131 self.assertEqual(arp.psrc, sip)
132 self.assertEqual(arp.pdst, dip)
133
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800134 def verify_ip(self, rx, smac, dmac, sip, dip):
135 ether = rx[Ether]
136 self.assertEqual(ether.dst, dmac)
137 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100138 self.assertEqual(ether.type, 0x0800)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800139
140 ip = rx[IP]
141 self.assertEqual(ip.src, sip)
142 self.assertEqual(ip.dst, dip)
143
Neale Ranns37be7362017-02-21 17:30:26 -0800144 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
145 ether = rx[Ether]
146 self.assertEqual(ether.dst, dmac)
147 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100148 self.assertEqual(ether.type, 0x8847)
Neale Ranns37be7362017-02-21 17:30:26 -0800149
150 mpls = rx[MPLS]
151 self.assertTrue(mpls.label, label)
152
153 ip = rx[IP]
154 self.assertEqual(ip.src, sip)
155 self.assertEqual(ip.dst, dip)
156
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800157 def test_arp(self):
158 """ ARP """
159
160 #
161 # Generate some hosts on the LAN
162 #
Neale Rannsca193612017-06-14 06:50:08 -0700163 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800164
165 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000166 # watch for:
167 # - all neighbour events
168 # - all neighbor events on pg1
169 # - neighbor events for host[1] on pg1
170 #
171 self.vapi.want_ip_neighbor_events(enable=1,
172 pid=os.getpid())
173 self.vapi.want_ip_neighbor_events(enable=1,
174 pid=os.getpid(),
175 sw_if_index=self.pg1.sw_if_index)
176 self.vapi.want_ip_neighbor_events(enable=1,
177 pid=os.getpid(),
178 sw_if_index=self.pg1.sw_if_index,
179 ip=self.pg1.remote_hosts[1].ip4)
180
181 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
182
183 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800184 # Send IP traffic to one of these unresolved hosts.
185 # expect the generation of an ARP request
186 #
187 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
188 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
189 UDP(sport=1234, dport=1234) /
190 Raw())
191
192 self.pg0.add_stream(p)
193 self.pg_enable_capture(self.pg_interfaces)
194 self.pg_start()
195
196 rx = self.pg1.get_capture(1)
197
198 self.verify_arp_req(rx[0],
199 self.pg1.local_mac,
200 self.pg1.local_ip4,
201 self.pg1._remote_hosts[1].ip4)
202
203 #
204 # And a dynamic ARP entry for host 1
205 #
206 dyn_arp = VppNeighbor(self,
207 self.pg1.sw_if_index,
208 self.pg1.remote_hosts[1].mac,
209 self.pg1.remote_hosts[1].ip4)
210 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000211 self.assertTrue(dyn_arp.query_vpp_config())
212
Neale Rannsdc617b82020-08-20 08:22:56 +0000213 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
214
Neale Rannscbe25aa2019-09-30 10:53:31 +0000215 # this matches all of the listnerers
216 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
217 for i in range(3)]
218 for e in es:
219 self.assertEqual(str(e.neighbor.ip_address),
220 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800221
222 #
223 # now we expect IP traffic forwarded
224 #
225 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
226 IP(src=self.pg0.remote_ip4,
227 dst=self.pg1._remote_hosts[1].ip4) /
228 UDP(sport=1234, dport=1234) /
229 Raw())
230
231 self.pg0.add_stream(dyn_p)
232 self.pg_enable_capture(self.pg_interfaces)
233 self.pg_start()
234
235 rx = self.pg1.get_capture(1)
236
237 self.verify_ip(rx[0],
238 self.pg1.local_mac,
239 self.pg1.remote_hosts[1].mac,
240 self.pg0.remote_ip4,
241 self.pg1._remote_hosts[1].ip4)
242
243 #
244 # And a Static ARP entry for host 2
245 #
246 static_arp = VppNeighbor(self,
247 self.pg1.sw_if_index,
248 self.pg1.remote_hosts[2].mac,
249 self.pg1.remote_hosts[2].ip4,
250 is_static=1)
251 static_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000252 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
253 for i in range(2)]
254 for e in es:
255 self.assertEqual(str(e.neighbor.ip_address),
256 self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800257
258 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
259 IP(src=self.pg0.remote_ip4,
260 dst=self.pg1._remote_hosts[2].ip4) /
261 UDP(sport=1234, dport=1234) /
262 Raw())
263
264 self.pg0.add_stream(static_p)
265 self.pg_enable_capture(self.pg_interfaces)
266 self.pg_start()
267
268 rx = self.pg1.get_capture(1)
269
270 self.verify_ip(rx[0],
271 self.pg1.local_mac,
272 self.pg1.remote_hosts[2].mac,
273 self.pg0.remote_ip4,
274 self.pg1._remote_hosts[2].ip4)
275
276 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000277 # remove all the listeners
278 #
279 self.vapi.want_ip_neighbor_events(enable=0,
280 pid=os.getpid())
281 self.vapi.want_ip_neighbor_events(enable=0,
282 pid=os.getpid(),
283 sw_if_index=self.pg1.sw_if_index)
284 self.vapi.want_ip_neighbor_events(enable=0,
285 pid=os.getpid(),
286 sw_if_index=self.pg1.sw_if_index,
287 ip=self.pg1.remote_hosts[1].ip4)
288
289 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800290 # flap the link. dynamic ARPs get flush, statics don't
291 #
292 self.pg1.admin_down()
293 self.pg1.admin_up()
294
295 self.pg0.add_stream(static_p)
296 self.pg_enable_capture(self.pg_interfaces)
297 self.pg_start()
298 rx = self.pg1.get_capture(1)
299
300 self.verify_ip(rx[0],
301 self.pg1.local_mac,
302 self.pg1.remote_hosts[2].mac,
303 self.pg0.remote_ip4,
304 self.pg1._remote_hosts[2].ip4)
305
306 self.pg0.add_stream(dyn_p)
307 self.pg_enable_capture(self.pg_interfaces)
308 self.pg_start()
309
310 rx = self.pg1.get_capture(1)
311 self.verify_arp_req(rx[0],
312 self.pg1.local_mac,
313 self.pg1.local_ip4,
314 self.pg1._remote_hosts[1].ip4)
315
Neale Rannscbe25aa2019-09-30 10:53:31 +0000316 self.assertFalse(dyn_arp.query_vpp_config())
317 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800318 #
319 # Send an ARP request from one of the so-far unlearned remote hosts
320 #
321 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
322 src=self.pg1._remote_hosts[3].mac) /
323 ARP(op="who-has",
324 hwsrc=self.pg1._remote_hosts[3].mac,
325 pdst=self.pg1.local_ip4,
326 psrc=self.pg1._remote_hosts[3].ip4))
327
328 self.pg1.add_stream(p)
329 self.pg_enable_capture(self.pg_interfaces)
330 self.pg_start()
331
332 rx = self.pg1.get_capture(1)
333 self.verify_arp_resp(rx[0],
334 self.pg1.local_mac,
335 self.pg1._remote_hosts[3].mac,
336 self.pg1.local_ip4,
337 self.pg1._remote_hosts[3].ip4)
338
339 #
340 # VPP should have learned the mapping for the remote host
341 #
342 self.assertTrue(find_nbr(self,
343 self.pg1.sw_if_index,
344 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800345 #
346 # Fire in an ARP request before the interface becomes IP enabled
347 #
348 self.pg2.generate_remote_hosts(4)
349
350 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
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 Ranns30d0fd42017-05-30 07:30:04 -0700355 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
356 Dot1Q(vlan=0) /
357 ARP(op="who-has",
358 hwsrc=self.pg2.remote_mac,
359 pdst=self.pg1.local_ip4,
360 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800361 self.send_and_assert_no_replies(self.pg2, p,
362 "interface not IP enabled")
363
364 #
365 # Make pg2 un-numbered to pg1
366 #
367 self.pg2.set_unnumbered(self.pg1.sw_if_index)
368
Neale Rannsac3e72c2019-10-06 01:04:26 -0700369 #
370 # test the unnumbered dump both by all interfaces and just the enabled
371 # one
372 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700373 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700374 self.assertTrue(len(unnum))
375 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
376 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
377 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
378 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700379 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
380 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
381
Neale Ranns4b919a52017-03-11 05:55:21 -0800382 #
383 # We should respond to ARP requests for the unnumbered to address
384 # once an attached route to the source is known
385 #
386 self.send_and_assert_no_replies(
387 self.pg2, p,
388 "ARP req for unnumbered address - no source")
389
390 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
391 [VppRoutePath("0.0.0.0",
392 self.pg2.sw_if_index)])
393 attached_host.add_vpp_config()
394
395 self.pg2.add_stream(p)
396 self.pg_enable_capture(self.pg_interfaces)
397 self.pg_start()
398
399 rx = self.pg2.get_capture(1)
400 self.verify_arp_resp(rx[0],
401 self.pg2.local_mac,
402 self.pg2.remote_mac,
403 self.pg1.local_ip4,
404 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800405
Neale Ranns30d0fd42017-05-30 07:30:04 -0700406 self.pg2.add_stream(pt)
407 self.pg_enable_capture(self.pg_interfaces)
408 self.pg_start()
409
410 rx = self.pg2.get_capture(1)
411 self.verify_arp_resp(rx[0],
412 self.pg2.local_mac,
413 self.pg2.remote_mac,
414 self.pg1.local_ip4,
415 self.pg2.remote_hosts[3].ip4)
416
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800417 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800418 # A neighbor entry that has no associated FIB-entry
419 #
420 arp_no_fib = VppNeighbor(self,
421 self.pg1.sw_if_index,
422 self.pg1.remote_hosts[4].mac,
423 self.pg1.remote_hosts[4].ip4,
424 is_no_fib_entry=1)
425 arp_no_fib.add_vpp_config()
426
427 #
428 # check we have the neighbor, but no route
429 #
430 self.assertTrue(find_nbr(self,
431 self.pg1.sw_if_index,
432 self.pg1._remote_hosts[4].ip4))
433 self.assertFalse(find_route(self,
434 self.pg1._remote_hosts[4].ip4,
435 32))
436 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800437 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
438 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800439 #
440 arp_unnum = VppNeighbor(self,
441 self.pg2.sw_if_index,
442 self.pg1.remote_hosts[5].mac,
443 self.pg1.remote_hosts[5].ip4)
444 arp_unnum.add_vpp_config()
445
446 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
447 IP(src=self.pg0.remote_ip4,
448 dst=self.pg1._remote_hosts[5].ip4) /
449 UDP(sport=1234, dport=1234) /
450 Raw())
451
452 self.pg0.add_stream(p)
453 self.pg_enable_capture(self.pg_interfaces)
454 self.pg_start()
455
456 rx = self.pg2.get_capture(1)
457
458 self.verify_ip(rx[0],
459 self.pg2.local_mac,
460 self.pg1.remote_hosts[5].mac,
461 self.pg0.remote_ip4,
462 self.pg1._remote_hosts[5].ip4)
463
464 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800465 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
466 # with the unnumbered interface's address as the source
467 #
468 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
469 ARP(op="who-has",
470 hwsrc=self.pg2.remote_mac,
471 pdst=self.pg1.local_ip4,
472 psrc=self.pg1.remote_hosts[6].ip4))
473
474 self.pg2.add_stream(p)
475 self.pg_enable_capture(self.pg_interfaces)
476 self.pg_start()
477
478 rx = self.pg2.get_capture(1)
479 self.verify_arp_resp(rx[0],
480 self.pg2.local_mac,
481 self.pg2.remote_mac,
482 self.pg1.local_ip4,
483 self.pg1.remote_hosts[6].ip4)
484
485 #
486 # An attached host route out of pg2 for an undiscovered hosts generates
487 # an ARP request with the unnumbered address as the source
488 #
489 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
490 [VppRoutePath("0.0.0.0",
491 self.pg2.sw_if_index)])
492 att_unnum.add_vpp_config()
493
494 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
495 IP(src=self.pg0.remote_ip4,
496 dst=self.pg1._remote_hosts[7].ip4) /
497 UDP(sport=1234, dport=1234) /
498 Raw())
499
500 self.pg0.add_stream(p)
501 self.pg_enable_capture(self.pg_interfaces)
502 self.pg_start()
503
504 rx = self.pg2.get_capture(1)
505
506 self.verify_arp_req(rx[0],
507 self.pg2.local_mac,
508 self.pg1.local_ip4,
509 self.pg1._remote_hosts[7].ip4)
510
511 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
512 ARP(op="who-has",
513 hwsrc=self.pg2.remote_mac,
514 pdst=self.pg1.local_ip4,
515 psrc=self.pg1.remote_hosts[7].ip4))
516
517 self.pg2.add_stream(p)
518 self.pg_enable_capture(self.pg_interfaces)
519 self.pg_start()
520
521 rx = self.pg2.get_capture(1)
522 self.verify_arp_resp(rx[0],
523 self.pg2.local_mac,
524 self.pg2.remote_mac,
525 self.pg1.local_ip4,
526 self.pg1.remote_hosts[7].ip4)
527
528 #
529 # An attached host route as yet unresolved out of pg2 for an
530 # undiscovered host, an ARP requests begets a response.
531 #
532 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
533 [VppRoutePath("0.0.0.0",
534 self.pg2.sw_if_index)])
535 att_unnum1.add_vpp_config()
536
537 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
538 ARP(op="who-has",
539 hwsrc=self.pg2.remote_mac,
540 pdst=self.pg1.local_ip4,
541 psrc=self.pg1.remote_hosts[8].ip4))
542
543 self.pg2.add_stream(p)
544 self.pg_enable_capture(self.pg_interfaces)
545 self.pg_start()
546
547 rx = self.pg2.get_capture(1)
548 self.verify_arp_resp(rx[0],
549 self.pg2.local_mac,
550 self.pg2.remote_mac,
551 self.pg1.local_ip4,
552 self.pg1.remote_hosts[8].ip4)
553
554 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700555 # Send an ARP request from one of the so-far unlearned remote hosts
556 # with a VLAN0 tag
557 #
558 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
559 src=self.pg1._remote_hosts[9].mac) /
560 Dot1Q(vlan=0) /
561 ARP(op="who-has",
562 hwsrc=self.pg1._remote_hosts[9].mac,
563 pdst=self.pg1.local_ip4,
564 psrc=self.pg1._remote_hosts[9].ip4))
565
566 self.pg1.add_stream(p)
567 self.pg_enable_capture(self.pg_interfaces)
568 self.pg_start()
569
570 rx = self.pg1.get_capture(1)
571 self.verify_arp_resp(rx[0],
572 self.pg1.local_mac,
573 self.pg1._remote_hosts[9].mac,
574 self.pg1.local_ip4,
575 self.pg1._remote_hosts[9].ip4)
576
577 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700578 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700579 # Should still get an ARP resp since the cover is attached
580 #
581 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
582 ARP(op="who-has",
583 hwsrc=self.pg1.remote_mac,
584 pdst=self.pg1.local_ip4,
585 psrc=self.pg1.remote_hosts[10].ip4))
586
587 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
588 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
589 self.pg1.sw_if_index)])
590 r1.add_vpp_config()
591
592 self.pg1.add_stream(p)
593 self.pg_enable_capture(self.pg_interfaces)
594 self.pg_start()
595 rx = self.pg1.get_capture(1)
596 self.verify_arp_resp(rx[0],
597 self.pg1.local_mac,
598 self.pg1.remote_mac,
599 self.pg1.local_ip4,
600 self.pg1.remote_hosts[10].ip4)
601
602 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
603 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
604 self.pg1.sw_if_index)])
605 r2.add_vpp_config()
606
607 self.pg1.add_stream(p)
608 self.pg_enable_capture(self.pg_interfaces)
609 self.pg_start()
610 rx = self.pg1.get_capture(1)
611 self.verify_arp_resp(rx[0],
612 self.pg1.local_mac,
613 self.pg1.remote_mac,
614 self.pg1.local_ip4,
615 self.pg1.remote_hosts[10].ip4)
616
617 #
618 # add an ARP entry that's not on the sub-net and so whose
619 # adj-fib fails the refinement check. then send an ARP request
620 # from that source
621 #
622 a1 = VppNeighbor(self,
623 self.pg0.sw_if_index,
624 self.pg0.remote_mac,
625 "100.100.100.50")
626 a1.add_vpp_config()
627
628 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
629 ARP(op="who-has",
630 hwsrc=self.pg0.remote_mac,
631 psrc="100.100.100.50",
632 pdst=self.pg0.remote_ip4))
633 self.send_and_assert_no_replies(self.pg0, p,
634 "ARP req for from failed adj-fib")
635
636 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800637 # ERROR Cases
638 # 1 - don't respond to ARP request for address not within the
639 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700640 # 1b - nor within the unnumbered subnet
641 # 1c - nor within the subnet of a different interface
642 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800643 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
644 ARP(op="who-has",
645 hwsrc=self.pg0.remote_mac,
646 pdst="10.10.10.3",
647 psrc=self.pg0.remote_ip4))
648 self.send_and_assert_no_replies(self.pg0, p,
649 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700650 self.assertFalse(find_nbr(self,
651 self.pg0.sw_if_index,
652 "10.10.10.3"))
653
Neale Ranns4b919a52017-03-11 05:55:21 -0800654 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
655 ARP(op="who-has",
656 hwsrc=self.pg2.remote_mac,
657 pdst="10.10.10.3",
658 psrc=self.pg1.remote_hosts[7].ip4))
659 self.send_and_assert_no_replies(
660 self.pg0, p,
661 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800662
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700663 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
664 ARP(op="who-has",
665 hwsrc=self.pg0.remote_mac,
666 pdst=self.pg1.local_ip4,
667 psrc=self.pg1.remote_ip4))
668 self.send_and_assert_no_replies(self.pg0, p,
669 "ARP req diff sub-net")
670 self.assertFalse(find_nbr(self,
671 self.pg0.sw_if_index,
672 self.pg1.remote_ip4))
673
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800674 #
675 # 2 - don't respond to ARP request from an address not within the
676 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700677 # 2b - to a proxied address
678 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800679 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
680 ARP(op="who-has",
681 hwsrc=self.pg0.remote_mac,
682 psrc="10.10.10.3",
683 pdst=self.pg0.local_ip4))
684 self.send_and_assert_no_replies(self.pg0, p,
685 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800686 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
687 ARP(op="who-has",
688 hwsrc=self.pg2.remote_mac,
689 psrc="10.10.10.3",
690 pdst=self.pg0.local_ip4))
691 self.send_and_assert_no_replies(
692 self.pg0, p,
693 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700694 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
695 ARP(op="who-has",
696 hwsrc=self.pg0.remote_mac,
697 psrc=self.pg1.remote_ip4,
698 pdst=self.pg0.local_ip4))
699 self.send_and_assert_no_replies(self.pg0, p,
700 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800701
702 #
703 # 3 - don't respond to ARP request from an address that belongs to
704 # the router
705 #
706 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
707 ARP(op="who-has",
708 hwsrc=self.pg0.remote_mac,
709 psrc=self.pg0.local_ip4,
710 pdst=self.pg0.local_ip4))
711 self.send_and_assert_no_replies(self.pg0, p,
712 "ARP req for non-local source")
713
714 #
715 # 4 - don't respond to ARP requests that has mac source different
716 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800717 #
718 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
719 ARP(op="who-has",
720 hwsrc="00:00:00:DE:AD:BE",
721 psrc=self.pg0.remote_ip4,
722 pdst=self.pg0.local_ip4))
723 self.send_and_assert_no_replies(self.pg0, p,
724 "ARP req for non-local source")
725
726 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800727 # 5 - don't respond to ARP requests for address within the
728 # interface's sub-net but not the interface's address
729 #
730 self.pg0.generate_remote_hosts(2)
731 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
732 ARP(op="who-has",
733 hwsrc=self.pg0.remote_mac,
734 psrc=self.pg0.remote_hosts[0].ip4,
735 pdst=self.pg0.remote_hosts[1].ip4))
736 self.send_and_assert_no_replies(self.pg0, p,
737 "ARP req for non-local destination")
738
739 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800740 # cleanup
741 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800742 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800743 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800744
Neale Ranns4b919a52017-03-11 05:55:21 -0800745 # need this to flush the adj-fibs
746 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
747 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700748 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800749
Neale Ranns24b170a2017-08-15 05:33:11 -0700750 def test_proxy_mirror_arp(self):
751 """ Interface Mirror Proxy ARP """
752
753 #
754 # When VPP has an interface whose address is also applied to a TAP
755 # interface on the host, then VPP's TAP interface will be unnumbered
756 # to the 'real' interface and do proxy ARP from the host.
757 # the curious aspect of this setup is that ARP requests from the host
758 # will come from the VPP's own address.
759 #
760 self.pg0.generate_remote_hosts(2)
761
762 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
763 dst="ff:ff:ff:ff:ff:ff") /
764 ARP(op="who-has",
765 hwsrc=self.pg2.remote_mac,
766 pdst=self.pg0.remote_hosts[1].ip4,
767 psrc=self.pg0.local_ip4))
768
769 #
770 # Configure Proxy ARP for the subnet on PG0addresses on pg0
771 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100772 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
773 'low': self.pg0._local_ip4_subnet,
774 'hi': self.pg0._local_ip4_bcast},
775 is_add=1)
Neale Ranns24b170a2017-08-15 05:33:11 -0700776
777 # Make pg2 un-numbered to pg0
778 #
779 self.pg2.set_unnumbered(self.pg0.sw_if_index)
780
781 #
782 # Enable pg2 for proxy ARP
783 #
784 self.pg2.set_proxy_arp()
785
786 #
787 # Send the ARP request with an originating address that
788 # is VPP's own address
789 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000790 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Neale Ranns24b170a2017-08-15 05:33:11 -0700791 self.verify_arp_resp(rx[0],
792 self.pg2.local_mac,
793 self.pg2.remote_mac,
794 self.pg0.remote_hosts[1].ip4,
795 self.pg0.local_ip4)
796
797 #
798 # validate we have not learned an ARP entry as a result of this
799 #
800 self.assertFalse(find_nbr(self,
801 self.pg2.sw_if_index,
802 self.pg0.local_ip4))
803
804 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000805 # setup a punt redirect so packets from the uplink go to the tap
806 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100807 redirect = VppIpPuntRedirect(self, self.pg0.sw_if_index,
808 self.pg2.sw_if_index, self.pg0.local_ip4)
809 redirect.add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +0000810
811 p_tcp = (Ether(src=self.pg0.remote_mac,
812 dst=self.pg0.local_mac,) /
813 IP(src=self.pg0.remote_ip4,
814 dst=self.pg0.local_ip4) /
815 TCP(sport=80, dport=80) /
816 Raw())
817 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
818
819 # there's no ARP entry so this is an ARP req
820 self.assertTrue(rx[0].haslayer(ARP))
821
822 # and ARP entry for VPP's pg0 address on the host interface
823 n1 = VppNeighbor(self,
824 self.pg2.sw_if_index,
825 self.pg2.remote_mac,
826 self.pg0.local_ip4,
827 is_no_fib_entry=True).add_vpp_config()
828 # now the packets shold forward
829 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
830 self.assertFalse(rx[0].haslayer(ARP))
831 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
832
833 #
834 # flush the neighbor cache on the uplink
835 #
836 af = VppEnum.vl_api_address_family_t
837 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
838
839 # ensure we can still resolve the ARPs on the uplink
840 self.pg0.resolve_arp()
841
842 self.assertTrue(find_nbr(self,
843 self.pg0.sw_if_index,
844 self.pg0.remote_ip4))
845
846 #
Neale Ranns24b170a2017-08-15 05:33:11 -0700847 # cleanup
848 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100849 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
850 'low': self.pg0._local_ip4_subnet,
851 'hi': self.pg0._local_ip4_bcast},
Neale Ranns24b170a2017-08-15 05:33:11 -0700852 is_add=0)
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100853 redirect.remove_vpp_config()
Neale Ranns24b170a2017-08-15 05:33:11 -0700854
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800855 def test_proxy_arp(self):
856 """ Proxy ARP """
857
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700858 self.pg1.generate_remote_hosts(2)
859
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800860 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700861 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800862 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800863 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
864 dst="ff:ff:ff:ff:ff:ff") /
865 ARP(op="who-has",
866 hwsrc=self.pg0.remote_mac,
867 pdst="10.10.10.3",
868 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700869 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
870 dst="ff:ff:ff:ff:ff:ff") /
871 Dot1Q(vlan=0) /
872 ARP(op="who-has",
873 hwsrc=self.pg0.remote_mac,
874 pdst="10.10.10.3",
875 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800876 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
877 dst="ff:ff:ff:ff:ff:ff") /
878 ARP(op="who-has",
879 hwsrc=self.pg1.remote_mac,
880 pdst="10.10.10.3",
881 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700882 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
883 dst="ff:ff:ff:ff:ff:ff") /
884 ARP(op="who-has",
885 hwsrc=self.pg2.remote_mac,
886 pdst="10.10.10.3",
887 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800888 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
889 dst="ff:ff:ff:ff:ff:ff") /
890 ARP(op="who-has",
891 hwsrc=self.pg3.remote_mac,
892 pdst="10.10.10.3",
893 psrc=self.pg3.remote_ip4))
894
895 #
896 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
897 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100898 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
899 'low': "10.10.10.2",
900 'hi': "10.10.10.124"},
901 is_add=1)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800902
903 #
904 # No responses are sent when the interfaces are not enabled for proxy
905 # ARP
906 #
907 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
908 "ARP req from unconfigured interface")
909 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
910 "ARP req from unconfigured interface")
911
912 #
913 # Make pg2 un-numbered to pg1
914 # still won't reply.
915 #
916 self.pg2.set_unnumbered(self.pg1.sw_if_index)
917
918 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
919 "ARP req from unnumbered interface")
920
921 #
922 # Enable each interface to reply to proxy ARPs
923 #
924 for i in self.pg_interfaces:
925 i.set_proxy_arp()
926
927 #
928 # Now each of the interfaces should reply to a request to a proxied
929 # address
930 #
931 self.pg0.add_stream(arp_req_pg0)
932 self.pg_enable_capture(self.pg_interfaces)
933 self.pg_start()
934
935 rx = self.pg0.get_capture(1)
936 self.verify_arp_resp(rx[0],
937 self.pg0.local_mac,
938 self.pg0.remote_mac,
939 "10.10.10.3",
940 self.pg0.remote_ip4)
941
Neale Ranns30d0fd42017-05-30 07:30:04 -0700942 self.pg0.add_stream(arp_req_pg0_tagged)
943 self.pg_enable_capture(self.pg_interfaces)
944 self.pg_start()
945
946 rx = self.pg0.get_capture(1)
947 self.verify_arp_resp(rx[0],
948 self.pg0.local_mac,
949 self.pg0.remote_mac,
950 "10.10.10.3",
951 self.pg0.remote_ip4)
952
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800953 self.pg1.add_stream(arp_req_pg1)
954 self.pg_enable_capture(self.pg_interfaces)
955 self.pg_start()
956
957 rx = self.pg1.get_capture(1)
958 self.verify_arp_resp(rx[0],
959 self.pg1.local_mac,
960 self.pg1.remote_mac,
961 "10.10.10.3",
962 self.pg1.remote_ip4)
963
964 self.pg2.add_stream(arp_req_pg2)
965 self.pg_enable_capture(self.pg_interfaces)
966 self.pg_start()
967
968 rx = self.pg2.get_capture(1)
969 self.verify_arp_resp(rx[0],
970 self.pg2.local_mac,
971 self.pg2.remote_mac,
972 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700973 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800974
975 #
976 # A request for an address out of the configured range
977 #
978 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
979 dst="ff:ff:ff:ff:ff:ff") /
980 ARP(op="who-has",
981 hwsrc=self.pg1.remote_mac,
982 pdst="10.10.10.125",
983 psrc=self.pg1.remote_ip4))
984 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
985 "ARP req out of range HI")
986 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
987 dst="ff:ff:ff:ff:ff:ff") /
988 ARP(op="who-has",
989 hwsrc=self.pg1.remote_mac,
990 pdst="10.10.10.1",
991 psrc=self.pg1.remote_ip4))
992 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
993 "ARP req out of range Low")
994
995 #
996 # Request for an address in the proxy range but from an interface
997 # in a different VRF
998 #
999 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
1000 "ARP req from different VRF")
1001
1002 #
1003 # Disable Each interface for proxy ARP
1004 # - expect none to respond
1005 #
1006 for i in self.pg_interfaces:
1007 i.set_proxy_arp(0)
1008
1009 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
1010 "ARP req from disable")
1011 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
1012 "ARP req from disable")
1013 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
1014 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001015
1016 #
1017 # clean up on interface 2
1018 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001019 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001020
1021 def test_mpls(self):
1022 """ MPLS """
1023
1024 #
1025 # Interface 2 does not yet have ip4 config
1026 #
1027 self.pg2.config_ip4()
1028 self.pg2.generate_remote_hosts(2)
1029
1030 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001031 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001032 #
1033 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1034 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
1035 self.pg2.sw_if_index,
1036 labels=[55])])
1037 ip_10_0_0_1.add_vpp_config()
1038
1039 #
1040 # packets should generate an ARP request
1041 #
1042 p = (Ether(src=self.pg0.remote_mac,
1043 dst=self.pg0.local_mac) /
1044 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
1045 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001046 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -08001047
1048 self.pg0.add_stream(p)
1049 self.pg_enable_capture(self.pg_interfaces)
1050 self.pg_start()
1051
1052 rx = self.pg2.get_capture(1)
1053 self.verify_arp_req(rx[0],
1054 self.pg2.local_mac,
1055 self.pg2.local_ip4,
1056 self.pg2._remote_hosts[1].ip4)
1057
1058 #
1059 # now resolve the neighbours
1060 #
1061 self.pg2.configure_ipv4_neighbors()
1062
1063 #
1064 # Now packet should be properly MPLS encapped.
1065 # This verifies that MPLS link-type adjacencies are completed
1066 # when the ARP entry resolves
1067 #
1068 self.pg0.add_stream(p)
1069 self.pg_enable_capture(self.pg_interfaces)
1070 self.pg_start()
1071
1072 rx = self.pg2.get_capture(1)
1073 self.verify_ip_o_mpls(rx[0],
1074 self.pg2.local_mac,
1075 self.pg2.remote_hosts[1].mac,
1076 55,
1077 self.pg0.remote_ip4,
1078 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -08001079 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001080
Matthew Smithcb9ab472017-05-16 21:35:56 -05001081 def test_arp_vrrp(self):
1082 """ ARP reply with VRRP virtual src hw addr """
1083
1084 #
1085 # IP packet destined for pg1 remote host arrives on pg0 resulting
1086 # in an ARP request for the address of the remote host on pg1
1087 #
1088 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1089 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1090 UDP(sport=1234, dport=1234) /
1091 Raw())
1092
Neale Ranns37029302018-08-10 05:30:06 -07001093 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001094
1095 self.verify_arp_req(rx1[0],
1096 self.pg1.local_mac,
1097 self.pg1.local_ip4,
1098 self.pg1.remote_ip4)
1099
1100 #
1101 # ARP reply for address of pg1 remote host arrives on pg1 with
1102 # the hw src addr set to a value in the VRRP IPv4 range of
1103 # MAC addresses
1104 #
1105 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1106 ARP(op="is-at", hwdst=self.pg1.local_mac,
1107 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1108 psrc=self.pg1.remote_ip4))
1109
Neale Ranns37029302018-08-10 05:30:06 -07001110 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001111
1112 #
1113 # IP packet destined for pg1 remote host arrives on pg0 again.
1114 # VPP should have an ARP entry for that address now and the packet
1115 # should be sent out pg1.
1116 #
Neale Ranns37029302018-08-10 05:30:06 -07001117 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001118
1119 self.verify_ip(rx1[0],
1120 self.pg1.local_mac,
1121 "00:00:5e:00:01:09",
1122 self.pg0.remote_ip4,
1123 self.pg1.remote_ip4)
1124
1125 self.pg1.admin_down()
1126 self.pg1.admin_up()
1127
Neale Rannsdcd6d622017-05-26 02:59:16 -07001128 def test_arp_duplicates(self):
1129 """ ARP Duplicates"""
1130
1131 #
1132 # Generate some hosts on the LAN
1133 #
1134 self.pg1.generate_remote_hosts(3)
1135
1136 #
1137 # Add host 1 on pg1 and pg2
1138 #
1139 arp_pg1 = VppNeighbor(self,
1140 self.pg1.sw_if_index,
1141 self.pg1.remote_hosts[1].mac,
1142 self.pg1.remote_hosts[1].ip4)
1143 arp_pg1.add_vpp_config()
1144 arp_pg2 = VppNeighbor(self,
1145 self.pg2.sw_if_index,
1146 self.pg2.remote_mac,
1147 self.pg1.remote_hosts[1].ip4)
1148 arp_pg2.add_vpp_config()
1149
1150 #
1151 # IP packet destined for pg1 remote host arrives on pg1 again.
1152 #
1153 p = (Ether(dst=self.pg0.local_mac,
1154 src=self.pg0.remote_mac) /
1155 IP(src=self.pg0.remote_ip4,
1156 dst=self.pg1.remote_hosts[1].ip4) /
1157 UDP(sport=1234, dport=1234) /
1158 Raw())
1159
1160 self.pg0.add_stream(p)
1161 self.pg_enable_capture(self.pg_interfaces)
1162 self.pg_start()
1163
1164 rx1 = self.pg1.get_capture(1)
1165
1166 self.verify_ip(rx1[0],
1167 self.pg1.local_mac,
1168 self.pg1.remote_hosts[1].mac,
1169 self.pg0.remote_ip4,
1170 self.pg1.remote_hosts[1].ip4)
1171
1172 #
1173 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001174 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001175 #
1176 arp_pg1.remove_vpp_config()
1177
1178 self.pg0.add_stream(p)
1179 self.pg_enable_capture(self.pg_interfaces)
1180 self.pg_start()
1181
1182 rx1 = self.pg1.get_capture(1)
1183
1184 self.verify_arp_req(rx1[0],
1185 self.pg1.local_mac,
1186 self.pg1.local_ip4,
1187 self.pg1.remote_hosts[1].ip4)
1188
1189 #
1190 # Add it back
1191 #
1192 arp_pg1.add_vpp_config()
1193
1194 self.pg0.add_stream(p)
1195 self.pg_enable_capture(self.pg_interfaces)
1196 self.pg_start()
1197
1198 rx1 = self.pg1.get_capture(1)
1199
1200 self.verify_ip(rx1[0],
1201 self.pg1.local_mac,
1202 self.pg1.remote_hosts[1].mac,
1203 self.pg0.remote_ip4,
1204 self.pg1.remote_hosts[1].ip4)
1205
Neale Ranns15002542017-09-10 04:39:11 -07001206 def test_arp_static(self):
1207 """ ARP Static"""
1208 self.pg2.generate_remote_hosts(3)
1209
1210 #
1211 # Add a static ARP entry
1212 #
1213 static_arp = VppNeighbor(self,
1214 self.pg2.sw_if_index,
1215 self.pg2.remote_hosts[1].mac,
1216 self.pg2.remote_hosts[1].ip4,
1217 is_static=1)
1218 static_arp.add_vpp_config()
1219
1220 #
1221 # Add the connected prefix to the interface
1222 #
1223 self.pg2.config_ip4()
1224
1225 #
1226 # We should now find the adj-fib
1227 #
1228 self.assertTrue(find_nbr(self,
1229 self.pg2.sw_if_index,
1230 self.pg2.remote_hosts[1].ip4,
1231 is_static=1))
1232 self.assertTrue(find_route(self,
1233 self.pg2.remote_hosts[1].ip4,
1234 32))
1235
1236 #
1237 # remove the connected
1238 #
1239 self.pg2.unconfig_ip4()
1240
1241 #
1242 # put the interface into table 1
1243 #
1244 self.pg2.set_table_ip4(1)
1245
1246 #
1247 # configure the same connected and expect to find the
1248 # adj fib in the new table
1249 #
1250 self.pg2.config_ip4()
1251 self.assertTrue(find_route(self,
1252 self.pg2.remote_hosts[1].ip4,
1253 32,
1254 table_id=1))
1255
1256 #
1257 # clean-up
1258 #
1259 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001260 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001261 self.pg2.set_table_ip4(0)
1262
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001263 def test_arp_static_replace_dynamic_same_mac(self):
1264 """ ARP Static can replace Dynamic (same mac) """
1265 self.pg2.generate_remote_hosts(1)
1266
1267 dyn_arp = VppNeighbor(self,
1268 self.pg2.sw_if_index,
1269 self.pg2.remote_hosts[0].mac,
1270 self.pg2.remote_hosts[0].ip4)
1271 static_arp = VppNeighbor(self,
1272 self.pg2.sw_if_index,
1273 self.pg2.remote_hosts[0].mac,
1274 self.pg2.remote_hosts[0].ip4,
1275 is_static=1)
1276
1277 #
1278 # Add a dynamic ARP entry
1279 #
1280 dyn_arp.add_vpp_config()
1281
1282 #
1283 # We should find the dynamic nbr
1284 #
1285 self.assertFalse(find_nbr(self,
1286 self.pg2.sw_if_index,
1287 self.pg2.remote_hosts[0].ip4,
1288 is_static=1))
1289 self.assertTrue(find_nbr(self,
1290 self.pg2.sw_if_index,
1291 self.pg2.remote_hosts[0].ip4,
1292 is_static=0,
1293 mac=self.pg2.remote_hosts[0].mac))
1294
1295 #
1296 # Add a static ARP entry with the same mac
1297 #
1298 static_arp.add_vpp_config()
1299
1300 #
1301 # We should now find the static nbr with the same mac
1302 #
1303 self.assertFalse(find_nbr(self,
1304 self.pg2.sw_if_index,
1305 self.pg2.remote_hosts[0].ip4,
1306 is_static=0))
1307 self.assertTrue(find_nbr(self,
1308 self.pg2.sw_if_index,
1309 self.pg2.remote_hosts[0].ip4,
1310 is_static=1,
1311 mac=self.pg2.remote_hosts[0].mac))
1312
1313 #
1314 # clean-up
1315 #
1316 static_arp.remove_vpp_config()
1317
1318 def test_arp_static_replace_dynamic_diff_mac(self):
1319 """ ARP Static can replace Dynamic (diff mac) """
1320 self.pg2.generate_remote_hosts(2)
1321
1322 dyn_arp = VppNeighbor(self,
1323 self.pg2.sw_if_index,
1324 self.pg2.remote_hosts[0].mac,
1325 self.pg2.remote_hosts[0].ip4)
1326 static_arp = VppNeighbor(self,
1327 self.pg2.sw_if_index,
1328 self.pg2.remote_hosts[1].mac,
1329 self.pg2.remote_hosts[0].ip4,
1330 is_static=1)
1331
1332 #
1333 # Add a dynamic ARP entry
1334 #
1335 dyn_arp.add_vpp_config()
1336
1337 #
1338 # We should find the dynamic nbr
1339 #
1340 self.assertFalse(find_nbr(self,
1341 self.pg2.sw_if_index,
1342 self.pg2.remote_hosts[0].ip4,
1343 is_static=1))
1344 self.assertTrue(find_nbr(self,
1345 self.pg2.sw_if_index,
1346 self.pg2.remote_hosts[0].ip4,
1347 is_static=0,
1348 mac=self.pg2.remote_hosts[0].mac))
1349
1350 #
1351 # Add a static ARP entry with a changed mac
1352 #
1353 static_arp.add_vpp_config()
1354
1355 #
1356 # We should now find the static nbr with a changed mac
1357 #
1358 self.assertFalse(find_nbr(self,
1359 self.pg2.sw_if_index,
1360 self.pg2.remote_hosts[0].ip4,
1361 is_static=0))
1362 self.assertTrue(find_nbr(self,
1363 self.pg2.sw_if_index,
1364 self.pg2.remote_hosts[0].ip4,
1365 is_static=1,
1366 mac=self.pg2.remote_hosts[1].mac))
1367
1368 #
1369 # clean-up
1370 #
1371 static_arp.remove_vpp_config()
1372
Neale Rannsc819fc62018-02-16 02:44:05 -08001373 def test_arp_incomplete(self):
1374 """ ARP Incomplete"""
Neale Rannsea8adf72021-08-13 08:10:59 +00001375 self.pg1.generate_remote_hosts(4)
Neale Rannsc819fc62018-02-16 02:44:05 -08001376
1377 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1378 IP(src=self.pg0.remote_ip4,
1379 dst=self.pg1.remote_hosts[1].ip4) /
1380 UDP(sport=1234, dport=1234) /
1381 Raw())
1382 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1383 IP(src=self.pg0.remote_ip4,
1384 dst=self.pg1.remote_hosts[2].ip4) /
1385 UDP(sport=1234, dport=1234) /
1386 Raw())
Neale Rannsea8adf72021-08-13 08:10:59 +00001387 p2 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1388 IP(src=self.pg0.remote_ip4,
1389 dst="1.1.1.1") /
1390 UDP(sport=1234, dport=1234) /
1391 Raw())
Neale Rannsc819fc62018-02-16 02:44:05 -08001392
1393 #
1394 # a packet to an unresolved destination generates an ARP request
1395 #
1396 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1397 self.verify_arp_req(rx[0],
1398 self.pg1.local_mac,
1399 self.pg1.local_ip4,
1400 self.pg1._remote_hosts[1].ip4)
1401
1402 #
1403 # add a neighbour for remote host 1
1404 #
1405 static_arp = VppNeighbor(self,
1406 self.pg1.sw_if_index,
1407 self.pg1.remote_hosts[1].mac,
1408 self.pg1.remote_hosts[1].ip4,
1409 is_static=1)
1410 static_arp.add_vpp_config()
1411
1412 #
Neale Rannsea8adf72021-08-13 08:10:59 +00001413 # add a route through remote host 3 hence we get an incomplete
1414 #
1415 VppIpRoute(self, "1.1.1.1", 32,
1416 [VppRoutePath(self.pg1.remote_hosts[3].ip4,
1417 self.pg1.sw_if_index)]).add_vpp_config()
1418 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
1419 self.verify_arp_req(rx[0],
1420 self.pg1.local_mac,
1421 self.pg1.local_ip4,
1422 self.pg1._remote_hosts[3].ip4)
1423
1424 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001425 # change the interface's MAC
1426 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001427 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001428 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001429
1430 #
1431 # now ARP requests come from the new source mac
1432 #
1433 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1434 self.verify_arp_req(rx[0],
1435 "00:00:00:33:33:33",
1436 self.pg1.local_ip4,
1437 self.pg1._remote_hosts[2].ip4)
Neale Rannsea8adf72021-08-13 08:10:59 +00001438 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
1439 self.verify_arp_req(rx[0],
1440 "00:00:00:33:33:33",
1441 self.pg1.local_ip4,
1442 self.pg1._remote_hosts[3].ip4)
Neale Rannsc819fc62018-02-16 02:44:05 -08001443
1444 #
1445 # packets to the resolved host also have the new source mac
1446 #
1447 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1448 self.verify_ip(rx[0],
1449 "00:00:00:33:33:33",
1450 self.pg1.remote_hosts[1].mac,
1451 self.pg0.remote_ip4,
1452 self.pg1.remote_hosts[1].ip4)
1453
1454 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001455 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001456 # configured subnet and thus no glean
1457 #
1458 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001459 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001460
Neale Ranns59ae61e2018-06-07 18:09:49 -07001461 def test_garp(self):
1462 """ GARP """
1463
1464 #
1465 # Generate some hosts on the LAN
1466 #
1467 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001468 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001469
1470 #
1471 # And an ARP entry
1472 #
1473 arp = VppNeighbor(self,
1474 self.pg1.sw_if_index,
1475 self.pg1.remote_hosts[1].mac,
1476 self.pg1.remote_hosts[1].ip4)
1477 arp.add_vpp_config()
1478
1479 self.assertTrue(find_nbr(self,
1480 self.pg1.sw_if_index,
1481 self.pg1.remote_hosts[1].ip4,
1482 mac=self.pg1.remote_hosts[1].mac))
1483
1484 #
1485 # Send a GARP (request) to swap the host 1's address to that of host 2
1486 #
1487 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1488 src=self.pg1.remote_hosts[2].mac) /
1489 ARP(op="who-has",
1490 hwdst=self.pg1.local_mac,
1491 hwsrc=self.pg1.remote_hosts[2].mac,
1492 pdst=self.pg1.remote_hosts[1].ip4,
1493 psrc=self.pg1.remote_hosts[1].ip4))
1494
1495 self.pg1.add_stream(p1)
1496 self.pg_enable_capture(self.pg_interfaces)
1497 self.pg_start()
1498
1499 self.assertTrue(find_nbr(self,
1500 self.pg1.sw_if_index,
1501 self.pg1.remote_hosts[1].ip4,
1502 mac=self.pg1.remote_hosts[2].mac))
1503
1504 #
1505 # Send a GARP (reply) to swap the host 1's address to that of host 3
1506 #
1507 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1508 src=self.pg1.remote_hosts[3].mac) /
1509 ARP(op="is-at",
1510 hwdst=self.pg1.local_mac,
1511 hwsrc=self.pg1.remote_hosts[3].mac,
1512 pdst=self.pg1.remote_hosts[1].ip4,
1513 psrc=self.pg1.remote_hosts[1].ip4))
1514
1515 self.pg1.add_stream(p1)
1516 self.pg_enable_capture(self.pg_interfaces)
1517 self.pg_start()
1518
1519 self.assertTrue(find_nbr(self,
1520 self.pg1.sw_if_index,
1521 self.pg1.remote_hosts[1].ip4,
1522 mac=self.pg1.remote_hosts[3].mac))
1523
1524 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001525 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001526 # don't result in new neighbour entries
1527 #
1528 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1529 src=self.pg1.remote_hosts[3].mac) /
1530 ARP(op="who-has",
1531 hwdst=self.pg1.local_mac,
1532 hwsrc=self.pg1.remote_hosts[3].mac,
1533 pdst=self.pg1.remote_hosts[2].ip4,
1534 psrc=self.pg1.remote_hosts[2].ip4))
1535
1536 self.pg1.add_stream(p1)
1537 self.pg_enable_capture(self.pg_interfaces)
1538 self.pg_start()
1539
1540 self.assertFalse(find_nbr(self,
1541 self.pg1.sw_if_index,
1542 self.pg1.remote_hosts[2].ip4))
1543
1544 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1545 src=self.pg1.remote_hosts[3].mac) /
1546 ARP(op="is-at",
1547 hwdst=self.pg1.local_mac,
1548 hwsrc=self.pg1.remote_hosts[3].mac,
1549 pdst=self.pg1.remote_hosts[2].ip4,
1550 psrc=self.pg1.remote_hosts[2].ip4))
1551
1552 self.pg1.add_stream(p1)
1553 self.pg_enable_capture(self.pg_interfaces)
1554 self.pg_start()
1555
1556 self.assertFalse(find_nbr(self,
1557 self.pg1.sw_if_index,
1558 self.pg1.remote_hosts[2].ip4))
1559
Neale Ranns22eefd72020-09-23 11:25:21 +00001560 #
1561 # IP address in different subnets are not learnt
1562 #
1563 self.pg2.configure_ipv4_neighbors()
1564
1565 for op in ["is-at", "who-has"]:
1566 p1 = [(Ether(dst="ff:ff:ff:ff:ff:ff",
1567 src=self.pg2.remote_hosts[1].mac) /
1568 ARP(op=op,
1569 hwdst=self.pg2.local_mac,
1570 hwsrc=self.pg2.remote_hosts[1].mac,
1571 pdst=self.pg2.remote_hosts[1].ip4,
1572 psrc=self.pg2.remote_hosts[1].ip4)),
1573 (Ether(dst="ff:ff:ff:ff:ff:ff",
1574 src=self.pg2.remote_hosts[1].mac) /
1575 ARP(op=op,
1576 hwdst="ff:ff:ff:ff:ff:ff",
1577 hwsrc=self.pg2.remote_hosts[1].mac,
1578 pdst=self.pg2.remote_hosts[1].ip4,
1579 psrc=self.pg2.remote_hosts[1].ip4))]
1580
1581 self.send_and_assert_no_replies(self.pg1, p1)
1582 self.assertFalse(find_nbr(self,
1583 self.pg1.sw_if_index,
1584 self.pg2.remote_hosts[1].ip4))
1585
1586 # they are all dropped because the subnet's don't match
1587 self.assertEqual(4, self.statistics.get_err_counter(
1588 "/err/arp-reply/IP4 destination address not local to subnet"))
1589
Neale Ranns77f91622020-11-23 16:25:27 +00001590 def test_arp_incomplete2(self):
Neale Ranns14260392018-09-28 05:00:57 -07001591 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001592
1593 #
Neale Rannscd35e532018-08-31 02:51:45 -07001594 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001595 #
1596 self.pg0.generate_remote_hosts(2)
1597
Neale Rannscd35e532018-08-31 02:51:45 -07001598 #
1599 # IPv4/ARP
1600 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001601 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1602 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001603 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001604 ip_10_0_0_1.add_vpp_config()
1605
1606 p1 = (Ether(dst=self.pg1.local_mac,
1607 src=self.pg1.remote_mac) /
1608 IP(src=self.pg1.remote_ip4,
1609 dst="10.0.0.1") /
1610 UDP(sport=1234, dport=1234) /
1611 Raw())
1612
1613 self.pg1.add_stream(p1 * 257)
1614 self.pg_enable_capture(self.pg_interfaces)
1615 self.pg_start()
1616 rx = self.pg0._get_capture(1)
1617
1618 #
1619 # how many we get is going to be dependent on the time for packet
1620 # processing but it should be small
1621 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001622 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001623
Neale Rannscd35e532018-08-31 02:51:45 -07001624 #
1625 # IPv6/ND
1626 #
1627 ip_10_1 = VppIpRoute(self, "10::1", 128,
1628 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1629 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001630 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001631 ip_10_1.add_vpp_config()
1632
1633 p1 = (Ether(dst=self.pg1.local_mac,
1634 src=self.pg1.remote_mac) /
1635 IPv6(src=self.pg1.remote_ip6,
1636 dst="10::1") /
1637 UDP(sport=1234, dport=1234) /
1638 Raw())
1639
1640 self.pg1.add_stream(p1 * 257)
1641 self.pg_enable_capture(self.pg_interfaces)
1642 self.pg_start()
1643 rx = self.pg0._get_capture(1)
1644
1645 #
1646 # how many we get is going to be dependent on the time for packet
1647 # processing but it should be small
1648 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001649 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001650
Neale Ranns7425f922019-01-23 00:36:16 -08001651 def test_arp_forus(self):
1652 """ ARP for for-us """
1653
1654 #
1655 # Test that VPP responds with ARP requests to addresses that
1656 # are connected and local routes.
1657 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001658 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001659 # address added to an interface
1660 #
1661 self.pg0.generate_remote_hosts(2)
1662
Neale Ranns097fa662018-05-01 05:17:55 -07001663 forus = VppIpRoute(
1664 self, self.pg0.remote_hosts[1].ip4, 32,
1665 [VppRoutePath("0.0.0.0",
1666 self.pg0.sw_if_index,
1667 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001668 forus.add_vpp_config()
1669
1670 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1671 src=self.pg0.remote_mac) /
1672 ARP(op="who-has",
1673 hwdst=self.pg0.local_mac,
1674 hwsrc=self.pg0.remote_mac,
1675 pdst=self.pg0.remote_hosts[1].ip4,
1676 psrc=self.pg0.remote_ip4))
1677
1678 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1679
1680 self.verify_arp_resp(rx[0],
1681 self.pg0.local_mac,
1682 self.pg0.remote_mac,
1683 self.pg0.remote_hosts[1].ip4,
1684 self.pg0.remote_ip4)
1685
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001686 def test_arp_table_swap(self):
1687 #
1688 # Generate some hosts on the LAN
1689 #
1690 N_NBRS = 4
1691 self.pg1.generate_remote_hosts(N_NBRS)
1692
1693 for n in range(N_NBRS):
1694 # a route thru each neighbour
1695 VppIpRoute(self, "10.0.0.%d" % n, 32,
1696 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1697 self.pg1.sw_if_index)]).add_vpp_config()
1698
1699 # resolve each neighbour
1700 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1701 ARP(op="is-at", hwdst=self.pg1.local_mac,
1702 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1703 psrc=self.pg1.remote_hosts[n].ip4))
1704
1705 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1706
1707 self.logger.info(self.vapi.cli("sh ip neighbors"))
1708
1709 #
1710 # swap the table pg1 is in
1711 #
1712 table = VppIpTable(self, 100).add_vpp_config()
1713
1714 self.pg1.unconfig_ip4()
1715 self.pg1.set_table_ip4(100)
1716 self.pg1.config_ip4()
1717
1718 #
1719 # all neighbours are cleared
1720 #
1721 for n in range(N_NBRS):
1722 self.assertFalse(find_nbr(self,
1723 self.pg1.sw_if_index,
1724 self.pg1.remote_hosts[n].ip4))
1725
1726 #
1727 # packets to all neighbours generate ARP requests
1728 #
1729 for n in range(N_NBRS):
1730 # a route thru each neighbour
1731 VppIpRoute(self, "10.0.0.%d" % n, 32,
1732 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1733 self.pg1.sw_if_index)],
1734 table_id=100).add_vpp_config()
1735
1736 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1737 dst=self.pg1.local_mac) /
1738 IP(src=self.pg1.remote_hosts[n].ip4,
1739 dst="10.0.0.%d" % n) /
1740 Raw(b'0x5' * 100))
1741 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1742 for rx in rxs:
1743 self.verify_arp_req(rx,
1744 self.pg1.local_mac,
1745 self.pg1.local_ip4,
1746 self.pg1.remote_hosts[n].ip4)
1747
1748 self.pg1.unconfig_ip4()
1749 self.pg1.set_table_ip4(0)
1750
Neale Rannse2fe0972020-11-26 08:37:27 +00001751 def test_glean_src_select(self):
1752 """ Multi Connecteds """
1753
1754 #
1755 # configure multiple connected subnets on an interface
1756 # and ensure that ARP requests for hosts on those subnets
1757 # pick up the correct source address
1758 #
1759 conn1 = VppIpInterfaceAddress(self, self.pg1,
1760 "10.0.0.1", 24).add_vpp_config()
1761 conn2 = VppIpInterfaceAddress(self, self.pg1,
1762 "10.0.1.1", 24).add_vpp_config()
1763
1764 p1 = (Ether(src=self.pg0.remote_mac,
1765 dst=self.pg0.local_mac) /
1766 IP(src=self.pg1.remote_ip4,
1767 dst="10.0.0.128") /
1768 Raw(b'0x5' * 100))
1769
1770 rxs = self.send_and_expect(self.pg0, [p1], self.pg1)
1771 for rx in rxs:
1772 self.verify_arp_req(rx,
1773 self.pg1.local_mac,
1774 "10.0.0.1",
1775 "10.0.0.128")
1776
1777 p2 = (Ether(src=self.pg0.remote_mac,
1778 dst=self.pg0.local_mac) /
1779 IP(src=self.pg1.remote_ip4,
1780 dst="10.0.1.128") /
1781 Raw(b'0x5' * 100))
1782
1783 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1784 for rx in rxs:
1785 self.verify_arp_req(rx,
1786 self.pg1.local_mac,
1787 "10.0.1.1",
1788 "10.0.1.128")
1789
1790 #
1791 # add a local address in the same subnet
1792 # the source addresses are equivalent. VPP happens to
1793 # choose the last one that was added
1794 conn3 = VppIpInterfaceAddress(self, self.pg1,
1795 "10.0.1.2", 24).add_vpp_config()
1796
1797 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1798 for rx in rxs:
1799 self.verify_arp_req(rx,
1800 self.pg1.local_mac,
1801 "10.0.1.2",
1802 "10.0.1.128")
1803
1804 #
1805 # remove
1806 #
1807 conn3.remove_vpp_config()
1808 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1809 for rx in rxs:
1810 self.verify_arp_req(rx,
1811 self.pg1.local_mac,
1812 "10.0.1.1",
1813 "10.0.1.128")
1814
1815 #
1816 # add back, this time remove the first one
1817 #
1818 conn3 = VppIpInterfaceAddress(self, self.pg1,
1819 "10.0.1.2", 24).add_vpp_config()
1820
1821 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1822 for rx in rxs:
1823 self.verify_arp_req(rx,
1824 self.pg1.local_mac,
1825 "10.0.1.2",
1826 "10.0.1.128")
1827
1828 conn1.remove_vpp_config()
1829 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1830 for rx in rxs:
1831 self.verify_arp_req(rx,
1832 self.pg1.local_mac,
1833 "10.0.1.2",
1834 "10.0.1.128")
1835
Neale Ranns66edaf22021-07-09 13:03:52 +00001836 # apply a connected prefix to an interface in a different table
1837 VppIpRoute(self, "10.0.1.0", 24,
1838 [VppRoutePath("0.0.0.0",
1839 self.pg1.sw_if_index)],
1840 table_id=1).add_vpp_config()
1841
1842 rxs = self.send_and_expect(self.pg3, [p2], self.pg1)
1843 for rx in rxs:
1844 self.verify_arp_req(rx,
1845 self.pg1.local_mac,
1846 "10.0.1.2",
1847 "10.0.1.128")
1848
Neale Rannse2fe0972020-11-26 08:37:27 +00001849 # cleanup
1850 conn3.remove_vpp_config()
1851 conn2.remove_vpp_config()
1852
Neale Rannsdcd6d622017-05-26 02:59:16 -07001853
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00001854@tag_fixme_vpp_workers
Neale Ranns14260392018-09-28 05:00:57 -07001855class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001856 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001857
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001858 @classmethod
1859 def setUpClass(cls):
1860 super(NeighborStatsTestCase, cls).setUpClass()
1861
1862 @classmethod
1863 def tearDownClass(cls):
1864 super(NeighborStatsTestCase, cls).tearDownClass()
1865
Neale Ranns14260392018-09-28 05:00:57 -07001866 def setUp(self):
1867 super(NeighborStatsTestCase, self).setUp()
1868
1869 self.create_pg_interfaces(range(2))
1870
1871 # pg0 configured with ip4 and 6 addresses used for input
1872 # pg1 configured with ip4 and 6 addresses used for output
1873 # pg2 is unnumbered to pg0
1874 for i in self.pg_interfaces:
1875 i.admin_up()
1876 i.config_ip4()
1877 i.config_ip6()
1878 i.resolve_arp()
1879 i.resolve_ndp()
1880
1881 def tearDown(self):
1882 super(NeighborStatsTestCase, self).tearDown()
1883
1884 for i in self.pg_interfaces:
1885 i.unconfig_ip4()
1886 i.unconfig_ip6()
1887 i.admin_down()
1888
1889 def test_arp_stats(self):
1890 """ ARP Counters """
1891
1892 self.vapi.cli("adj counters enable")
1893 self.pg1.generate_remote_hosts(2)
1894
1895 arp1 = VppNeighbor(self,
1896 self.pg1.sw_if_index,
1897 self.pg1.remote_hosts[0].mac,
1898 self.pg1.remote_hosts[0].ip4)
1899 arp1.add_vpp_config()
1900 arp2 = VppNeighbor(self,
1901 self.pg1.sw_if_index,
1902 self.pg1.remote_hosts[1].mac,
1903 self.pg1.remote_hosts[1].ip4)
1904 arp2.add_vpp_config()
1905
1906 p1 = (Ether(dst=self.pg0.local_mac,
1907 src=self.pg0.remote_mac) /
1908 IP(src=self.pg0.remote_ip4,
1909 dst=self.pg1.remote_hosts[0].ip4) /
1910 UDP(sport=1234, dport=1234) /
1911 Raw())
1912 p2 = (Ether(dst=self.pg0.local_mac,
1913 src=self.pg0.remote_mac) /
1914 IP(src=self.pg0.remote_ip4,
1915 dst=self.pg1.remote_hosts[1].ip4) /
1916 UDP(sport=1234, dport=1234) /
1917 Raw())
1918
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001919 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1920 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001921
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001922 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1923 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001924
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001925 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1926 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001927
1928 def test_nd_stats(self):
1929 """ ND Counters """
1930
1931 self.vapi.cli("adj counters enable")
1932 self.pg0.generate_remote_hosts(3)
1933
1934 nd1 = VppNeighbor(self,
1935 self.pg0.sw_if_index,
1936 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001937 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001938 nd1.add_vpp_config()
1939 nd2 = VppNeighbor(self,
1940 self.pg0.sw_if_index,
1941 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001942 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001943 nd2.add_vpp_config()
1944
1945 p1 = (Ether(dst=self.pg1.local_mac,
1946 src=self.pg1.remote_mac) /
1947 IPv6(src=self.pg1.remote_ip6,
1948 dst=self.pg0.remote_hosts[1].ip6) /
1949 UDP(sport=1234, dport=1234) /
1950 Raw())
1951 p2 = (Ether(dst=self.pg1.local_mac,
1952 src=self.pg1.remote_mac) /
1953 IPv6(src=self.pg1.remote_ip6,
1954 dst=self.pg0.remote_hosts[2].ip6) /
1955 UDP(sport=1234, dport=1234) /
1956 Raw())
1957
1958 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1959 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1960
1961 self.assertEqual(16, nd1.get_stats()['packets'])
1962 self.assertEqual(16, nd2.get_stats()['packets'])
1963
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001964 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1965 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001966
1967
Neale Rannscbe25aa2019-09-30 10:53:31 +00001968class NeighborAgeTestCase(VppTestCase):
1969 """ ARP/ND Aging """
1970
1971 @classmethod
1972 def setUpClass(cls):
1973 super(NeighborAgeTestCase, cls).setUpClass()
1974
1975 @classmethod
1976 def tearDownClass(cls):
1977 super(NeighborAgeTestCase, cls).tearDownClass()
1978
1979 def setUp(self):
1980 super(NeighborAgeTestCase, self).setUp()
1981
1982 self.create_pg_interfaces(range(1))
1983
1984 # pg0 configured with ip4 and 6 addresses used for input
1985 # pg1 configured with ip4 and 6 addresses used for output
1986 # pg2 is unnumbered to pg0
1987 for i in self.pg_interfaces:
1988 i.admin_up()
1989 i.config_ip4()
1990 i.config_ip6()
1991 i.resolve_arp()
1992 i.resolve_ndp()
1993
1994 def tearDown(self):
1995 super(NeighborAgeTestCase, self).tearDown()
1996
1997 for i in self.pg_interfaces:
1998 i.unconfig_ip4()
1999 i.unconfig_ip6()
2000 i.admin_down()
2001
Neale Rannscbe25aa2019-09-30 10:53:31 +00002002 def verify_arp_req(self, rx, smac, sip, dip):
2003 ether = rx[Ether]
2004 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2005 self.assertEqual(ether.src, smac)
2006
2007 arp = rx[ARP]
2008 self.assertEqual(arp.hwtype, 1)
2009 self.assertEqual(arp.ptype, 0x800)
2010 self.assertEqual(arp.hwlen, 6)
2011 self.assertEqual(arp.plen, 4)
2012 self.assertEqual(arp.op, arp_opts["who-has"])
2013 self.assertEqual(arp.hwsrc, smac)
2014 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2015 self.assertEqual(arp.psrc, sip)
2016 self.assertEqual(arp.pdst, dip)
2017
2018 def test_age(self):
2019 """ Aging/Recycle """
2020
2021 self.vapi.cli("set logging unthrottle 0")
2022 self.vapi.cli("set logging size %d" % 0xffff)
2023
2024 self.pg0.generate_remote_hosts(201)
2025
2026 vaf = VppEnum.vl_api_address_family_t
2027
2028 #
2029 # start listening on all interfaces
2030 #
2031 self.pg_enable_capture(self.pg_interfaces)
2032
2033 #
2034 # Set the neighbor configuration:
2035 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002036 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00002037 # recycle = false
2038 #
2039 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2040 max_number=200,
2041 max_age=0,
2042 recycle=False)
2043
2044 self.vapi.cli("sh ip neighbor-config")
2045
2046 # add the 198 neighbours that should pass (-1 for one created in setup)
2047 for ii in range(200):
2048 VppNeighbor(self,
2049 self.pg0.sw_if_index,
2050 self.pg0.remote_hosts[ii].mac,
2051 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2052
2053 # one more neighbor over the limit should fail
2054 with self.vapi.assert_negative_api_retval():
2055 VppNeighbor(self,
2056 self.pg0.sw_if_index,
2057 self.pg0.remote_hosts[200].mac,
2058 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2059
2060 #
2061 # change the config to allow recycling the old neighbors
2062 #
2063 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2064 max_number=200,
2065 max_age=0,
2066 recycle=True)
2067
2068 # now new additions are allowed
2069 VppNeighbor(self,
2070 self.pg0.sw_if_index,
2071 self.pg0.remote_hosts[200].mac,
2072 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2073
2074 # add the first neighbor we configured has been re-used
2075 self.assertFalse(find_nbr(self,
2076 self.pg0.sw_if_index,
2077 self.pg0.remote_hosts[0].ip4))
2078 self.assertTrue(find_nbr(self,
2079 self.pg0.sw_if_index,
2080 self.pg0.remote_hosts[200].ip4))
2081
2082 #
2083 # change the config to age old neighbors
2084 #
2085 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2086 max_number=200,
2087 max_age=2,
2088 recycle=True)
2089
2090 self.vapi.cli("sh ip4 neighbor-sorted")
2091
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002092 # age out neighbors
2093 self.virtual_sleep(3)
2094
Neale Rannscbe25aa2019-09-30 10:53:31 +00002095 #
2096 # expect probes from all these ARP entries as they age
2097 # 3 probes for each neighbor 3*200 = 600
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002098 rxs = self.pg0.get_capture(600, timeout=2)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002099
2100 for ii in range(3):
2101 for jj in range(200):
2102 rx = rxs[ii*200 + jj]
2103 # rx.show()
2104
2105 #
2106 # 3 probes sent then 1 more second to see if a reply comes, before
2107 # they age out
2108 #
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002109 self.virtual_sleep(1)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002110
2111 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2112 af=vaf.ADDRESS_IP4))
2113
2114 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002115 # load up some neighbours again with 2s aging enabled
2116 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002117 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002118 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002119 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2120
2121 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002122 for ii in range(10):
2123 VppNeighbor(self,
2124 self.pg0.sw_if_index,
2125 self.pg0.remote_hosts[ii].mac,
2126 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002127
2128 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2129 self.assertEqual(e.flags,
2130 enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2131 self.assertEqual(str(e.neighbor.ip_address),
2132 self.pg0.remote_hosts[ii].ip4)
2133 self.assertEqual(e.neighbor.mac_address,
2134 self.pg0.remote_hosts[ii].mac)
2135
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002136 self.virtual_sleep(10)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002137 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2138 af=vaf.ADDRESS_IP4))
2139
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002140 evs = []
2141 for ii in range(10):
2142 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2143 self.assertEqual(e.flags,
2144 enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
2145 evs.append(e)
2146
2147 # check we got the correct mac/ip pairs - done separately
2148 # because we don't care about the order the remove notifications
2149 # arrive
2150 for ii in range(10):
2151 found = False
2152 mac = self.pg0.remote_hosts[ii].mac
2153 ip = self.pg0.remote_hosts[ii].ip4
2154
2155 for e in evs:
2156 if (e.neighbor.mac_address == mac and
2157 str(e.neighbor.ip_address) == ip):
2158 found = True
2159 break
2160 self.assertTrue(found)
2161
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002162 #
2163 # check if we can set age and recycle with empty neighbor list
2164 #
2165 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2166 max_number=200,
2167 max_age=1000,
2168 recycle=True)
2169
2170 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002171 # load up some neighbours again, then disable the aging
2172 # they should still be there in 10 seconds time
2173 #
2174 for ii in range(10):
2175 VppNeighbor(self,
2176 self.pg0.sw_if_index,
2177 self.pg0.remote_hosts[ii].mac,
2178 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2179 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2180 max_number=200,
2181 max_age=0,
2182 recycle=False)
2183
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002184 self.virtual_sleep(10)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002185 self.assertTrue(find_nbr(self,
2186 self.pg0.sw_if_index,
2187 self.pg0.remote_hosts[0].ip4))
2188
2189
Neale Rannsc87fbb42020-04-02 17:08:28 +00002190class NeighborReplaceTestCase(VppTestCase):
2191 """ ARP/ND Replacement """
2192
2193 @classmethod
2194 def setUpClass(cls):
2195 super(NeighborReplaceTestCase, cls).setUpClass()
2196
2197 @classmethod
2198 def tearDownClass(cls):
2199 super(NeighborReplaceTestCase, cls).tearDownClass()
2200
2201 def setUp(self):
2202 super(NeighborReplaceTestCase, self).setUp()
2203
2204 self.create_pg_interfaces(range(4))
2205
2206 # pg0 configured with ip4 and 6 addresses used for input
2207 # pg1 configured with ip4 and 6 addresses used for output
2208 # pg2 is unnumbered to pg0
2209 for i in self.pg_interfaces:
2210 i.admin_up()
2211 i.config_ip4()
2212 i.config_ip6()
2213 i.resolve_arp()
2214 i.resolve_ndp()
2215
2216 def tearDown(self):
2217 super(NeighborReplaceTestCase, self).tearDown()
2218
2219 for i in self.pg_interfaces:
2220 i.unconfig_ip4()
2221 i.unconfig_ip6()
2222 i.admin_down()
2223
2224 def test_replace(self):
2225 """ replace """
2226
2227 N_HOSTS = 16
2228
2229 for i in self.pg_interfaces:
2230 i.generate_remote_hosts(N_HOSTS)
2231 i.configure_ipv4_neighbors()
2232 i.configure_ipv6_neighbors()
2233
2234 # replace them all
2235 self.vapi.ip_neighbor_replace_begin()
2236 self.vapi.ip_neighbor_replace_end()
2237
2238 for i in self.pg_interfaces:
2239 for h in range(N_HOSTS):
2240 self.assertFalse(find_nbr(self,
2241 self.pg0.sw_if_index,
2242 self.pg0.remote_hosts[h].ip4))
2243 self.assertFalse(find_nbr(self,
2244 self.pg0.sw_if_index,
2245 self.pg0.remote_hosts[h].ip6))
2246
2247 #
2248 # and them all back via the API
2249 #
2250 for i in self.pg_interfaces:
2251 for h in range(N_HOSTS):
2252 VppNeighbor(self,
2253 i.sw_if_index,
2254 i.remote_hosts[h].mac,
2255 i.remote_hosts[h].ip4).add_vpp_config()
2256 VppNeighbor(self,
2257 i.sw_if_index,
2258 i.remote_hosts[h].mac,
2259 i.remote_hosts[h].ip6).add_vpp_config()
2260
2261 #
2262 # begin the replacement again, this time touch some
2263 # the neighbours on pg1 so they are not deleted
2264 #
2265 self.vapi.ip_neighbor_replace_begin()
2266
2267 # update from the API all neighbours on pg1
2268 for h in range(N_HOSTS):
2269 VppNeighbor(self,
2270 self.pg1.sw_if_index,
2271 self.pg1.remote_hosts[h].mac,
2272 self.pg1.remote_hosts[h].ip4).add_vpp_config()
2273 VppNeighbor(self,
2274 self.pg1.sw_if_index,
2275 self.pg1.remote_hosts[h].mac,
2276 self.pg1.remote_hosts[h].ip6).add_vpp_config()
2277
2278 # update from the data-plane all neighbours on pg3
2279 self.pg3.configure_ipv4_neighbors()
2280 self.pg3.configure_ipv6_neighbors()
2281
2282 # complete the replacement
2283 self.logger.info(self.vapi.cli("sh ip neighbors"))
2284 self.vapi.ip_neighbor_replace_end()
2285
2286 for i in self.pg_interfaces:
2287 if i == self.pg1 or i == self.pg3:
2288 # neighbours on pg1 and pg3 are still present
2289 for h in range(N_HOSTS):
2290 self.assertTrue(find_nbr(self,
2291 i.sw_if_index,
2292 i.remote_hosts[h].ip4))
2293 self.assertTrue(find_nbr(self,
2294 i.sw_if_index,
2295 i.remote_hosts[h].ip6))
2296 else:
2297 # all other neighbours are toast
2298 for h in range(N_HOSTS):
2299 self.assertFalse(find_nbr(self,
2300 i.sw_if_index,
2301 i.remote_hosts[h].ip4))
2302 self.assertFalse(find_nbr(self,
2303 i.sw_if_index,
2304 i.remote_hosts[h].ip6))
2305
2306
Neale Ranns240dcb22020-04-23 09:04:59 +00002307class NeighborFlush(VppTestCase):
2308 """ Neighbor Flush """
2309
2310 @classmethod
2311 def setUpClass(cls):
2312 super(NeighborFlush, cls).setUpClass()
2313
2314 @classmethod
2315 def tearDownClass(cls):
2316 super(NeighborFlush, cls).tearDownClass()
2317
2318 def setUp(self):
2319 super(NeighborFlush, self).setUp()
2320
2321 self.create_pg_interfaces(range(2))
2322
2323 for i in self.pg_interfaces:
2324 i.admin_up()
2325 i.config_ip4()
2326 i.config_ip6()
2327 i.resolve_arp()
2328 i.resolve_ndp()
2329
2330 def tearDown(self):
2331 super(NeighborFlush, self).tearDown()
2332
2333 for i in self.pg_interfaces:
2334 i.unconfig_ip4()
2335 i.unconfig_ip6()
2336 i.admin_down()
2337
2338 def test_flush(self):
2339 """ Neighbour Flush """
2340
2341 e = VppEnum
2342 nf = e.vl_api_ip_neighbor_flags_t
2343 af = e.vl_api_address_family_t
2344 N_HOSTS = 16
2345 static = [False, True]
2346 self.pg0.generate_remote_hosts(N_HOSTS)
2347 self.pg1.generate_remote_hosts(N_HOSTS)
2348
2349 for s in static:
2350 # a few v4 and v6 dynamic neoghbors
2351 for n in range(N_HOSTS):
2352 VppNeighbor(self,
2353 self.pg0.sw_if_index,
2354 self.pg0.remote_hosts[n].mac,
2355 self.pg0.remote_hosts[n].ip4,
2356 is_static=s).add_vpp_config()
2357 VppNeighbor(self,
2358 self.pg1.sw_if_index,
2359 self.pg1.remote_hosts[n].mac,
2360 self.pg1.remote_hosts[n].ip6,
2361 is_static=s).add_vpp_config()
2362
2363 # flush the interfaces individually
2364 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2365
2366 # check we haven't flushed that which we shouldn't
2367 for n in range(N_HOSTS):
2368 self.assertTrue(find_nbr(self,
2369 self.pg1.sw_if_index,
2370 self.pg1.remote_hosts[n].ip6,
2371 is_static=s))
2372
2373 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2374
2375 for n in range(N_HOSTS):
2376 self.assertFalse(find_nbr(self,
2377 self.pg0.sw_if_index,
2378 self.pg0.remote_hosts[n].ip4))
2379 self.assertFalse(find_nbr(self,
2380 self.pg1.sw_if_index,
2381 self.pg1.remote_hosts[n].ip6))
2382
2383 # add the nieghbours back
2384 for n in range(N_HOSTS):
2385 VppNeighbor(self,
2386 self.pg0.sw_if_index,
2387 self.pg0.remote_hosts[n].mac,
2388 self.pg0.remote_hosts[n].ip4,
2389 is_static=s).add_vpp_config()
2390 VppNeighbor(self,
2391 self.pg1.sw_if_index,
2392 self.pg1.remote_hosts[n].mac,
2393 self.pg1.remote_hosts[n].ip6,
2394 is_static=s).add_vpp_config()
2395
2396 self.logger.info(self.vapi.cli("sh ip neighbor"))
2397
2398 # flush both interfaces at the same time
2399 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2400
2401 # check we haven't flushed that which we shouldn't
2402 for n in range(N_HOSTS):
2403 self.assertTrue(find_nbr(self,
2404 self.pg0.sw_if_index,
2405 self.pg0.remote_hosts[n].ip4,
2406 is_static=s))
2407
2408 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2409
2410 for n in range(N_HOSTS):
2411 self.assertFalse(find_nbr(self,
2412 self.pg0.sw_if_index,
2413 self.pg0.remote_hosts[n].ip4))
2414 self.assertFalse(find_nbr(self,
2415 self.pg1.sw_if_index,
2416 self.pg1.remote_hosts[n].ip6))
2417
2418
Neale Ranns37be7362017-02-21 17:30:26 -08002419if __name__ == '__main__':
2420 unittest.main(testRunner=VppTestRunner)