blob: e1b37a0a1243e96aa9672f44f6a59fa126c256f9 [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
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020010from vpp_ip_route import (
11 VppIpRoute,
12 VppRoutePath,
13 find_route,
14 VppIpTable,
15 DpoProto,
16 FibPathType,
17 VppIpInterfaceAddress,
18)
Neale Ranns37029302018-08-10 05:30:06 -070019from vpp_papi import VppEnum
Jakub Grajciar2df2f752020-12-01 11:23:44 +010020from vpp_ip import VppIpPuntRedirect
Neale Ranns39f9d8b2017-02-16 21:57:05 -080021
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070022import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080023from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070024from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000025from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070026from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080027from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070028from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080029
Paul Vinciguerra4271c972019-05-14 13:25:49 -040030
31NUM_PKTS = 67
32
Neale Ranns39f9d8b2017-02-16 21:57:05 -080033# not exported by scapy, so redefined here
34arp_opts = {"who-has": 1, "is-at": 2}
35
36
37class ARPTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020038 """ARP Test Case"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -080039
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070040 @classmethod
41 def setUpClass(cls):
42 super(ARPTestCase, cls).setUpClass()
43
44 @classmethod
45 def tearDownClass(cls):
46 super(ARPTestCase, cls).tearDownClass()
47
Neale Ranns39f9d8b2017-02-16 21:57:05 -080048 def setUp(self):
49 super(ARPTestCase, self).setUp()
50
51 # create 3 pg interfaces
52 self.create_pg_interfaces(range(4))
53
54 # pg0 configured with ip4 and 6 addresses used for input
55 # pg1 configured with ip4 and 6 addresses used for output
56 # pg2 is unnumbered to pg0
57 for i in self.pg_interfaces:
58 i.admin_up()
59
60 self.pg0.config_ip4()
61 self.pg0.config_ip6()
62 self.pg0.resolve_arp()
63
64 self.pg1.config_ip4()
65 self.pg1.config_ip6()
66
67 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070068 self.tbl = VppIpTable(self, 1)
69 self.tbl.add_vpp_config()
70
Neale Ranns39f9d8b2017-02-16 21:57:05 -080071 self.pg3.set_table_ip4(1)
72 self.pg3.config_ip4()
73
Neale Ranns4008ac92017-02-13 23:20:04 -080074 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080075 self.pg0.unconfig_ip4()
76 self.pg0.unconfig_ip6()
77
78 self.pg1.unconfig_ip4()
79 self.pg1.unconfig_ip6()
80
81 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070082 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080083
Neale Ranns4008ac92017-02-13 23:20:04 -080084 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080085 i.admin_down()
86
Neale Ranns15002542017-09-10 04:39:11 -070087 super(ARPTestCase, self).tearDown()
88
Neale Ranns39f9d8b2017-02-16 21:57:05 -080089 def verify_arp_req(self, rx, smac, sip, dip):
90 ether = rx[Ether]
91 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
92 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +010093 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -080094
95 arp = rx[ARP]
96 self.assertEqual(arp.hwtype, 1)
97 self.assertEqual(arp.ptype, 0x800)
98 self.assertEqual(arp.hwlen, 6)
99 self.assertEqual(arp.plen, 4)
100 self.assertEqual(arp.op, arp_opts["who-has"])
101 self.assertEqual(arp.hwsrc, smac)
102 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
103 self.assertEqual(arp.psrc, sip)
104 self.assertEqual(arp.pdst, dip)
105
106 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
107 ether = rx[Ether]
108 self.assertEqual(ether.dst, dmac)
109 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100110 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800111
112 arp = rx[ARP]
113 self.assertEqual(arp.hwtype, 1)
114 self.assertEqual(arp.ptype, 0x800)
115 self.assertEqual(arp.hwlen, 6)
116 self.assertEqual(arp.plen, 4)
117 self.assertEqual(arp.op, arp_opts["is-at"])
118 self.assertEqual(arp.hwsrc, smac)
119 self.assertEqual(arp.hwdst, dmac)
120 self.assertEqual(arp.psrc, sip)
121 self.assertEqual(arp.pdst, dip)
122
Matthew Smithcb9ab472017-05-16 21:35:56 -0500123 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
124 ether = rx[Ether]
125 self.assertEqual(ether.dst, dmac)
126 self.assertEqual(ether.src, smac)
127
128 arp = rx[ARP]
129 self.assertEqual(arp.hwtype, 1)
130 self.assertEqual(arp.ptype, 0x800)
131 self.assertEqual(arp.hwlen, 6)
132 self.assertEqual(arp.plen, 4)
133 self.assertEqual(arp.op, arp_opts["is-at"])
134 self.assertNotEqual(arp.hwsrc, smac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200135 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or "00:00:5E:00:01" in arp.hwsrc)
Matthew Smithcb9ab472017-05-16 21:35:56 -0500136 self.assertEqual(arp.hwdst, dmac)
137 self.assertEqual(arp.psrc, sip)
138 self.assertEqual(arp.pdst, dip)
139
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800140 def verify_ip(self, rx, smac, dmac, sip, dip):
141 ether = rx[Ether]
142 self.assertEqual(ether.dst, dmac)
143 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100144 self.assertEqual(ether.type, 0x0800)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800145
146 ip = rx[IP]
147 self.assertEqual(ip.src, sip)
148 self.assertEqual(ip.dst, dip)
149
Neale Ranns37be7362017-02-21 17:30:26 -0800150 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
151 ether = rx[Ether]
152 self.assertEqual(ether.dst, dmac)
153 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100154 self.assertEqual(ether.type, 0x8847)
Neale Ranns37be7362017-02-21 17:30:26 -0800155
156 mpls = rx[MPLS]
157 self.assertTrue(mpls.label, label)
158
159 ip = rx[IP]
160 self.assertEqual(ip.src, sip)
161 self.assertEqual(ip.dst, dip)
162
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800163 def test_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200164 """ARP"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800165
166 #
167 # Generate some hosts on the LAN
168 #
Neale Rannsca193612017-06-14 06:50:08 -0700169 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800170
171 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000172 # watch for:
173 # - all neighbour events
174 # - all neighbor events on pg1
175 # - neighbor events for host[1] on pg1
176 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200177 self.vapi.want_ip_neighbor_events(enable=1, pid=os.getpid())
178 self.vapi.want_ip_neighbor_events(
179 enable=1, pid=os.getpid(), sw_if_index=self.pg1.sw_if_index
180 )
181 self.vapi.want_ip_neighbor_events(
182 enable=1,
183 pid=os.getpid(),
184 sw_if_index=self.pg1.sw_if_index,
185 ip=self.pg1.remote_hosts[1].ip4,
186 )
Neale Rannscbe25aa2019-09-30 10:53:31 +0000187
188 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
189
190 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800191 # Send IP traffic to one of these unresolved hosts.
192 # expect the generation of an ARP request
193 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200194 p = (
195 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
196 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4)
197 / UDP(sport=1234, dport=1234)
198 / Raw()
199 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800200
201 self.pg0.add_stream(p)
202 self.pg_enable_capture(self.pg_interfaces)
203 self.pg_start()
204
205 rx = self.pg1.get_capture(1)
206
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200207 self.verify_arp_req(
208 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
209 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800210
211 #
212 # And a dynamic ARP entry for host 1
213 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200214 dyn_arp = VppNeighbor(
215 self,
216 self.pg1.sw_if_index,
217 self.pg1.remote_hosts[1].mac,
218 self.pg1.remote_hosts[1].ip4,
219 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800220 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000221 self.assertTrue(dyn_arp.query_vpp_config())
222
Neale Rannsdc617b82020-08-20 08:22:56 +0000223 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
224
Neale Rannscbe25aa2019-09-30 10:53:31 +0000225 # this matches all of the listnerers
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200226 es = [self.vapi.wait_for_event(1, "ip_neighbor_event") for i in range(3)]
Neale Rannscbe25aa2019-09-30 10:53:31 +0000227 for e in es:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200228 self.assertEqual(str(e.neighbor.ip_address), self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800229
230 #
231 # now we expect IP traffic forwarded
232 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200233 dyn_p = (
234 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
235 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4)
236 / UDP(sport=1234, dport=1234)
237 / Raw()
238 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800239
240 self.pg0.add_stream(dyn_p)
241 self.pg_enable_capture(self.pg_interfaces)
242 self.pg_start()
243
244 rx = self.pg1.get_capture(1)
245
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200246 self.verify_ip(
247 rx[0],
248 self.pg1.local_mac,
249 self.pg1.remote_hosts[1].mac,
250 self.pg0.remote_ip4,
251 self.pg1._remote_hosts[1].ip4,
252 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800253
254 #
255 # And a Static ARP entry for host 2
256 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200257 static_arp = VppNeighbor(
258 self,
259 self.pg1.sw_if_index,
260 self.pg1.remote_hosts[2].mac,
261 self.pg1.remote_hosts[2].ip4,
262 is_static=1,
263 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800264 static_arp.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200265 es = [self.vapi.wait_for_event(1, "ip_neighbor_event") for i in range(2)]
Neale Rannscbe25aa2019-09-30 10:53:31 +0000266 for e in es:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200267 self.assertEqual(str(e.neighbor.ip_address), self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800268
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200269 static_p = (
270 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
271 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[2].ip4)
272 / UDP(sport=1234, dport=1234)
273 / Raw()
274 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800275
276 self.pg0.add_stream(static_p)
277 self.pg_enable_capture(self.pg_interfaces)
278 self.pg_start()
279
280 rx = self.pg1.get_capture(1)
281
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200282 self.verify_ip(
283 rx[0],
284 self.pg1.local_mac,
285 self.pg1.remote_hosts[2].mac,
286 self.pg0.remote_ip4,
287 self.pg1._remote_hosts[2].ip4,
288 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800289
290 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000291 # remove all the listeners
292 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200293 self.vapi.want_ip_neighbor_events(enable=0, pid=os.getpid())
294 self.vapi.want_ip_neighbor_events(
295 enable=0, pid=os.getpid(), sw_if_index=self.pg1.sw_if_index
296 )
297 self.vapi.want_ip_neighbor_events(
298 enable=0,
299 pid=os.getpid(),
300 sw_if_index=self.pg1.sw_if_index,
301 ip=self.pg1.remote_hosts[1].ip4,
302 )
Neale Rannscbe25aa2019-09-30 10:53:31 +0000303
304 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800305 # flap the link. dynamic ARPs get flush, statics don't
306 #
307 self.pg1.admin_down()
308 self.pg1.admin_up()
309
310 self.pg0.add_stream(static_p)
311 self.pg_enable_capture(self.pg_interfaces)
312 self.pg_start()
313 rx = self.pg1.get_capture(1)
314
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200315 self.verify_ip(
316 rx[0],
317 self.pg1.local_mac,
318 self.pg1.remote_hosts[2].mac,
319 self.pg0.remote_ip4,
320 self.pg1._remote_hosts[2].ip4,
321 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800322
323 self.pg0.add_stream(dyn_p)
324 self.pg_enable_capture(self.pg_interfaces)
325 self.pg_start()
326
327 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200328 self.verify_arp_req(
329 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
330 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800331
Neale Rannscbe25aa2019-09-30 10:53:31 +0000332 self.assertFalse(dyn_arp.query_vpp_config())
333 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800334 #
335 # Send an ARP request from one of the so-far unlearned remote hosts
336 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200337 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[3].mac) / ARP(
338 op="who-has",
339 hwsrc=self.pg1._remote_hosts[3].mac,
340 pdst=self.pg1.local_ip4,
341 psrc=self.pg1._remote_hosts[3].ip4,
342 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800343
344 self.pg1.add_stream(p)
345 self.pg_enable_capture(self.pg_interfaces)
346 self.pg_start()
347
348 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200349 self.verify_arp_resp(
350 rx[0],
351 self.pg1.local_mac,
352 self.pg1._remote_hosts[3].mac,
353 self.pg1.local_ip4,
354 self.pg1._remote_hosts[3].ip4,
355 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800356
357 #
358 # VPP should have learned the mapping for the remote host
359 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200360 self.assertTrue(
361 find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[3].ip4)
362 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800363 #
364 # Fire in an ARP request before the interface becomes IP enabled
365 #
366 self.pg2.generate_remote_hosts(4)
367
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200368 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
369 op="who-has",
370 hwsrc=self.pg2.remote_mac,
371 pdst=self.pg1.local_ip4,
372 psrc=self.pg2.remote_hosts[3].ip4,
373 )
374 pt = (
375 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac)
376 / Dot1Q(vlan=0)
377 / ARP(
378 op="who-has",
379 hwsrc=self.pg2.remote_mac,
380 pdst=self.pg1.local_ip4,
381 psrc=self.pg2.remote_hosts[3].ip4,
382 )
383 )
384 self.send_and_assert_no_replies(self.pg2, p, "interface not IP enabled")
Neale Ranns4b919a52017-03-11 05:55:21 -0800385
386 #
387 # Make pg2 un-numbered to pg1
388 #
389 self.pg2.set_unnumbered(self.pg1.sw_if_index)
390
Neale Rannsac3e72c2019-10-06 01:04:26 -0700391 #
392 # test the unnumbered dump both by all interfaces and just the enabled
393 # one
394 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700395 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700396 self.assertTrue(len(unnum))
397 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
398 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
399 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
400 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700401 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
402 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
403
Neale Ranns4b919a52017-03-11 05:55:21 -0800404 #
405 # We should respond to ARP requests for the unnumbered to address
406 # once an attached route to the source is known
407 #
408 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200409 self.pg2, p, "ARP req for unnumbered address - no source"
410 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800411
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200412 attached_host = VppIpRoute(
413 self,
414 self.pg2.remote_hosts[3].ip4,
415 32,
416 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
417 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800418 attached_host.add_vpp_config()
419
420 self.pg2.add_stream(p)
421 self.pg_enable_capture(self.pg_interfaces)
422 self.pg_start()
423
424 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200425 self.verify_arp_resp(
426 rx[0],
427 self.pg2.local_mac,
428 self.pg2.remote_mac,
429 self.pg1.local_ip4,
430 self.pg2.remote_hosts[3].ip4,
431 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800432
Neale Ranns30d0fd42017-05-30 07:30:04 -0700433 self.pg2.add_stream(pt)
434 self.pg_enable_capture(self.pg_interfaces)
435 self.pg_start()
436
437 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200438 self.verify_arp_resp(
439 rx[0],
440 self.pg2.local_mac,
441 self.pg2.remote_mac,
442 self.pg1.local_ip4,
443 self.pg2.remote_hosts[3].ip4,
444 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700445
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800446 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800447 # A neighbor entry that has no associated FIB-entry
448 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200449 arp_no_fib = VppNeighbor(
450 self,
451 self.pg1.sw_if_index,
452 self.pg1.remote_hosts[4].mac,
453 self.pg1.remote_hosts[4].ip4,
454 is_no_fib_entry=1,
455 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800456 arp_no_fib.add_vpp_config()
457
458 #
459 # check we have the neighbor, but no route
460 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200461 self.assertTrue(
462 find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[4].ip4)
463 )
464 self.assertFalse(find_route(self, self.pg1._remote_hosts[4].ip4, 32))
Neale Ranns3983ac22017-03-10 11:53:27 -0800465 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800466 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
467 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800468 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200469 arp_unnum = VppNeighbor(
470 self,
471 self.pg2.sw_if_index,
472 self.pg1.remote_hosts[5].mac,
473 self.pg1.remote_hosts[5].ip4,
474 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800475 arp_unnum.add_vpp_config()
476
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200477 p = (
478 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
479 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[5].ip4)
480 / UDP(sport=1234, dport=1234)
481 / Raw()
482 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800483
484 self.pg0.add_stream(p)
485 self.pg_enable_capture(self.pg_interfaces)
486 self.pg_start()
487
488 rx = self.pg2.get_capture(1)
489
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200490 self.verify_ip(
491 rx[0],
492 self.pg2.local_mac,
493 self.pg1.remote_hosts[5].mac,
494 self.pg0.remote_ip4,
495 self.pg1._remote_hosts[5].ip4,
496 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800497
498 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800499 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
500 # with the unnumbered interface's address as the source
501 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200502 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
503 op="who-has",
504 hwsrc=self.pg2.remote_mac,
505 pdst=self.pg1.local_ip4,
506 psrc=self.pg1.remote_hosts[6].ip4,
507 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800508
509 self.pg2.add_stream(p)
510 self.pg_enable_capture(self.pg_interfaces)
511 self.pg_start()
512
513 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200514 self.verify_arp_resp(
515 rx[0],
516 self.pg2.local_mac,
517 self.pg2.remote_mac,
518 self.pg1.local_ip4,
519 self.pg1.remote_hosts[6].ip4,
520 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800521
522 #
523 # An attached host route out of pg2 for an undiscovered hosts generates
524 # an ARP request with the unnumbered address as the source
525 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200526 att_unnum = VppIpRoute(
527 self,
528 self.pg1.remote_hosts[7].ip4,
529 32,
530 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
531 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800532 att_unnum.add_vpp_config()
533
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200534 p = (
535 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
536 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[7].ip4)
537 / UDP(sport=1234, dport=1234)
538 / Raw()
539 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800540
541 self.pg0.add_stream(p)
542 self.pg_enable_capture(self.pg_interfaces)
543 self.pg_start()
544
545 rx = self.pg2.get_capture(1)
546
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200547 self.verify_arp_req(
548 rx[0], self.pg2.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[7].ip4
549 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800550
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200551 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
552 op="who-has",
553 hwsrc=self.pg2.remote_mac,
554 pdst=self.pg1.local_ip4,
555 psrc=self.pg1.remote_hosts[7].ip4,
556 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800557
558 self.pg2.add_stream(p)
559 self.pg_enable_capture(self.pg_interfaces)
560 self.pg_start()
561
562 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200563 self.verify_arp_resp(
564 rx[0],
565 self.pg2.local_mac,
566 self.pg2.remote_mac,
567 self.pg1.local_ip4,
568 self.pg1.remote_hosts[7].ip4,
569 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800570
571 #
572 # An attached host route as yet unresolved out of pg2 for an
573 # undiscovered host, an ARP requests begets a response.
574 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200575 att_unnum1 = VppIpRoute(
576 self,
577 self.pg1.remote_hosts[8].ip4,
578 32,
579 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
580 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800581 att_unnum1.add_vpp_config()
582
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200583 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
584 op="who-has",
585 hwsrc=self.pg2.remote_mac,
586 pdst=self.pg1.local_ip4,
587 psrc=self.pg1.remote_hosts[8].ip4,
588 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800589
590 self.pg2.add_stream(p)
591 self.pg_enable_capture(self.pg_interfaces)
592 self.pg_start()
593
594 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200595 self.verify_arp_resp(
596 rx[0],
597 self.pg2.local_mac,
598 self.pg2.remote_mac,
599 self.pg1.local_ip4,
600 self.pg1.remote_hosts[8].ip4,
601 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800602
603 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700604 # Send an ARP request from one of the so-far unlearned remote hosts
605 # with a VLAN0 tag
606 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200607 p = (
608 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[9].mac)
609 / Dot1Q(vlan=0)
610 / ARP(
611 op="who-has",
612 hwsrc=self.pg1._remote_hosts[9].mac,
613 pdst=self.pg1.local_ip4,
614 psrc=self.pg1._remote_hosts[9].ip4,
615 )
616 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700617
618 self.pg1.add_stream(p)
619 self.pg_enable_capture(self.pg_interfaces)
620 self.pg_start()
621
622 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200623 self.verify_arp_resp(
624 rx[0],
625 self.pg1.local_mac,
626 self.pg1._remote_hosts[9].mac,
627 self.pg1.local_ip4,
628 self.pg1._remote_hosts[9].ip4,
629 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700630
631 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700632 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700633 # Should still get an ARP resp since the cover is attached
634 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200635 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) / ARP(
636 op="who-has",
637 hwsrc=self.pg1.remote_mac,
638 pdst=self.pg1.local_ip4,
639 psrc=self.pg1.remote_hosts[10].ip4,
640 )
Neale Rannsca193612017-06-14 06:50:08 -0700641
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200642 r1 = VppIpRoute(
643 self,
644 self.pg1.remote_hosts[10].ip4,
645 30,
646 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
647 )
Neale Rannsca193612017-06-14 06:50:08 -0700648 r1.add_vpp_config()
649
650 self.pg1.add_stream(p)
651 self.pg_enable_capture(self.pg_interfaces)
652 self.pg_start()
653 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200654 self.verify_arp_resp(
655 rx[0],
656 self.pg1.local_mac,
657 self.pg1.remote_mac,
658 self.pg1.local_ip4,
659 self.pg1.remote_hosts[10].ip4,
660 )
Neale Rannsca193612017-06-14 06:50:08 -0700661
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200662 r2 = VppIpRoute(
663 self,
664 self.pg1.remote_hosts[10].ip4,
665 32,
666 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
667 )
Neale Rannsca193612017-06-14 06:50:08 -0700668 r2.add_vpp_config()
669
670 self.pg1.add_stream(p)
671 self.pg_enable_capture(self.pg_interfaces)
672 self.pg_start()
673 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200674 self.verify_arp_resp(
675 rx[0],
676 self.pg1.local_mac,
677 self.pg1.remote_mac,
678 self.pg1.local_ip4,
679 self.pg1.remote_hosts[10].ip4,
680 )
Neale Rannsca193612017-06-14 06:50:08 -0700681
682 #
683 # add an ARP entry that's not on the sub-net and so whose
684 # adj-fib fails the refinement check. then send an ARP request
685 # from that source
686 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200687 a1 = VppNeighbor(
688 self, self.pg0.sw_if_index, self.pg0.remote_mac, "100.100.100.50"
689 )
Neale Rannsca193612017-06-14 06:50:08 -0700690 a1.add_vpp_config()
691
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200692 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
693 op="who-has",
694 hwsrc=self.pg0.remote_mac,
695 psrc="100.100.100.50",
696 pdst=self.pg0.remote_ip4,
697 )
698 self.send_and_assert_no_replies(self.pg0, p, "ARP req for from failed adj-fib")
Neale Rannsca193612017-06-14 06:50:08 -0700699
700 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800701 # ERROR Cases
702 # 1 - don't respond to ARP request for address not within the
703 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700704 # 1b - nor within the unnumbered subnet
705 # 1c - nor within the subnet of a different interface
706 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200707 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
708 op="who-has",
709 hwsrc=self.pg0.remote_mac,
710 pdst="10.10.10.3",
711 psrc=self.pg0.remote_ip4,
712 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800713 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200714 self.pg0, p, "ARP req for non-local destination"
715 )
716 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, "10.10.10.3"))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800717
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200718 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
719 op="who-has",
720 hwsrc=self.pg2.remote_mac,
721 pdst="10.10.10.3",
722 psrc=self.pg1.remote_hosts[7].ip4,
723 )
724 self.send_and_assert_no_replies(
725 self.pg0, p, "ARP req for non-local destination - unnum"
726 )
727
728 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
729 op="who-has",
730 hwsrc=self.pg0.remote_mac,
731 pdst=self.pg1.local_ip4,
732 psrc=self.pg1.remote_ip4,
733 )
734 self.send_and_assert_no_replies(self.pg0, p, "ARP req diff sub-net")
735 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700736
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800737 #
738 # 2 - don't respond to ARP request from an address not within the
739 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700740 # 2b - to a proxied address
741 # 2c - not within a different interface's sub-net
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200742 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
743 op="who-has",
744 hwsrc=self.pg0.remote_mac,
745 psrc="10.10.10.3",
746 pdst=self.pg0.local_ip4,
747 )
748 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
749 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
750 op="who-has",
751 hwsrc=self.pg2.remote_mac,
752 psrc="10.10.10.3",
753 pdst=self.pg0.local_ip4,
754 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800755 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200756 self.pg0, p, "ARP req for non-local source - unnum"
757 )
758 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
759 op="who-has",
760 hwsrc=self.pg0.remote_mac,
761 psrc=self.pg1.remote_ip4,
762 pdst=self.pg0.local_ip4,
763 )
764 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800765
766 #
767 # 3 - don't respond to ARP request from an address that belongs to
768 # the router
769 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200770 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
771 op="who-has",
772 hwsrc=self.pg0.remote_mac,
773 psrc=self.pg0.local_ip4,
774 pdst=self.pg0.local_ip4,
775 )
776 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800777
778 #
779 # 4 - don't respond to ARP requests that has mac source different
780 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800781 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200782 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
783 op="who-has",
784 hwsrc="00:00:00:DE:AD:BE",
785 psrc=self.pg0.remote_ip4,
786 pdst=self.pg0.local_ip4,
787 )
788 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800789
790 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800791 # 5 - don't respond to ARP requests for address within the
792 # interface's sub-net but not the interface's address
793 #
794 self.pg0.generate_remote_hosts(2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200795 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
796 op="who-has",
797 hwsrc=self.pg0.remote_mac,
798 psrc=self.pg0.remote_hosts[0].ip4,
799 pdst=self.pg0.remote_hosts[1].ip4,
800 )
801 self.send_and_assert_no_replies(
802 self.pg0, p, "ARP req for non-local destination"
803 )
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800804
805 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800806 # cleanup
807 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800808 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800809 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800810
Neale Ranns4b919a52017-03-11 05:55:21 -0800811 # need this to flush the adj-fibs
812 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
813 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700814 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800815
Neale Ranns24b170a2017-08-15 05:33:11 -0700816 def test_proxy_mirror_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200817 """Interface Mirror Proxy ARP"""
Neale Ranns24b170a2017-08-15 05:33:11 -0700818
819 #
820 # When VPP has an interface whose address is also applied to a TAP
821 # interface on the host, then VPP's TAP interface will be unnumbered
822 # to the 'real' interface and do proxy ARP from the host.
823 # the curious aspect of this setup is that ARP requests from the host
824 # will come from the VPP's own address.
825 #
826 self.pg0.generate_remote_hosts(2)
827
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200828 arp_req_from_me = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
829 op="who-has",
830 hwsrc=self.pg2.remote_mac,
831 pdst=self.pg0.remote_hosts[1].ip4,
832 psrc=self.pg0.local_ip4,
833 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700834
835 #
836 # Configure Proxy ARP for the subnet on PG0addresses on pg0
837 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200838 self.vapi.proxy_arp_add_del(
839 proxy={
840 "table_id": 0,
841 "low": self.pg0._local_ip4_subnet,
842 "hi": self.pg0._local_ip4_bcast,
843 },
844 is_add=1,
845 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700846
847 # Make pg2 un-numbered to pg0
848 #
849 self.pg2.set_unnumbered(self.pg0.sw_if_index)
850
851 #
852 # Enable pg2 for proxy ARP
853 #
854 self.pg2.set_proxy_arp()
855
856 #
857 # Send the ARP request with an originating address that
858 # is VPP's own address
859 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000860 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200861 self.verify_arp_resp(
862 rx[0],
863 self.pg2.local_mac,
864 self.pg2.remote_mac,
865 self.pg0.remote_hosts[1].ip4,
866 self.pg0.local_ip4,
867 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700868
869 #
870 # validate we have not learned an ARP entry as a result of this
871 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200872 self.assertFalse(find_nbr(self, self.pg2.sw_if_index, self.pg0.local_ip4))
Neale Ranns24b170a2017-08-15 05:33:11 -0700873
874 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000875 # setup a punt redirect so packets from the uplink go to the tap
876 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200877 redirect = VppIpPuntRedirect(
878 self, self.pg0.sw_if_index, self.pg2.sw_if_index, self.pg0.local_ip4
879 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100880 redirect.add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +0000881
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200882 p_tcp = (
883 Ether(
884 src=self.pg0.remote_mac,
885 dst=self.pg0.local_mac,
886 )
887 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
888 / TCP(sport=80, dport=80)
889 / Raw()
890 )
Neale Ranns240dcb22020-04-23 09:04:59 +0000891 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
892
893 # there's no ARP entry so this is an ARP req
894 self.assertTrue(rx[0].haslayer(ARP))
895
896 # and ARP entry for VPP's pg0 address on the host interface
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200897 n1 = VppNeighbor(
898 self,
899 self.pg2.sw_if_index,
900 self.pg2.remote_mac,
901 self.pg0.local_ip4,
902 is_no_fib_entry=True,
903 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +0000904 # now the packets shold forward
905 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
906 self.assertFalse(rx[0].haslayer(ARP))
907 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
908
909 #
910 # flush the neighbor cache on the uplink
911 #
912 af = VppEnum.vl_api_address_family_t
913 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
914
915 # ensure we can still resolve the ARPs on the uplink
916 self.pg0.resolve_arp()
917
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200918 self.assertTrue(find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_ip4))
Neale Ranns240dcb22020-04-23 09:04:59 +0000919
920 #
Neale Ranns24b170a2017-08-15 05:33:11 -0700921 # cleanup
922 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200923 self.vapi.proxy_arp_add_del(
924 proxy={
925 "table_id": 0,
926 "low": self.pg0._local_ip4_subnet,
927 "hi": self.pg0._local_ip4_bcast,
928 },
929 is_add=0,
930 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100931 redirect.remove_vpp_config()
Neale Ranns24b170a2017-08-15 05:33:11 -0700932
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800933 def test_proxy_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200934 """Proxy ARP"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800935
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700936 self.pg1.generate_remote_hosts(2)
937
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800938 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700939 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800940 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200941 arp_req_pg0 = Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
942 op="who-has",
943 hwsrc=self.pg0.remote_mac,
944 pdst="10.10.10.3",
945 psrc=self.pg0.remote_ip4,
946 )
947 arp_req_pg0_tagged = (
948 Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff")
949 / Dot1Q(vlan=0)
950 / ARP(
951 op="who-has",
952 hwsrc=self.pg0.remote_mac,
953 pdst="10.10.10.3",
954 psrc=self.pg0.remote_ip4,
955 )
956 )
957 arp_req_pg1 = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
958 op="who-has",
959 hwsrc=self.pg1.remote_mac,
960 pdst="10.10.10.3",
961 psrc=self.pg1.remote_ip4,
962 )
963 arp_req_pg2 = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
964 op="who-has",
965 hwsrc=self.pg2.remote_mac,
966 pdst="10.10.10.3",
967 psrc=self.pg1.remote_hosts[1].ip4,
968 )
969 arp_req_pg3 = Ether(src=self.pg3.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
970 op="who-has",
971 hwsrc=self.pg3.remote_mac,
972 pdst="10.10.10.3",
973 psrc=self.pg3.remote_ip4,
974 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800975
976 #
977 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
978 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200979 self.vapi.proxy_arp_add_del(
980 proxy={"table_id": 0, "low": "10.10.10.2", "hi": "10.10.10.124"}, is_add=1
981 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800982
983 #
984 # No responses are sent when the interfaces are not enabled for proxy
985 # ARP
986 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200987 self.send_and_assert_no_replies(
988 self.pg0, arp_req_pg0, "ARP req from unconfigured interface"
989 )
990 self.send_and_assert_no_replies(
991 self.pg2, arp_req_pg2, "ARP req from unconfigured interface"
992 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800993
994 #
995 # Make pg2 un-numbered to pg1
996 # still won't reply.
997 #
998 self.pg2.set_unnumbered(self.pg1.sw_if_index)
999
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001000 self.send_and_assert_no_replies(
1001 self.pg2, arp_req_pg2, "ARP req from unnumbered interface"
1002 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001003
1004 #
1005 # Enable each interface to reply to proxy ARPs
1006 #
1007 for i in self.pg_interfaces:
1008 i.set_proxy_arp()
1009
1010 #
1011 # Now each of the interfaces should reply to a request to a proxied
1012 # address
1013 #
1014 self.pg0.add_stream(arp_req_pg0)
1015 self.pg_enable_capture(self.pg_interfaces)
1016 self.pg_start()
1017
1018 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001019 self.verify_arp_resp(
1020 rx[0],
1021 self.pg0.local_mac,
1022 self.pg0.remote_mac,
1023 "10.10.10.3",
1024 self.pg0.remote_ip4,
1025 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001026
Neale Ranns30d0fd42017-05-30 07:30:04 -07001027 self.pg0.add_stream(arp_req_pg0_tagged)
1028 self.pg_enable_capture(self.pg_interfaces)
1029 self.pg_start()
1030
1031 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001032 self.verify_arp_resp(
1033 rx[0],
1034 self.pg0.local_mac,
1035 self.pg0.remote_mac,
1036 "10.10.10.3",
1037 self.pg0.remote_ip4,
1038 )
Neale Ranns30d0fd42017-05-30 07:30:04 -07001039
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001040 self.pg1.add_stream(arp_req_pg1)
1041 self.pg_enable_capture(self.pg_interfaces)
1042 self.pg_start()
1043
1044 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001045 self.verify_arp_resp(
1046 rx[0],
1047 self.pg1.local_mac,
1048 self.pg1.remote_mac,
1049 "10.10.10.3",
1050 self.pg1.remote_ip4,
1051 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001052
1053 self.pg2.add_stream(arp_req_pg2)
1054 self.pg_enable_capture(self.pg_interfaces)
1055 self.pg_start()
1056
1057 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001058 self.verify_arp_resp(
1059 rx[0],
1060 self.pg2.local_mac,
1061 self.pg2.remote_mac,
1062 "10.10.10.3",
1063 self.pg1.remote_hosts[1].ip4,
1064 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001065
1066 #
1067 # A request for an address out of the configured range
1068 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001069 arp_req_pg1_hi = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1070 op="who-has",
1071 hwsrc=self.pg1.remote_mac,
1072 pdst="10.10.10.125",
1073 psrc=self.pg1.remote_ip4,
1074 )
1075 self.send_and_assert_no_replies(
1076 self.pg1, arp_req_pg1_hi, "ARP req out of range HI"
1077 )
1078 arp_req_pg1_low = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1079 op="who-has",
1080 hwsrc=self.pg1.remote_mac,
1081 pdst="10.10.10.1",
1082 psrc=self.pg1.remote_ip4,
1083 )
1084 self.send_and_assert_no_replies(
1085 self.pg1, arp_req_pg1_low, "ARP req out of range Low"
1086 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001087
1088 #
1089 # Request for an address in the proxy range but from an interface
1090 # in a different VRF
1091 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001092 self.send_and_assert_no_replies(
1093 self.pg3, arp_req_pg3, "ARP req from different VRF"
1094 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001095
1096 #
1097 # Disable Each interface for proxy ARP
1098 # - expect none to respond
1099 #
1100 for i in self.pg_interfaces:
1101 i.set_proxy_arp(0)
1102
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001103 self.send_and_assert_no_replies(self.pg0, arp_req_pg0, "ARP req from disable")
1104 self.send_and_assert_no_replies(self.pg1, arp_req_pg1, "ARP req from disable")
1105 self.send_and_assert_no_replies(self.pg2, arp_req_pg2, "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001106
1107 #
1108 # clean up on interface 2
1109 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001110 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001111
1112 def test_mpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001113 """MPLS"""
Neale Ranns37be7362017-02-21 17:30:26 -08001114
1115 #
1116 # Interface 2 does not yet have ip4 config
1117 #
1118 self.pg2.config_ip4()
1119 self.pg2.generate_remote_hosts(2)
1120
1121 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001122 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001123 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001124 ip_10_0_0_1 = VppIpRoute(
1125 self,
1126 "10.0.0.1",
1127 32,
1128 [
1129 VppRoutePath(
1130 self.pg2.remote_hosts[1].ip4, self.pg2.sw_if_index, labels=[55]
1131 )
1132 ],
1133 )
Neale Ranns37be7362017-02-21 17:30:26 -08001134 ip_10_0_0_1.add_vpp_config()
1135
1136 #
1137 # packets should generate an ARP request
1138 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001139 p = (
1140 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1141 / IP(src=self.pg0.remote_ip4, dst="10.0.0.1")
1142 / UDP(sport=1234, dport=1234)
1143 / Raw(b"\xa5" * 100)
1144 )
Neale Ranns37be7362017-02-21 17:30:26 -08001145
1146 self.pg0.add_stream(p)
1147 self.pg_enable_capture(self.pg_interfaces)
1148 self.pg_start()
1149
1150 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001151 self.verify_arp_req(
1152 rx[0], self.pg2.local_mac, self.pg2.local_ip4, self.pg2._remote_hosts[1].ip4
1153 )
Neale Ranns37be7362017-02-21 17:30:26 -08001154
1155 #
1156 # now resolve the neighbours
1157 #
1158 self.pg2.configure_ipv4_neighbors()
1159
1160 #
1161 # Now packet should be properly MPLS encapped.
1162 # This verifies that MPLS link-type adjacencies are completed
1163 # when the ARP entry resolves
1164 #
1165 self.pg0.add_stream(p)
1166 self.pg_enable_capture(self.pg_interfaces)
1167 self.pg_start()
1168
1169 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001170 self.verify_ip_o_mpls(
1171 rx[0],
1172 self.pg2.local_mac,
1173 self.pg2.remote_hosts[1].mac,
1174 55,
1175 self.pg0.remote_ip4,
1176 "10.0.0.1",
1177 )
Neale Ranns4b919a52017-03-11 05:55:21 -08001178 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001179
Matthew Smithcb9ab472017-05-16 21:35:56 -05001180 def test_arp_vrrp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001181 """ARP reply with VRRP virtual src hw addr"""
Matthew Smithcb9ab472017-05-16 21:35:56 -05001182
1183 #
1184 # IP packet destined for pg1 remote host arrives on pg0 resulting
1185 # in an ARP request for the address of the remote host on pg1
1186 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001187 p0 = (
1188 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1189 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1190 / UDP(sport=1234, dport=1234)
1191 / Raw()
1192 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001193
Neale Ranns37029302018-08-10 05:30:06 -07001194 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001195
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001196 self.verify_arp_req(
1197 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
1198 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001199
1200 #
1201 # ARP reply for address of pg1 remote host arrives on pg1 with
1202 # the hw src addr set to a value in the VRRP IPv4 range of
1203 # MAC addresses
1204 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001205 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
1206 op="is-at",
1207 hwdst=self.pg1.local_mac,
1208 hwsrc="00:00:5e:00:01:09",
1209 pdst=self.pg1.local_ip4,
1210 psrc=self.pg1.remote_ip4,
1211 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001212
Neale Ranns37029302018-08-10 05:30:06 -07001213 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001214
1215 #
1216 # IP packet destined for pg1 remote host arrives on pg0 again.
1217 # VPP should have an ARP entry for that address now and the packet
1218 # should be sent out pg1.
1219 #
Neale Ranns37029302018-08-10 05:30:06 -07001220 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001221
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001222 self.verify_ip(
1223 rx1[0],
1224 self.pg1.local_mac,
1225 "00:00:5e:00:01:09",
1226 self.pg0.remote_ip4,
1227 self.pg1.remote_ip4,
1228 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001229
1230 self.pg1.admin_down()
1231 self.pg1.admin_up()
1232
Neale Rannsdcd6d622017-05-26 02:59:16 -07001233 def test_arp_duplicates(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001234 """ARP Duplicates"""
Neale Rannsdcd6d622017-05-26 02:59:16 -07001235
1236 #
1237 # Generate some hosts on the LAN
1238 #
1239 self.pg1.generate_remote_hosts(3)
1240
1241 #
1242 # Add host 1 on pg1 and pg2
1243 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001244 arp_pg1 = VppNeighbor(
1245 self,
1246 self.pg1.sw_if_index,
1247 self.pg1.remote_hosts[1].mac,
1248 self.pg1.remote_hosts[1].ip4,
1249 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001250 arp_pg1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001251 arp_pg2 = VppNeighbor(
1252 self,
1253 self.pg2.sw_if_index,
1254 self.pg2.remote_mac,
1255 self.pg1.remote_hosts[1].ip4,
1256 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001257 arp_pg2.add_vpp_config()
1258
1259 #
1260 # IP packet destined for pg1 remote host arrives on pg1 again.
1261 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001262 p = (
1263 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1264 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1265 / UDP(sport=1234, dport=1234)
1266 / Raw()
1267 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001268
1269 self.pg0.add_stream(p)
1270 self.pg_enable_capture(self.pg_interfaces)
1271 self.pg_start()
1272
1273 rx1 = self.pg1.get_capture(1)
1274
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001275 self.verify_ip(
1276 rx1[0],
1277 self.pg1.local_mac,
1278 self.pg1.remote_hosts[1].mac,
1279 self.pg0.remote_ip4,
1280 self.pg1.remote_hosts[1].ip4,
1281 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001282
1283 #
1284 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001285 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001286 #
1287 arp_pg1.remove_vpp_config()
1288
1289 self.pg0.add_stream(p)
1290 self.pg_enable_capture(self.pg_interfaces)
1291 self.pg_start()
1292
1293 rx1 = self.pg1.get_capture(1)
1294
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001295 self.verify_arp_req(
1296 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_hosts[1].ip4
1297 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001298
1299 #
1300 # Add it back
1301 #
1302 arp_pg1.add_vpp_config()
1303
1304 self.pg0.add_stream(p)
1305 self.pg_enable_capture(self.pg_interfaces)
1306 self.pg_start()
1307
1308 rx1 = self.pg1.get_capture(1)
1309
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001310 self.verify_ip(
1311 rx1[0],
1312 self.pg1.local_mac,
1313 self.pg1.remote_hosts[1].mac,
1314 self.pg0.remote_ip4,
1315 self.pg1.remote_hosts[1].ip4,
1316 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001317
Neale Ranns15002542017-09-10 04:39:11 -07001318 def test_arp_static(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001319 """ARP Static"""
Neale Ranns15002542017-09-10 04:39:11 -07001320 self.pg2.generate_remote_hosts(3)
1321
1322 #
1323 # Add a static ARP entry
1324 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001325 static_arp = VppNeighbor(
1326 self,
1327 self.pg2.sw_if_index,
1328 self.pg2.remote_hosts[1].mac,
1329 self.pg2.remote_hosts[1].ip4,
1330 is_static=1,
1331 )
Neale Ranns15002542017-09-10 04:39:11 -07001332 static_arp.add_vpp_config()
1333
1334 #
1335 # Add the connected prefix to the interface
1336 #
1337 self.pg2.config_ip4()
1338
1339 #
1340 # We should now find the adj-fib
1341 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001342 self.assertTrue(
1343 find_nbr(
1344 self, self.pg2.sw_if_index, self.pg2.remote_hosts[1].ip4, is_static=1
1345 )
1346 )
1347 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32))
Neale Ranns15002542017-09-10 04:39:11 -07001348
1349 #
1350 # remove the connected
1351 #
1352 self.pg2.unconfig_ip4()
1353
1354 #
1355 # put the interface into table 1
1356 #
1357 self.pg2.set_table_ip4(1)
1358
1359 #
1360 # configure the same connected and expect to find the
1361 # adj fib in the new table
1362 #
1363 self.pg2.config_ip4()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001364 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32, table_id=1))
Neale Ranns15002542017-09-10 04:39:11 -07001365
1366 #
1367 # clean-up
1368 #
1369 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001370 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001371 self.pg2.set_table_ip4(0)
1372
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001373 def test_arp_static_replace_dynamic_same_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001374 """ARP Static can replace Dynamic (same mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001375 self.pg2.generate_remote_hosts(1)
1376
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001377 dyn_arp = VppNeighbor(
1378 self,
1379 self.pg2.sw_if_index,
1380 self.pg2.remote_hosts[0].mac,
1381 self.pg2.remote_hosts[0].ip4,
1382 )
1383 static_arp = VppNeighbor(
1384 self,
1385 self.pg2.sw_if_index,
1386 self.pg2.remote_hosts[0].mac,
1387 self.pg2.remote_hosts[0].ip4,
1388 is_static=1,
1389 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001390
1391 #
1392 # Add a dynamic ARP entry
1393 #
1394 dyn_arp.add_vpp_config()
1395
1396 #
1397 # We should find the dynamic nbr
1398 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001399 self.assertFalse(
1400 find_nbr(
1401 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1402 )
1403 )
1404 self.assertTrue(
1405 find_nbr(
1406 self,
1407 self.pg2.sw_if_index,
1408 self.pg2.remote_hosts[0].ip4,
1409 is_static=0,
1410 mac=self.pg2.remote_hosts[0].mac,
1411 )
1412 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001413
1414 #
1415 # Add a static ARP entry with the same mac
1416 #
1417 static_arp.add_vpp_config()
1418
1419 #
1420 # We should now find the static nbr with the same mac
1421 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001422 self.assertFalse(
1423 find_nbr(
1424 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1425 )
1426 )
1427 self.assertTrue(
1428 find_nbr(
1429 self,
1430 self.pg2.sw_if_index,
1431 self.pg2.remote_hosts[0].ip4,
1432 is_static=1,
1433 mac=self.pg2.remote_hosts[0].mac,
1434 )
1435 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001436
1437 #
1438 # clean-up
1439 #
1440 static_arp.remove_vpp_config()
1441
1442 def test_arp_static_replace_dynamic_diff_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001443 """ARP Static can replace Dynamic (diff mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001444 self.pg2.generate_remote_hosts(2)
1445
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001446 dyn_arp = VppNeighbor(
1447 self,
1448 self.pg2.sw_if_index,
1449 self.pg2.remote_hosts[0].mac,
1450 self.pg2.remote_hosts[0].ip4,
1451 )
1452 static_arp = VppNeighbor(
1453 self,
1454 self.pg2.sw_if_index,
1455 self.pg2.remote_hosts[1].mac,
1456 self.pg2.remote_hosts[0].ip4,
1457 is_static=1,
1458 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001459
1460 #
1461 # Add a dynamic ARP entry
1462 #
1463 dyn_arp.add_vpp_config()
1464
1465 #
1466 # We should find the dynamic nbr
1467 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001468 self.assertFalse(
1469 find_nbr(
1470 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1471 )
1472 )
1473 self.assertTrue(
1474 find_nbr(
1475 self,
1476 self.pg2.sw_if_index,
1477 self.pg2.remote_hosts[0].ip4,
1478 is_static=0,
1479 mac=self.pg2.remote_hosts[0].mac,
1480 )
1481 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001482
1483 #
1484 # Add a static ARP entry with a changed mac
1485 #
1486 static_arp.add_vpp_config()
1487
1488 #
1489 # We should now find the static nbr with a changed mac
1490 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001491 self.assertFalse(
1492 find_nbr(
1493 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1494 )
1495 )
1496 self.assertTrue(
1497 find_nbr(
1498 self,
1499 self.pg2.sw_if_index,
1500 self.pg2.remote_hosts[0].ip4,
1501 is_static=1,
1502 mac=self.pg2.remote_hosts[1].mac,
1503 )
1504 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001505
1506 #
1507 # clean-up
1508 #
1509 static_arp.remove_vpp_config()
1510
Neale Rannsc819fc62018-02-16 02:44:05 -08001511 def test_arp_incomplete(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001512 """ARP Incomplete"""
Neale Rannsea8adf72021-08-13 08:10:59 +00001513 self.pg1.generate_remote_hosts(4)
Neale Rannsc819fc62018-02-16 02:44:05 -08001514
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001515 p0 = (
1516 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1517 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1518 / UDP(sport=1234, dport=1234)
1519 / Raw()
1520 )
1521 p1 = (
1522 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1523 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
1524 / UDP(sport=1234, dport=1234)
1525 / Raw()
1526 )
1527 p2 = (
1528 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1529 / IP(src=self.pg0.remote_ip4, dst="1.1.1.1")
1530 / UDP(sport=1234, dport=1234)
1531 / Raw()
1532 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001533
1534 #
1535 # a packet to an unresolved destination generates an ARP request
1536 #
1537 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001538 self.verify_arp_req(
1539 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
1540 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001541
1542 #
1543 # add a neighbour for remote host 1
1544 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001545 static_arp = VppNeighbor(
1546 self,
1547 self.pg1.sw_if_index,
1548 self.pg1.remote_hosts[1].mac,
1549 self.pg1.remote_hosts[1].ip4,
1550 is_static=1,
1551 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001552 static_arp.add_vpp_config()
1553
1554 #
Neale Rannsea8adf72021-08-13 08:10:59 +00001555 # add a route through remote host 3 hence we get an incomplete
1556 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001557 VppIpRoute(
1558 self,
1559 "1.1.1.1",
1560 32,
1561 [VppRoutePath(self.pg1.remote_hosts[3].ip4, self.pg1.sw_if_index)],
1562 ).add_vpp_config()
Neale Rannsea8adf72021-08-13 08:10:59 +00001563 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001564 self.verify_arp_req(
1565 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[3].ip4
1566 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001567
1568 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001569 # change the interface's MAC
1570 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001571 self.vapi.sw_interface_set_mac_address(
1572 self.pg1.sw_if_index, "00:00:00:33:33:33"
1573 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001574
1575 #
1576 # now ARP requests come from the new source mac
1577 #
1578 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001579 self.verify_arp_req(
1580 rx[0],
1581 "00:00:00:33:33:33",
1582 self.pg1.local_ip4,
1583 self.pg1._remote_hosts[2].ip4,
1584 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001585 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001586 self.verify_arp_req(
1587 rx[0],
1588 "00:00:00:33:33:33",
1589 self.pg1.local_ip4,
1590 self.pg1._remote_hosts[3].ip4,
1591 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001592
1593 #
1594 # packets to the resolved host also have the new source mac
1595 #
1596 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001597 self.verify_ip(
1598 rx[0],
1599 "00:00:00:33:33:33",
1600 self.pg1.remote_hosts[1].mac,
1601 self.pg0.remote_ip4,
1602 self.pg1.remote_hosts[1].ip4,
1603 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001604
1605 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001606 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001607 # configured subnet and thus no glean
1608 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001609 self.vapi.sw_interface_set_mac_address(
1610 self.pg2.sw_if_index, "00:00:00:33:33:33"
1611 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001612
Neale Ranns59ae61e2018-06-07 18:09:49 -07001613 def test_garp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001614 """GARP"""
Neale Ranns59ae61e2018-06-07 18:09:49 -07001615
1616 #
1617 # Generate some hosts on the LAN
1618 #
1619 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001620 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001621
1622 #
1623 # And an ARP entry
1624 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001625 arp = VppNeighbor(
1626 self,
1627 self.pg1.sw_if_index,
1628 self.pg1.remote_hosts[1].mac,
1629 self.pg1.remote_hosts[1].ip4,
1630 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001631 arp.add_vpp_config()
1632
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001633 self.assertTrue(
1634 find_nbr(
1635 self,
1636 self.pg1.sw_if_index,
1637 self.pg1.remote_hosts[1].ip4,
1638 mac=self.pg1.remote_hosts[1].mac,
1639 )
1640 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001641
1642 #
1643 # Send a GARP (request) to swap the host 1's address to that of host 2
1644 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001645 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[2].mac) / ARP(
1646 op="who-has",
1647 hwdst=self.pg1.local_mac,
1648 hwsrc=self.pg1.remote_hosts[2].mac,
1649 pdst=self.pg1.remote_hosts[1].ip4,
1650 psrc=self.pg1.remote_hosts[1].ip4,
1651 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001652
1653 self.pg1.add_stream(p1)
1654 self.pg_enable_capture(self.pg_interfaces)
1655 self.pg_start()
1656
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001657 self.assertTrue(
1658 find_nbr(
1659 self,
1660 self.pg1.sw_if_index,
1661 self.pg1.remote_hosts[1].ip4,
1662 mac=self.pg1.remote_hosts[2].mac,
1663 )
1664 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001665
1666 #
1667 # Send a GARP (reply) to swap the host 1's address to that of host 3
1668 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001669 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1670 op="is-at",
1671 hwdst=self.pg1.local_mac,
1672 hwsrc=self.pg1.remote_hosts[3].mac,
1673 pdst=self.pg1.remote_hosts[1].ip4,
1674 psrc=self.pg1.remote_hosts[1].ip4,
1675 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001676
1677 self.pg1.add_stream(p1)
1678 self.pg_enable_capture(self.pg_interfaces)
1679 self.pg_start()
1680
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001681 self.assertTrue(
1682 find_nbr(
1683 self,
1684 self.pg1.sw_if_index,
1685 self.pg1.remote_hosts[1].ip4,
1686 mac=self.pg1.remote_hosts[3].mac,
1687 )
1688 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001689
1690 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001691 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001692 # don't result in new neighbour entries
1693 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001694 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1695 op="who-has",
1696 hwdst=self.pg1.local_mac,
1697 hwsrc=self.pg1.remote_hosts[3].mac,
1698 pdst=self.pg1.remote_hosts[2].ip4,
1699 psrc=self.pg1.remote_hosts[2].ip4,
1700 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001701
1702 self.pg1.add_stream(p1)
1703 self.pg_enable_capture(self.pg_interfaces)
1704 self.pg_start()
1705
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001706 self.assertFalse(
1707 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1708 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001709
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001710 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1711 op="is-at",
1712 hwdst=self.pg1.local_mac,
1713 hwsrc=self.pg1.remote_hosts[3].mac,
1714 pdst=self.pg1.remote_hosts[2].ip4,
1715 psrc=self.pg1.remote_hosts[2].ip4,
1716 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001717
1718 self.pg1.add_stream(p1)
1719 self.pg_enable_capture(self.pg_interfaces)
1720 self.pg_start()
1721
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001722 self.assertFalse(
1723 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1724 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001725
Neale Ranns22eefd72020-09-23 11:25:21 +00001726 #
1727 # IP address in different subnets are not learnt
1728 #
1729 self.pg2.configure_ipv4_neighbors()
1730
1731 for op in ["is-at", "who-has"]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001732 p1 = [
1733 (
1734 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1735 / ARP(
1736 op=op,
1737 hwdst=self.pg2.local_mac,
1738 hwsrc=self.pg2.remote_hosts[1].mac,
1739 pdst=self.pg2.remote_hosts[1].ip4,
1740 psrc=self.pg2.remote_hosts[1].ip4,
1741 )
1742 ),
1743 (
1744 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1745 / ARP(
1746 op=op,
1747 hwdst="ff:ff:ff:ff:ff:ff",
1748 hwsrc=self.pg2.remote_hosts[1].mac,
1749 pdst=self.pg2.remote_hosts[1].ip4,
1750 psrc=self.pg2.remote_hosts[1].ip4,
1751 )
1752 ),
1753 ]
Neale Ranns22eefd72020-09-23 11:25:21 +00001754
1755 self.send_and_assert_no_replies(self.pg1, p1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001756 self.assertFalse(
1757 find_nbr(self, self.pg1.sw_if_index, self.pg2.remote_hosts[1].ip4)
1758 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001759
1760 # they are all dropped because the subnet's don't match
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001761 self.assertEqual(
1762 4,
1763 self.statistics.get_err_counter(
1764 "/err/arp-reply/IP4 destination address not local to subnet"
1765 ),
1766 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001767
Neale Ranns77f91622020-11-23 16:25:27 +00001768 def test_arp_incomplete2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001769 """Incomplete Entries"""
Neale Rannsc8352bc2018-08-29 10:23:58 -07001770
1771 #
Neale Rannscd35e532018-08-31 02:51:45 -07001772 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001773 #
1774 self.pg0.generate_remote_hosts(2)
1775
Neale Rannscd35e532018-08-31 02:51:45 -07001776 #
1777 # IPv4/ARP
1778 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001779 ip_10_0_0_1 = VppIpRoute(
1780 self,
1781 "10.0.0.1",
1782 32,
1783 [VppRoutePath(self.pg0.remote_hosts[1].ip4, self.pg0.sw_if_index)],
1784 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001785 ip_10_0_0_1.add_vpp_config()
1786
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001787 p1 = (
1788 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1789 / IP(src=self.pg1.remote_ip4, dst="10.0.0.1")
1790 / UDP(sport=1234, dport=1234)
1791 / Raw()
1792 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001793
1794 self.pg1.add_stream(p1 * 257)
1795 self.pg_enable_capture(self.pg_interfaces)
1796 self.pg_start()
1797 rx = self.pg0._get_capture(1)
1798
1799 #
1800 # how many we get is going to be dependent on the time for packet
1801 # processing but it should be small
1802 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001803 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001804
Neale Rannscd35e532018-08-31 02:51:45 -07001805 #
1806 # IPv6/ND
1807 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001808 ip_10_1 = VppIpRoute(
1809 self,
1810 "10::1",
1811 128,
1812 [
1813 VppRoutePath(
1814 self.pg0.remote_hosts[1].ip6,
1815 self.pg0.sw_if_index,
1816 proto=DpoProto.DPO_PROTO_IP6,
1817 )
1818 ],
1819 )
Neale Rannscd35e532018-08-31 02:51:45 -07001820 ip_10_1.add_vpp_config()
1821
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001822 p1 = (
1823 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1824 / IPv6(src=self.pg1.remote_ip6, dst="10::1")
1825 / UDP(sport=1234, dport=1234)
1826 / Raw()
1827 )
Neale Rannscd35e532018-08-31 02:51:45 -07001828
1829 self.pg1.add_stream(p1 * 257)
1830 self.pg_enable_capture(self.pg_interfaces)
1831 self.pg_start()
1832 rx = self.pg0._get_capture(1)
1833
1834 #
1835 # how many we get is going to be dependent on the time for packet
1836 # processing but it should be small
1837 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001838 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001839
Neale Ranns7425f922019-01-23 00:36:16 -08001840 def test_arp_forus(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001841 """ARP for for-us"""
Neale Ranns7425f922019-01-23 00:36:16 -08001842
1843 #
1844 # Test that VPP responds with ARP requests to addresses that
1845 # are connected and local routes.
1846 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001847 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001848 # address added to an interface
1849 #
1850 self.pg0.generate_remote_hosts(2)
1851
Neale Ranns097fa662018-05-01 05:17:55 -07001852 forus = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001853 self,
1854 self.pg0.remote_hosts[1].ip4,
1855 32,
1856 [
1857 VppRoutePath(
1858 "0.0.0.0",
1859 self.pg0.sw_if_index,
1860 type=FibPathType.FIB_PATH_TYPE_LOCAL,
1861 )
1862 ],
1863 )
Neale Ranns7425f922019-01-23 00:36:16 -08001864 forus.add_vpp_config()
1865
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001866 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
1867 op="who-has",
1868 hwdst=self.pg0.local_mac,
1869 hwsrc=self.pg0.remote_mac,
1870 pdst=self.pg0.remote_hosts[1].ip4,
1871 psrc=self.pg0.remote_ip4,
1872 )
Neale Ranns7425f922019-01-23 00:36:16 -08001873
1874 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1875
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001876 self.verify_arp_resp(
1877 rx[0],
1878 self.pg0.local_mac,
1879 self.pg0.remote_mac,
1880 self.pg0.remote_hosts[1].ip4,
1881 self.pg0.remote_ip4,
1882 )
Neale Ranns7425f922019-01-23 00:36:16 -08001883
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001884 def test_arp_table_swap(self):
1885 #
1886 # Generate some hosts on the LAN
1887 #
1888 N_NBRS = 4
1889 self.pg1.generate_remote_hosts(N_NBRS)
1890
1891 for n in range(N_NBRS):
1892 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001893 VppIpRoute(
1894 self,
1895 "10.0.0.%d" % n,
1896 32,
1897 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
1898 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001899
1900 # resolve each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001901 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
1902 op="is-at",
1903 hwdst=self.pg1.local_mac,
1904 hwsrc="00:00:5e:00:01:09",
1905 pdst=self.pg1.local_ip4,
1906 psrc=self.pg1.remote_hosts[n].ip4,
1907 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001908
1909 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1910
1911 self.logger.info(self.vapi.cli("sh ip neighbors"))
1912
1913 #
1914 # swap the table pg1 is in
1915 #
1916 table = VppIpTable(self, 100).add_vpp_config()
1917
1918 self.pg1.unconfig_ip4()
1919 self.pg1.set_table_ip4(100)
1920 self.pg1.config_ip4()
1921
1922 #
1923 # all neighbours are cleared
1924 #
1925 for n in range(N_NBRS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001926 self.assertFalse(
1927 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip4)
1928 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001929
1930 #
1931 # packets to all neighbours generate ARP requests
1932 #
1933 for n in range(N_NBRS):
1934 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001935 VppIpRoute(
1936 self,
1937 "10.0.0.%d" % n,
1938 32,
1939 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
1940 table_id=100,
1941 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001942
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001943 p = (
1944 Ether(src=self.pg1.remote_hosts[n].mac, dst=self.pg1.local_mac)
1945 / IP(src=self.pg1.remote_hosts[n].ip4, dst="10.0.0.%d" % n)
1946 / Raw(b"0x5" * 100)
1947 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001948 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1949 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001950 self.verify_arp_req(
1951 rx,
1952 self.pg1.local_mac,
1953 self.pg1.local_ip4,
1954 self.pg1.remote_hosts[n].ip4,
1955 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001956
1957 self.pg1.unconfig_ip4()
1958 self.pg1.set_table_ip4(0)
1959
Neale Rannse2fe0972020-11-26 08:37:27 +00001960 def test_glean_src_select(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001961 """Multi Connecteds"""
Neale Rannse2fe0972020-11-26 08:37:27 +00001962
1963 #
1964 # configure multiple connected subnets on an interface
1965 # and ensure that ARP requests for hosts on those subnets
1966 # pick up the correct source address
1967 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001968 conn1 = VppIpInterfaceAddress(self, self.pg1, "10.0.0.1", 24).add_vpp_config()
1969 conn2 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.1", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00001970
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001971 p1 = (
1972 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1973 / IP(src=self.pg1.remote_ip4, dst="10.0.0.128")
1974 / Raw(b"0x5" * 100)
1975 )
Neale Rannse2fe0972020-11-26 08:37:27 +00001976
1977 rxs = self.send_and_expect(self.pg0, [p1], self.pg1)
1978 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001979 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.0.1", "10.0.0.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00001980
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001981 p2 = (
1982 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1983 / IP(src=self.pg1.remote_ip4, dst="10.0.1.128")
1984 / Raw(b"0x5" * 100)
1985 )
Neale Rannse2fe0972020-11-26 08:37:27 +00001986
1987 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1988 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001989 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00001990
1991 #
1992 # add a local address in the same subnet
1993 # the source addresses are equivalent. VPP happens to
1994 # choose the last one that was added
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001995 conn3 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.2", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00001996
1997 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1998 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001999 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002000
2001 #
2002 # remove
2003 #
2004 conn3.remove_vpp_config()
2005 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2006 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002007 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002008
2009 #
2010 # add back, this time remove the first one
2011 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002012 conn3 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.2", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002013
2014 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2015 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002016 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002017
2018 conn1.remove_vpp_config()
2019 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2020 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002021 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002022
Neale Ranns66edaf22021-07-09 13:03:52 +00002023 # apply a connected prefix to an interface in a different table
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002024 VppIpRoute(
2025 self,
2026 "10.0.1.0",
2027 24,
2028 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
2029 table_id=1,
2030 ).add_vpp_config()
Neale Ranns66edaf22021-07-09 13:03:52 +00002031
2032 rxs = self.send_and_expect(self.pg3, [p2], self.pg1)
2033 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002034 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Ranns66edaf22021-07-09 13:03:52 +00002035
Neale Rannse2fe0972020-11-26 08:37:27 +00002036 # cleanup
2037 conn3.remove_vpp_config()
2038 conn2.remove_vpp_config()
2039
Neale Rannsdcd6d622017-05-26 02:59:16 -07002040
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002041@tag_fixme_vpp_workers
Neale Ranns14260392018-09-28 05:00:57 -07002042class NeighborStatsTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002043 """ARP/ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002044
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002045 @classmethod
2046 def setUpClass(cls):
2047 super(NeighborStatsTestCase, cls).setUpClass()
2048
2049 @classmethod
2050 def tearDownClass(cls):
2051 super(NeighborStatsTestCase, cls).tearDownClass()
2052
Neale Ranns14260392018-09-28 05:00:57 -07002053 def setUp(self):
2054 super(NeighborStatsTestCase, self).setUp()
2055
2056 self.create_pg_interfaces(range(2))
2057
2058 # pg0 configured with ip4 and 6 addresses used for input
2059 # pg1 configured with ip4 and 6 addresses used for output
2060 # pg2 is unnumbered to pg0
2061 for i in self.pg_interfaces:
2062 i.admin_up()
2063 i.config_ip4()
2064 i.config_ip6()
2065 i.resolve_arp()
2066 i.resolve_ndp()
2067
2068 def tearDown(self):
2069 super(NeighborStatsTestCase, self).tearDown()
2070
2071 for i in self.pg_interfaces:
2072 i.unconfig_ip4()
2073 i.unconfig_ip6()
2074 i.admin_down()
2075
2076 def test_arp_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002077 """ARP Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002078
2079 self.vapi.cli("adj counters enable")
2080 self.pg1.generate_remote_hosts(2)
2081
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002082 arp1 = VppNeighbor(
2083 self,
2084 self.pg1.sw_if_index,
2085 self.pg1.remote_hosts[0].mac,
2086 self.pg1.remote_hosts[0].ip4,
2087 )
Neale Ranns14260392018-09-28 05:00:57 -07002088 arp1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002089 arp2 = VppNeighbor(
2090 self,
2091 self.pg1.sw_if_index,
2092 self.pg1.remote_hosts[1].mac,
2093 self.pg1.remote_hosts[1].ip4,
2094 )
Neale Ranns14260392018-09-28 05:00:57 -07002095 arp2.add_vpp_config()
2096
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002097 p1 = (
2098 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2099 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[0].ip4)
2100 / UDP(sport=1234, dport=1234)
2101 / Raw()
2102 )
2103 p2 = (
2104 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2105 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
2106 / UDP(sport=1234, dport=1234)
2107 / Raw()
2108 )
Neale Ranns14260392018-09-28 05:00:57 -07002109
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002110 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
2111 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07002112
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002113 self.assertEqual(NUM_PKTS, arp1.get_stats()["packets"])
2114 self.assertEqual(NUM_PKTS, arp2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002115
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002116 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002117 self.assertEqual(NUM_PKTS * 2, arp1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002118
2119 def test_nd_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002120 """ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002121
2122 self.vapi.cli("adj counters enable")
2123 self.pg0.generate_remote_hosts(3)
2124
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002125 nd1 = VppNeighbor(
2126 self,
2127 self.pg0.sw_if_index,
2128 self.pg0.remote_hosts[1].mac,
2129 self.pg0.remote_hosts[1].ip6,
2130 )
Neale Ranns14260392018-09-28 05:00:57 -07002131 nd1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002132 nd2 = VppNeighbor(
2133 self,
2134 self.pg0.sw_if_index,
2135 self.pg0.remote_hosts[2].mac,
2136 self.pg0.remote_hosts[2].ip6,
2137 )
Neale Ranns14260392018-09-28 05:00:57 -07002138 nd2.add_vpp_config()
2139
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002140 p1 = (
2141 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2142 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[1].ip6)
2143 / UDP(sport=1234, dport=1234)
2144 / Raw()
2145 )
2146 p2 = (
2147 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2148 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[2].ip6)
2149 / UDP(sport=1234, dport=1234)
2150 / Raw()
2151 )
Neale Ranns14260392018-09-28 05:00:57 -07002152
2153 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
2154 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
2155
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002156 self.assertEqual(16, nd1.get_stats()["packets"])
2157 self.assertEqual(16, nd2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002158
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002159 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002160 self.assertEqual(NUM_PKTS + 16, nd1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002161
2162
Neale Rannscbe25aa2019-09-30 10:53:31 +00002163class NeighborAgeTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002164 """ARP/ND Aging"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002165
2166 @classmethod
2167 def setUpClass(cls):
2168 super(NeighborAgeTestCase, cls).setUpClass()
2169
2170 @classmethod
2171 def tearDownClass(cls):
2172 super(NeighborAgeTestCase, cls).tearDownClass()
2173
2174 def setUp(self):
2175 super(NeighborAgeTestCase, self).setUp()
2176
2177 self.create_pg_interfaces(range(1))
2178
2179 # pg0 configured with ip4 and 6 addresses used for input
2180 # pg1 configured with ip4 and 6 addresses used for output
2181 # pg2 is unnumbered to pg0
2182 for i in self.pg_interfaces:
2183 i.admin_up()
2184 i.config_ip4()
2185 i.config_ip6()
2186 i.resolve_arp()
2187 i.resolve_ndp()
2188
2189 def tearDown(self):
2190 super(NeighborAgeTestCase, self).tearDown()
2191
2192 for i in self.pg_interfaces:
2193 i.unconfig_ip4()
2194 i.unconfig_ip6()
2195 i.admin_down()
2196
Neale Rannscbe25aa2019-09-30 10:53:31 +00002197 def verify_arp_req(self, rx, smac, sip, dip):
2198 ether = rx[Ether]
2199 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2200 self.assertEqual(ether.src, smac)
2201
2202 arp = rx[ARP]
2203 self.assertEqual(arp.hwtype, 1)
2204 self.assertEqual(arp.ptype, 0x800)
2205 self.assertEqual(arp.hwlen, 6)
2206 self.assertEqual(arp.plen, 4)
2207 self.assertEqual(arp.op, arp_opts["who-has"])
2208 self.assertEqual(arp.hwsrc, smac)
2209 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2210 self.assertEqual(arp.psrc, sip)
2211 self.assertEqual(arp.pdst, dip)
2212
2213 def test_age(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002214 """Aging/Recycle"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002215
2216 self.vapi.cli("set logging unthrottle 0")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002217 self.vapi.cli("set logging size %d" % 0xFFFF)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002218
2219 self.pg0.generate_remote_hosts(201)
2220
2221 vaf = VppEnum.vl_api_address_family_t
2222
2223 #
2224 # start listening on all interfaces
2225 #
2226 self.pg_enable_capture(self.pg_interfaces)
2227
2228 #
2229 # Set the neighbor configuration:
2230 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002231 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00002232 # recycle = false
2233 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002234 self.vapi.ip_neighbor_config(
2235 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2236 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002237
2238 self.vapi.cli("sh ip neighbor-config")
2239
2240 # add the 198 neighbours that should pass (-1 for one created in setup)
2241 for ii in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002242 VppNeighbor(
2243 self,
2244 self.pg0.sw_if_index,
2245 self.pg0.remote_hosts[ii].mac,
2246 self.pg0.remote_hosts[ii].ip4,
2247 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002248
2249 # one more neighbor over the limit should fail
2250 with self.vapi.assert_negative_api_retval():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002251 VppNeighbor(
2252 self,
2253 self.pg0.sw_if_index,
2254 self.pg0.remote_hosts[200].mac,
2255 self.pg0.remote_hosts[200].ip4,
2256 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002257
2258 #
2259 # change the config to allow recycling the old neighbors
2260 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002261 self.vapi.ip_neighbor_config(
2262 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=True
2263 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002264
2265 # now new additions are allowed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002266 VppNeighbor(
2267 self,
2268 self.pg0.sw_if_index,
2269 self.pg0.remote_hosts[200].mac,
2270 self.pg0.remote_hosts[200].ip4,
2271 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002272
2273 # add the first neighbor we configured has been re-used
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002274 self.assertFalse(
2275 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2276 )
2277 self.assertTrue(
2278 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[200].ip4)
2279 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002280
2281 #
2282 # change the config to age old neighbors
2283 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002284 self.vapi.ip_neighbor_config(
2285 af=vaf.ADDRESS_IP4, max_number=200, max_age=2, recycle=True
2286 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002287
2288 self.vapi.cli("sh ip4 neighbor-sorted")
2289
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002290 # age out neighbors
2291 self.virtual_sleep(3)
2292
Neale Rannscbe25aa2019-09-30 10:53:31 +00002293 #
2294 # expect probes from all these ARP entries as they age
2295 # 3 probes for each neighbor 3*200 = 600
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002296 rxs = self.pg0.get_capture(600, timeout=2)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002297
2298 for ii in range(3):
2299 for jj in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002300 rx = rxs[ii * 200 + jj]
Neale Rannscbe25aa2019-09-30 10:53:31 +00002301 # rx.show()
2302
2303 #
2304 # 3 probes sent then 1 more second to see if a reply comes, before
2305 # they age out
2306 #
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002307 self.virtual_sleep(1)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002308
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002309 self.assertFalse(
2310 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2311 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002312
2313 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002314 # load up some neighbours again with 2s aging enabled
2315 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002316 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002317 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002318 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2319
2320 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002321 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002322 VppNeighbor(
2323 self,
2324 self.pg0.sw_if_index,
2325 self.pg0.remote_hosts[ii].mac,
2326 self.pg0.remote_hosts[ii].ip4,
2327 ).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002328
2329 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002330 self.assertEqual(e.flags, enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2331 self.assertEqual(str(e.neighbor.ip_address), self.pg0.remote_hosts[ii].ip4)
2332 self.assertEqual(e.neighbor.mac_address, self.pg0.remote_hosts[ii].mac)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002333
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002334 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002335 self.assertFalse(
2336 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2337 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002338
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002339 evs = []
2340 for ii in range(10):
2341 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002342 self.assertEqual(e.flags, enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002343 evs.append(e)
2344
2345 # check we got the correct mac/ip pairs - done separately
2346 # because we don't care about the order the remove notifications
2347 # arrive
2348 for ii in range(10):
2349 found = False
2350 mac = self.pg0.remote_hosts[ii].mac
2351 ip = self.pg0.remote_hosts[ii].ip4
2352
2353 for e in evs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002354 if e.neighbor.mac_address == mac and str(e.neighbor.ip_address) == ip:
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002355 found = True
2356 break
2357 self.assertTrue(found)
2358
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002359 #
2360 # check if we can set age and recycle with empty neighbor list
2361 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002362 self.vapi.ip_neighbor_config(
2363 af=vaf.ADDRESS_IP4, max_number=200, max_age=1000, recycle=True
2364 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002365
2366 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002367 # load up some neighbours again, then disable the aging
2368 # they should still be there in 10 seconds time
2369 #
2370 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002371 VppNeighbor(
2372 self,
2373 self.pg0.sw_if_index,
2374 self.pg0.remote_hosts[ii].mac,
2375 self.pg0.remote_hosts[ii].ip4,
2376 ).add_vpp_config()
2377 self.vapi.ip_neighbor_config(
2378 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2379 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002380
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002381 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002382 self.assertTrue(
2383 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2384 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002385
2386
Neale Rannsc87fbb42020-04-02 17:08:28 +00002387class NeighborReplaceTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002388 """ARP/ND Replacement"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002389
2390 @classmethod
2391 def setUpClass(cls):
2392 super(NeighborReplaceTestCase, cls).setUpClass()
2393
2394 @classmethod
2395 def tearDownClass(cls):
2396 super(NeighborReplaceTestCase, cls).tearDownClass()
2397
2398 def setUp(self):
2399 super(NeighborReplaceTestCase, self).setUp()
2400
2401 self.create_pg_interfaces(range(4))
2402
2403 # pg0 configured with ip4 and 6 addresses used for input
2404 # pg1 configured with ip4 and 6 addresses used for output
2405 # pg2 is unnumbered to pg0
2406 for i in self.pg_interfaces:
2407 i.admin_up()
2408 i.config_ip4()
2409 i.config_ip6()
2410 i.resolve_arp()
2411 i.resolve_ndp()
2412
2413 def tearDown(self):
2414 super(NeighborReplaceTestCase, self).tearDown()
2415
2416 for i in self.pg_interfaces:
2417 i.unconfig_ip4()
2418 i.unconfig_ip6()
2419 i.admin_down()
2420
2421 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002422 """replace"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002423
2424 N_HOSTS = 16
2425
2426 for i in self.pg_interfaces:
2427 i.generate_remote_hosts(N_HOSTS)
2428 i.configure_ipv4_neighbors()
2429 i.configure_ipv6_neighbors()
2430
2431 # replace them all
2432 self.vapi.ip_neighbor_replace_begin()
2433 self.vapi.ip_neighbor_replace_end()
2434
2435 for i in self.pg_interfaces:
2436 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002437 self.assertFalse(
2438 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip4)
2439 )
2440 self.assertFalse(
2441 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip6)
2442 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002443
2444 #
2445 # and them all back via the API
2446 #
2447 for i in self.pg_interfaces:
2448 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002449 VppNeighbor(
2450 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip4
2451 ).add_vpp_config()
2452 VppNeighbor(
2453 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip6
2454 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002455
2456 #
2457 # begin the replacement again, this time touch some
2458 # the neighbours on pg1 so they are not deleted
2459 #
2460 self.vapi.ip_neighbor_replace_begin()
2461
2462 # update from the API all neighbours on pg1
2463 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002464 VppNeighbor(
2465 self,
2466 self.pg1.sw_if_index,
2467 self.pg1.remote_hosts[h].mac,
2468 self.pg1.remote_hosts[h].ip4,
2469 ).add_vpp_config()
2470 VppNeighbor(
2471 self,
2472 self.pg1.sw_if_index,
2473 self.pg1.remote_hosts[h].mac,
2474 self.pg1.remote_hosts[h].ip6,
2475 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002476
2477 # update from the data-plane all neighbours on pg3
2478 self.pg3.configure_ipv4_neighbors()
2479 self.pg3.configure_ipv6_neighbors()
2480
2481 # complete the replacement
2482 self.logger.info(self.vapi.cli("sh ip neighbors"))
2483 self.vapi.ip_neighbor_replace_end()
2484
2485 for i in self.pg_interfaces:
2486 if i == self.pg1 or i == self.pg3:
2487 # neighbours on pg1 and pg3 are still present
2488 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002489 self.assertTrue(
2490 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2491 )
2492 self.assertTrue(
2493 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2494 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002495 else:
2496 # all other neighbours are toast
2497 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002498 self.assertFalse(
2499 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2500 )
2501 self.assertFalse(
2502 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2503 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002504
2505
Neale Ranns240dcb22020-04-23 09:04:59 +00002506class NeighborFlush(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002507 """Neighbor Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002508
2509 @classmethod
2510 def setUpClass(cls):
2511 super(NeighborFlush, cls).setUpClass()
2512
2513 @classmethod
2514 def tearDownClass(cls):
2515 super(NeighborFlush, cls).tearDownClass()
2516
2517 def setUp(self):
2518 super(NeighborFlush, self).setUp()
2519
2520 self.create_pg_interfaces(range(2))
2521
2522 for i in self.pg_interfaces:
2523 i.admin_up()
2524 i.config_ip4()
2525 i.config_ip6()
2526 i.resolve_arp()
2527 i.resolve_ndp()
2528
2529 def tearDown(self):
2530 super(NeighborFlush, self).tearDown()
2531
2532 for i in self.pg_interfaces:
2533 i.unconfig_ip4()
2534 i.unconfig_ip6()
2535 i.admin_down()
2536
2537 def test_flush(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002538 """Neighbour Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002539
2540 e = VppEnum
2541 nf = e.vl_api_ip_neighbor_flags_t
2542 af = e.vl_api_address_family_t
2543 N_HOSTS = 16
2544 static = [False, True]
2545 self.pg0.generate_remote_hosts(N_HOSTS)
2546 self.pg1.generate_remote_hosts(N_HOSTS)
2547
2548 for s in static:
2549 # a few v4 and v6 dynamic neoghbors
2550 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002551 VppNeighbor(
2552 self,
2553 self.pg0.sw_if_index,
2554 self.pg0.remote_hosts[n].mac,
2555 self.pg0.remote_hosts[n].ip4,
2556 is_static=s,
2557 ).add_vpp_config()
2558 VppNeighbor(
2559 self,
2560 self.pg1.sw_if_index,
2561 self.pg1.remote_hosts[n].mac,
2562 self.pg1.remote_hosts[n].ip6,
2563 is_static=s,
2564 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002565
2566 # flush the interfaces individually
2567 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2568
2569 # check we haven't flushed that which we shouldn't
2570 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002571 self.assertTrue(
2572 find_nbr(
2573 self,
2574 self.pg1.sw_if_index,
2575 self.pg1.remote_hosts[n].ip6,
2576 is_static=s,
2577 )
2578 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002579
2580 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2581
2582 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002583 self.assertFalse(
2584 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2585 )
2586 self.assertFalse(
2587 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2588 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002589
2590 # add the nieghbours back
2591 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002592 VppNeighbor(
2593 self,
2594 self.pg0.sw_if_index,
2595 self.pg0.remote_hosts[n].mac,
2596 self.pg0.remote_hosts[n].ip4,
2597 is_static=s,
2598 ).add_vpp_config()
2599 VppNeighbor(
2600 self,
2601 self.pg1.sw_if_index,
2602 self.pg1.remote_hosts[n].mac,
2603 self.pg1.remote_hosts[n].ip6,
2604 is_static=s,
2605 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002606
2607 self.logger.info(self.vapi.cli("sh ip neighbor"))
2608
2609 # flush both interfaces at the same time
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002610 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002611
2612 # check we haven't flushed that which we shouldn't
2613 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002614 self.assertTrue(
2615 find_nbr(
2616 self,
2617 self.pg0.sw_if_index,
2618 self.pg0.remote_hosts[n].ip4,
2619 is_static=s,
2620 )
2621 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002622
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002623 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002624
2625 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002626 self.assertFalse(
2627 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2628 )
2629 self.assertFalse(
2630 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2631 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002632
2633
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002634if __name__ == "__main__":
Neale Ranns37be7362017-02-21 17:30:26 -08002635 unittest.main(testRunner=VppTestRunner)