blob: b600a97c3c240d2fa65366c089d5b13133d7fbb8 [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
Dave Wallace670724c2022-09-20 21:52:18 -04007from framework import tag_fixme_vpp_workers, tag_fixme_ubuntu2204, tag_fixme_debian11
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 Rannsfd2417b2021-07-16 14:00:16 +0000163 def get_arp_rx_requests(self, itf):
164 """Get ARP RX request stats for and interface"""
165 return self.statistics["/net/arp/rx/requests"][:, itf.sw_if_index].sum()
166
167 def get_arp_tx_requests(self, itf):
168 """Get ARP TX request stats for and interface"""
169 return self.statistics["/net/arp/tx/requests"][:, itf.sw_if_index].sum()
170
171 def get_arp_rx_replies(self, itf):
172 """Get ARP RX replies stats for and interface"""
173 return self.statistics["/net/arp/rx/replies"][:, itf.sw_if_index].sum()
174
175 def get_arp_tx_replies(self, itf):
176 """Get ARP TX replies stats for and interface"""
177 return self.statistics["/net/arp/tx/replies"][:, itf.sw_if_index].sum()
178
179 def get_arp_rx_garp(self, itf):
180 """Get ARP RX grat stats for and interface"""
181 return self.statistics["/net/arp/rx/gratuitous"][:, itf.sw_if_index].sum()
182
183 def get_arp_tx_garp(self, itf):
184 """Get ARP RX grat stats for and interface"""
185 return self.statistics["/net/arp/tx/gratuitous"][:, itf.sw_if_index].sum()
186
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800187 def test_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200188 """ARP"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800189
190 #
191 # Generate some hosts on the LAN
192 #
Neale Rannsca193612017-06-14 06:50:08 -0700193 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800194
195 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000196 # watch for:
197 # - all neighbour events
198 # - all neighbor events on pg1
199 # - neighbor events for host[1] on pg1
200 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200201 self.vapi.want_ip_neighbor_events(enable=1, pid=os.getpid())
202 self.vapi.want_ip_neighbor_events(
203 enable=1, pid=os.getpid(), sw_if_index=self.pg1.sw_if_index
204 )
205 self.vapi.want_ip_neighbor_events(
206 enable=1,
207 pid=os.getpid(),
208 sw_if_index=self.pg1.sw_if_index,
209 ip=self.pg1.remote_hosts[1].ip4,
210 )
Neale Rannscbe25aa2019-09-30 10:53:31 +0000211
212 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
213
214 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800215 # Send IP traffic to one of these unresolved hosts.
216 # expect the generation of an ARP request
217 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200218 p = (
219 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
220 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4)
221 / UDP(sport=1234, dport=1234)
222 / Raw()
223 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800224
225 self.pg0.add_stream(p)
226 self.pg_enable_capture(self.pg_interfaces)
227 self.pg_start()
228
229 rx = self.pg1.get_capture(1)
230
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200231 self.verify_arp_req(
232 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
233 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800234
Neale Rannsfd2417b2021-07-16 14:00:16 +0000235 self.logger.info(self.vapi.cli("sh ip neighbor-stats"))
236 self.logger.info(self.vapi.cli("sh ip neighbor-stats pg1"))
237 self.assert_equal(self.get_arp_tx_requests(self.pg1), 1)
238
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800239 #
240 # And a dynamic ARP entry for host 1
241 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200242 dyn_arp = VppNeighbor(
243 self,
244 self.pg1.sw_if_index,
245 self.pg1.remote_hosts[1].mac,
246 self.pg1.remote_hosts[1].ip4,
247 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800248 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000249 self.assertTrue(dyn_arp.query_vpp_config())
250
Neale Rannsdc617b82020-08-20 08:22:56 +0000251 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
252
Neale Rannscbe25aa2019-09-30 10:53:31 +0000253 # this matches all of the listnerers
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200254 es = [self.vapi.wait_for_event(1, "ip_neighbor_event") for i in range(3)]
Neale Rannscbe25aa2019-09-30 10:53:31 +0000255 for e in es:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200256 self.assertEqual(str(e.neighbor.ip_address), self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800257
258 #
259 # now we expect IP traffic forwarded
260 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200261 dyn_p = (
262 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
263 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4)
264 / UDP(sport=1234, dport=1234)
265 / Raw()
266 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800267
268 self.pg0.add_stream(dyn_p)
269 self.pg_enable_capture(self.pg_interfaces)
270 self.pg_start()
271
272 rx = self.pg1.get_capture(1)
273
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200274 self.verify_ip(
275 rx[0],
276 self.pg1.local_mac,
277 self.pg1.remote_hosts[1].mac,
278 self.pg0.remote_ip4,
279 self.pg1._remote_hosts[1].ip4,
280 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800281
282 #
283 # And a Static ARP entry for host 2
284 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200285 static_arp = VppNeighbor(
286 self,
287 self.pg1.sw_if_index,
288 self.pg1.remote_hosts[2].mac,
289 self.pg1.remote_hosts[2].ip4,
290 is_static=1,
291 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800292 static_arp.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200293 es = [self.vapi.wait_for_event(1, "ip_neighbor_event") for i in range(2)]
Neale Rannscbe25aa2019-09-30 10:53:31 +0000294 for e in es:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200295 self.assertEqual(str(e.neighbor.ip_address), self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800296
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200297 static_p = (
298 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
299 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[2].ip4)
300 / UDP(sport=1234, dport=1234)
301 / Raw()
302 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800303
304 self.pg0.add_stream(static_p)
305 self.pg_enable_capture(self.pg_interfaces)
306 self.pg_start()
307
308 rx = self.pg1.get_capture(1)
309
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200310 self.verify_ip(
311 rx[0],
312 self.pg1.local_mac,
313 self.pg1.remote_hosts[2].mac,
314 self.pg0.remote_ip4,
315 self.pg1._remote_hosts[2].ip4,
316 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800317
318 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000319 # remove all the listeners
320 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200321 self.vapi.want_ip_neighbor_events(enable=0, pid=os.getpid())
322 self.vapi.want_ip_neighbor_events(
323 enable=0, pid=os.getpid(), sw_if_index=self.pg1.sw_if_index
324 )
325 self.vapi.want_ip_neighbor_events(
326 enable=0,
327 pid=os.getpid(),
328 sw_if_index=self.pg1.sw_if_index,
329 ip=self.pg1.remote_hosts[1].ip4,
330 )
Neale Rannscbe25aa2019-09-30 10:53:31 +0000331
332 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800333 # flap the link. dynamic ARPs get flush, statics don't
334 #
335 self.pg1.admin_down()
336 self.pg1.admin_up()
337
338 self.pg0.add_stream(static_p)
339 self.pg_enable_capture(self.pg_interfaces)
340 self.pg_start()
341 rx = self.pg1.get_capture(1)
342
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200343 self.verify_ip(
344 rx[0],
345 self.pg1.local_mac,
346 self.pg1.remote_hosts[2].mac,
347 self.pg0.remote_ip4,
348 self.pg1._remote_hosts[2].ip4,
349 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800350
351 self.pg0.add_stream(dyn_p)
352 self.pg_enable_capture(self.pg_interfaces)
353 self.pg_start()
354
355 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200356 self.verify_arp_req(
357 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
358 )
Neale Rannsfd2417b2021-07-16 14:00:16 +0000359 self.assert_equal(self.get_arp_tx_requests(self.pg1), 2)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800360
Neale Rannscbe25aa2019-09-30 10:53:31 +0000361 self.assertFalse(dyn_arp.query_vpp_config())
362 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800363 #
364 # Send an ARP request from one of the so-far unlearned remote hosts
365 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200366 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[3].mac) / ARP(
367 op="who-has",
368 hwsrc=self.pg1._remote_hosts[3].mac,
369 pdst=self.pg1.local_ip4,
370 psrc=self.pg1._remote_hosts[3].ip4,
371 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800372
373 self.pg1.add_stream(p)
374 self.pg_enable_capture(self.pg_interfaces)
375 self.pg_start()
376
377 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200378 self.verify_arp_resp(
379 rx[0],
380 self.pg1.local_mac,
381 self.pg1._remote_hosts[3].mac,
382 self.pg1.local_ip4,
383 self.pg1._remote_hosts[3].ip4,
384 )
Neale Rannsfd2417b2021-07-16 14:00:16 +0000385 self.logger.info(self.vapi.cli("sh ip neighbor-stats pg1"))
386 self.assert_equal(self.get_arp_rx_requests(self.pg1), 1)
387 self.assert_equal(self.get_arp_tx_replies(self.pg1), 1)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800388
389 #
390 # VPP should have learned the mapping for the remote host
391 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200392 self.assertTrue(
393 find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[3].ip4)
394 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800395 #
396 # Fire in an ARP request before the interface becomes IP enabled
397 #
398 self.pg2.generate_remote_hosts(4)
399
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200400 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
401 op="who-has",
402 hwsrc=self.pg2.remote_mac,
403 pdst=self.pg1.local_ip4,
404 psrc=self.pg2.remote_hosts[3].ip4,
405 )
406 pt = (
407 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac)
408 / Dot1Q(vlan=0)
409 / ARP(
410 op="who-has",
411 hwsrc=self.pg2.remote_mac,
412 pdst=self.pg1.local_ip4,
413 psrc=self.pg2.remote_hosts[3].ip4,
414 )
415 )
416 self.send_and_assert_no_replies(self.pg2, p, "interface not IP enabled")
Neale Ranns4b919a52017-03-11 05:55:21 -0800417
418 #
419 # Make pg2 un-numbered to pg1
420 #
421 self.pg2.set_unnumbered(self.pg1.sw_if_index)
422
Neale Rannsac3e72c2019-10-06 01:04:26 -0700423 #
424 # test the unnumbered dump both by all interfaces and just the enabled
425 # one
426 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700427 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700428 self.assertTrue(len(unnum))
429 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
430 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
431 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
432 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700433 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
434 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
435
Neale Ranns4b919a52017-03-11 05:55:21 -0800436 #
437 # We should respond to ARP requests for the unnumbered to address
438 # once an attached route to the source is known
439 #
440 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200441 self.pg2, p, "ARP req for unnumbered address - no source"
442 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800443
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200444 attached_host = VppIpRoute(
445 self,
446 self.pg2.remote_hosts[3].ip4,
447 32,
448 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
449 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800450 attached_host.add_vpp_config()
451
452 self.pg2.add_stream(p)
453 self.pg_enable_capture(self.pg_interfaces)
454 self.pg_start()
455
456 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200457 self.verify_arp_resp(
458 rx[0],
459 self.pg2.local_mac,
460 self.pg2.remote_mac,
461 self.pg1.local_ip4,
462 self.pg2.remote_hosts[3].ip4,
463 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800464
Neale Ranns30d0fd42017-05-30 07:30:04 -0700465 self.pg2.add_stream(pt)
466 self.pg_enable_capture(self.pg_interfaces)
467 self.pg_start()
468
469 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200470 self.verify_arp_resp(
471 rx[0],
472 self.pg2.local_mac,
473 self.pg2.remote_mac,
474 self.pg1.local_ip4,
475 self.pg2.remote_hosts[3].ip4,
476 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700477
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800478 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800479 # A neighbor entry that has no associated FIB-entry
480 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200481 arp_no_fib = VppNeighbor(
482 self,
483 self.pg1.sw_if_index,
484 self.pg1.remote_hosts[4].mac,
485 self.pg1.remote_hosts[4].ip4,
486 is_no_fib_entry=1,
487 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800488 arp_no_fib.add_vpp_config()
489
490 #
491 # check we have the neighbor, but no route
492 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200493 self.assertTrue(
494 find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[4].ip4)
495 )
496 self.assertFalse(find_route(self, self.pg1._remote_hosts[4].ip4, 32))
Neale Ranns3983ac22017-03-10 11:53:27 -0800497 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800498 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
499 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800500 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200501 arp_unnum = VppNeighbor(
502 self,
503 self.pg2.sw_if_index,
504 self.pg1.remote_hosts[5].mac,
505 self.pg1.remote_hosts[5].ip4,
506 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800507 arp_unnum.add_vpp_config()
508
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200509 p = (
510 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
511 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[5].ip4)
512 / UDP(sport=1234, dport=1234)
513 / Raw()
514 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800515
516 self.pg0.add_stream(p)
517 self.pg_enable_capture(self.pg_interfaces)
518 self.pg_start()
519
520 rx = self.pg2.get_capture(1)
521
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200522 self.verify_ip(
523 rx[0],
524 self.pg2.local_mac,
525 self.pg1.remote_hosts[5].mac,
526 self.pg0.remote_ip4,
527 self.pg1._remote_hosts[5].ip4,
528 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800529
530 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800531 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
532 # with the unnumbered interface's address as the source
533 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200534 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
535 op="who-has",
536 hwsrc=self.pg2.remote_mac,
537 pdst=self.pg1.local_ip4,
538 psrc=self.pg1.remote_hosts[6].ip4,
539 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800540
541 self.pg2.add_stream(p)
542 self.pg_enable_capture(self.pg_interfaces)
543 self.pg_start()
544
545 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200546 self.verify_arp_resp(
547 rx[0],
548 self.pg2.local_mac,
549 self.pg2.remote_mac,
550 self.pg1.local_ip4,
551 self.pg1.remote_hosts[6].ip4,
552 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800553
554 #
555 # An attached host route out of pg2 for an undiscovered hosts generates
556 # an ARP request with the unnumbered address as the source
557 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200558 att_unnum = VppIpRoute(
559 self,
560 self.pg1.remote_hosts[7].ip4,
561 32,
562 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
563 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800564 att_unnum.add_vpp_config()
565
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200566 p = (
567 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
568 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[7].ip4)
569 / UDP(sport=1234, dport=1234)
570 / Raw()
571 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800572
573 self.pg0.add_stream(p)
574 self.pg_enable_capture(self.pg_interfaces)
575 self.pg_start()
576
577 rx = self.pg2.get_capture(1)
578
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200579 self.verify_arp_req(
580 rx[0], self.pg2.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[7].ip4
581 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800582
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[7].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[7].ip4,
601 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800602
603 #
604 # An attached host route as yet unresolved out of pg2 for an
605 # undiscovered host, an ARP requests begets a response.
606 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200607 att_unnum1 = VppIpRoute(
608 self,
609 self.pg1.remote_hosts[8].ip4,
610 32,
611 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
612 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800613 att_unnum1.add_vpp_config()
614
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200615 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
616 op="who-has",
617 hwsrc=self.pg2.remote_mac,
618 pdst=self.pg1.local_ip4,
619 psrc=self.pg1.remote_hosts[8].ip4,
620 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800621
622 self.pg2.add_stream(p)
623 self.pg_enable_capture(self.pg_interfaces)
624 self.pg_start()
625
626 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200627 self.verify_arp_resp(
628 rx[0],
629 self.pg2.local_mac,
630 self.pg2.remote_mac,
631 self.pg1.local_ip4,
632 self.pg1.remote_hosts[8].ip4,
633 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800634
635 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700636 # Send an ARP request from one of the so-far unlearned remote hosts
637 # with a VLAN0 tag
638 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200639 p = (
640 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[9].mac)
641 / Dot1Q(vlan=0)
642 / ARP(
643 op="who-has",
644 hwsrc=self.pg1._remote_hosts[9].mac,
645 pdst=self.pg1.local_ip4,
646 psrc=self.pg1._remote_hosts[9].ip4,
647 )
648 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700649
650 self.pg1.add_stream(p)
651 self.pg_enable_capture(self.pg_interfaces)
652 self.pg_start()
653
654 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200655 self.verify_arp_resp(
656 rx[0],
657 self.pg1.local_mac,
658 self.pg1._remote_hosts[9].mac,
659 self.pg1.local_ip4,
660 self.pg1._remote_hosts[9].ip4,
661 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700662
663 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700664 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700665 # Should still get an ARP resp since the cover is attached
666 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200667 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) / ARP(
668 op="who-has",
669 hwsrc=self.pg1.remote_mac,
670 pdst=self.pg1.local_ip4,
671 psrc=self.pg1.remote_hosts[10].ip4,
672 )
Neale Rannsca193612017-06-14 06:50:08 -0700673
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200674 r1 = VppIpRoute(
675 self,
676 self.pg1.remote_hosts[10].ip4,
677 30,
678 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
679 )
Neale Rannsca193612017-06-14 06:50:08 -0700680 r1.add_vpp_config()
681
682 self.pg1.add_stream(p)
683 self.pg_enable_capture(self.pg_interfaces)
684 self.pg_start()
685 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200686 self.verify_arp_resp(
687 rx[0],
688 self.pg1.local_mac,
689 self.pg1.remote_mac,
690 self.pg1.local_ip4,
691 self.pg1.remote_hosts[10].ip4,
692 )
Neale Rannsca193612017-06-14 06:50:08 -0700693
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200694 r2 = VppIpRoute(
695 self,
696 self.pg1.remote_hosts[10].ip4,
697 32,
698 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
699 )
Neale Rannsca193612017-06-14 06:50:08 -0700700 r2.add_vpp_config()
701
702 self.pg1.add_stream(p)
703 self.pg_enable_capture(self.pg_interfaces)
704 self.pg_start()
705 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200706 self.verify_arp_resp(
707 rx[0],
708 self.pg1.local_mac,
709 self.pg1.remote_mac,
710 self.pg1.local_ip4,
711 self.pg1.remote_hosts[10].ip4,
712 )
Neale Rannsca193612017-06-14 06:50:08 -0700713
714 #
715 # add an ARP entry that's not on the sub-net and so whose
716 # adj-fib fails the refinement check. then send an ARP request
717 # from that source
718 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200719 a1 = VppNeighbor(
720 self, self.pg0.sw_if_index, self.pg0.remote_mac, "100.100.100.50"
721 )
Neale Rannsca193612017-06-14 06:50:08 -0700722 a1.add_vpp_config()
723
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200724 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
725 op="who-has",
726 hwsrc=self.pg0.remote_mac,
727 psrc="100.100.100.50",
728 pdst=self.pg0.remote_ip4,
729 )
730 self.send_and_assert_no_replies(self.pg0, p, "ARP req for from failed adj-fib")
Neale Rannsca193612017-06-14 06:50:08 -0700731
732 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800733 # ERROR Cases
734 # 1 - don't respond to ARP request for address not within the
735 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700736 # 1b - nor within the unnumbered subnet
737 # 1c - nor within the subnet of a different interface
738 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200739 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
740 op="who-has",
741 hwsrc=self.pg0.remote_mac,
742 pdst="10.10.10.3",
743 psrc=self.pg0.remote_ip4,
744 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800745 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200746 self.pg0, p, "ARP req for non-local destination"
747 )
748 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, "10.10.10.3"))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800749
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200750 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
751 op="who-has",
752 hwsrc=self.pg2.remote_mac,
753 pdst="10.10.10.3",
754 psrc=self.pg1.remote_hosts[7].ip4,
755 )
756 self.send_and_assert_no_replies(
757 self.pg0, p, "ARP req for non-local destination - unnum"
758 )
759
760 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
761 op="who-has",
762 hwsrc=self.pg0.remote_mac,
763 pdst=self.pg1.local_ip4,
764 psrc=self.pg1.remote_ip4,
765 )
766 self.send_and_assert_no_replies(self.pg0, p, "ARP req diff sub-net")
767 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700768
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800769 #
770 # 2 - don't respond to ARP request from an address not within the
771 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700772 # 2b - to a proxied address
773 # 2c - not within a different interface's sub-net
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200774 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
775 op="who-has",
776 hwsrc=self.pg0.remote_mac,
777 psrc="10.10.10.3",
778 pdst=self.pg0.local_ip4,
779 )
780 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
781 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
782 op="who-has",
783 hwsrc=self.pg2.remote_mac,
784 psrc="10.10.10.3",
785 pdst=self.pg0.local_ip4,
786 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800787 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200788 self.pg0, p, "ARP req for non-local source - unnum"
789 )
790 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
791 op="who-has",
792 hwsrc=self.pg0.remote_mac,
793 psrc=self.pg1.remote_ip4,
794 pdst=self.pg0.local_ip4,
795 )
796 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800797
798 #
799 # 3 - don't respond to ARP request from an address that belongs to
800 # the router
801 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200802 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
803 op="who-has",
804 hwsrc=self.pg0.remote_mac,
805 psrc=self.pg0.local_ip4,
806 pdst=self.pg0.local_ip4,
807 )
808 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800809
810 #
811 # 4 - don't respond to ARP requests that has mac source different
812 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800813 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200814 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
815 op="who-has",
816 hwsrc="00:00:00:DE:AD:BE",
817 psrc=self.pg0.remote_ip4,
818 pdst=self.pg0.local_ip4,
819 )
820 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800821
822 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800823 # 5 - don't respond to ARP requests for address within the
824 # interface's sub-net but not the interface's address
825 #
826 self.pg0.generate_remote_hosts(2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200827 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
828 op="who-has",
829 hwsrc=self.pg0.remote_mac,
830 psrc=self.pg0.remote_hosts[0].ip4,
831 pdst=self.pg0.remote_hosts[1].ip4,
832 )
833 self.send_and_assert_no_replies(
834 self.pg0, p, "ARP req for non-local destination"
835 )
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800836
837 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800838 # cleanup
839 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800840 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800841 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800842
Neale Ranns4b919a52017-03-11 05:55:21 -0800843 # need this to flush the adj-fibs
844 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
845 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700846 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800847
Neale Ranns24b170a2017-08-15 05:33:11 -0700848 def test_proxy_mirror_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200849 """Interface Mirror Proxy ARP"""
Neale Ranns24b170a2017-08-15 05:33:11 -0700850
851 #
852 # When VPP has an interface whose address is also applied to a TAP
853 # interface on the host, then VPP's TAP interface will be unnumbered
854 # to the 'real' interface and do proxy ARP from the host.
855 # the curious aspect of this setup is that ARP requests from the host
856 # will come from the VPP's own address.
857 #
858 self.pg0.generate_remote_hosts(2)
859
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200860 arp_req_from_me = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
861 op="who-has",
862 hwsrc=self.pg2.remote_mac,
863 pdst=self.pg0.remote_hosts[1].ip4,
864 psrc=self.pg0.local_ip4,
865 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700866
867 #
868 # Configure Proxy ARP for the subnet on PG0addresses on pg0
869 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200870 self.vapi.proxy_arp_add_del(
871 proxy={
872 "table_id": 0,
873 "low": self.pg0._local_ip4_subnet,
874 "hi": self.pg0._local_ip4_bcast,
875 },
876 is_add=1,
877 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700878
879 # Make pg2 un-numbered to pg0
880 #
881 self.pg2.set_unnumbered(self.pg0.sw_if_index)
882
883 #
884 # Enable pg2 for proxy ARP
885 #
886 self.pg2.set_proxy_arp()
887
888 #
889 # Send the ARP request with an originating address that
890 # is VPP's own address
891 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000892 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200893 self.verify_arp_resp(
894 rx[0],
895 self.pg2.local_mac,
896 self.pg2.remote_mac,
897 self.pg0.remote_hosts[1].ip4,
898 self.pg0.local_ip4,
899 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700900
901 #
902 # validate we have not learned an ARP entry as a result of this
903 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200904 self.assertFalse(find_nbr(self, self.pg2.sw_if_index, self.pg0.local_ip4))
Neale Ranns24b170a2017-08-15 05:33:11 -0700905
906 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000907 # setup a punt redirect so packets from the uplink go to the tap
908 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200909 redirect = VppIpPuntRedirect(
910 self, self.pg0.sw_if_index, self.pg2.sw_if_index, self.pg0.local_ip4
911 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100912 redirect.add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +0000913
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200914 p_tcp = (
915 Ether(
916 src=self.pg0.remote_mac,
917 dst=self.pg0.local_mac,
918 )
919 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
920 / TCP(sport=80, dport=80)
921 / Raw()
922 )
Neale Ranns240dcb22020-04-23 09:04:59 +0000923 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
924
925 # there's no ARP entry so this is an ARP req
926 self.assertTrue(rx[0].haslayer(ARP))
927
928 # and ARP entry for VPP's pg0 address on the host interface
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200929 n1 = VppNeighbor(
930 self,
931 self.pg2.sw_if_index,
932 self.pg2.remote_mac,
933 self.pg0.local_ip4,
934 is_no_fib_entry=True,
935 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +0000936 # now the packets shold forward
937 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
938 self.assertFalse(rx[0].haslayer(ARP))
939 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
940
941 #
942 # flush the neighbor cache on the uplink
943 #
944 af = VppEnum.vl_api_address_family_t
945 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
946
947 # ensure we can still resolve the ARPs on the uplink
948 self.pg0.resolve_arp()
949
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200950 self.assertTrue(find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_ip4))
Neale Ranns240dcb22020-04-23 09:04:59 +0000951
952 #
Neale Ranns24b170a2017-08-15 05:33:11 -0700953 # cleanup
954 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200955 self.vapi.proxy_arp_add_del(
956 proxy={
957 "table_id": 0,
958 "low": self.pg0._local_ip4_subnet,
959 "hi": self.pg0._local_ip4_bcast,
960 },
961 is_add=0,
962 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100963 redirect.remove_vpp_config()
Neale Ranns24b170a2017-08-15 05:33:11 -0700964
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800965 def test_proxy_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200966 """Proxy ARP"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800967
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700968 self.pg1.generate_remote_hosts(2)
969
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800970 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700971 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800972 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200973 arp_req_pg0 = Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
974 op="who-has",
975 hwsrc=self.pg0.remote_mac,
976 pdst="10.10.10.3",
977 psrc=self.pg0.remote_ip4,
978 )
979 arp_req_pg0_tagged = (
980 Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff")
981 / Dot1Q(vlan=0)
982 / ARP(
983 op="who-has",
984 hwsrc=self.pg0.remote_mac,
985 pdst="10.10.10.3",
986 psrc=self.pg0.remote_ip4,
987 )
988 )
989 arp_req_pg1 = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
990 op="who-has",
991 hwsrc=self.pg1.remote_mac,
992 pdst="10.10.10.3",
993 psrc=self.pg1.remote_ip4,
994 )
995 arp_req_pg2 = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
996 op="who-has",
997 hwsrc=self.pg2.remote_mac,
998 pdst="10.10.10.3",
999 psrc=self.pg1.remote_hosts[1].ip4,
1000 )
1001 arp_req_pg3 = Ether(src=self.pg3.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1002 op="who-has",
1003 hwsrc=self.pg3.remote_mac,
1004 pdst="10.10.10.3",
1005 psrc=self.pg3.remote_ip4,
1006 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001007
1008 #
1009 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
1010 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001011 self.vapi.proxy_arp_add_del(
1012 proxy={"table_id": 0, "low": "10.10.10.2", "hi": "10.10.10.124"}, is_add=1
1013 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001014
1015 #
1016 # No responses are sent when the interfaces are not enabled for proxy
1017 # ARP
1018 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001019 self.send_and_assert_no_replies(
1020 self.pg0, arp_req_pg0, "ARP req from unconfigured interface"
1021 )
1022 self.send_and_assert_no_replies(
1023 self.pg2, arp_req_pg2, "ARP req from unconfigured interface"
1024 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001025
1026 #
1027 # Make pg2 un-numbered to pg1
1028 # still won't reply.
1029 #
1030 self.pg2.set_unnumbered(self.pg1.sw_if_index)
1031
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001032 self.send_and_assert_no_replies(
1033 self.pg2, arp_req_pg2, "ARP req from unnumbered interface"
1034 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001035
1036 #
1037 # Enable each interface to reply to proxy ARPs
1038 #
1039 for i in self.pg_interfaces:
1040 i.set_proxy_arp()
1041
1042 #
1043 # Now each of the interfaces should reply to a request to a proxied
1044 # address
1045 #
1046 self.pg0.add_stream(arp_req_pg0)
1047 self.pg_enable_capture(self.pg_interfaces)
1048 self.pg_start()
1049
1050 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001051 self.verify_arp_resp(
1052 rx[0],
1053 self.pg0.local_mac,
1054 self.pg0.remote_mac,
1055 "10.10.10.3",
1056 self.pg0.remote_ip4,
1057 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001058
Neale Ranns30d0fd42017-05-30 07:30:04 -07001059 self.pg0.add_stream(arp_req_pg0_tagged)
1060 self.pg_enable_capture(self.pg_interfaces)
1061 self.pg_start()
1062
1063 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001064 self.verify_arp_resp(
1065 rx[0],
1066 self.pg0.local_mac,
1067 self.pg0.remote_mac,
1068 "10.10.10.3",
1069 self.pg0.remote_ip4,
1070 )
Neale Ranns30d0fd42017-05-30 07:30:04 -07001071
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001072 self.pg1.add_stream(arp_req_pg1)
1073 self.pg_enable_capture(self.pg_interfaces)
1074 self.pg_start()
1075
1076 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001077 self.verify_arp_resp(
1078 rx[0],
1079 self.pg1.local_mac,
1080 self.pg1.remote_mac,
1081 "10.10.10.3",
1082 self.pg1.remote_ip4,
1083 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001084
1085 self.pg2.add_stream(arp_req_pg2)
1086 self.pg_enable_capture(self.pg_interfaces)
1087 self.pg_start()
1088
1089 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001090 self.verify_arp_resp(
1091 rx[0],
1092 self.pg2.local_mac,
1093 self.pg2.remote_mac,
1094 "10.10.10.3",
1095 self.pg1.remote_hosts[1].ip4,
1096 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001097
1098 #
1099 # A request for an address out of the configured range
1100 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001101 arp_req_pg1_hi = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1102 op="who-has",
1103 hwsrc=self.pg1.remote_mac,
1104 pdst="10.10.10.125",
1105 psrc=self.pg1.remote_ip4,
1106 )
1107 self.send_and_assert_no_replies(
1108 self.pg1, arp_req_pg1_hi, "ARP req out of range HI"
1109 )
1110 arp_req_pg1_low = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1111 op="who-has",
1112 hwsrc=self.pg1.remote_mac,
1113 pdst="10.10.10.1",
1114 psrc=self.pg1.remote_ip4,
1115 )
1116 self.send_and_assert_no_replies(
1117 self.pg1, arp_req_pg1_low, "ARP req out of range Low"
1118 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001119
1120 #
1121 # Request for an address in the proxy range but from an interface
1122 # in a different VRF
1123 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001124 self.send_and_assert_no_replies(
1125 self.pg3, arp_req_pg3, "ARP req from different VRF"
1126 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001127
1128 #
1129 # Disable Each interface for proxy ARP
1130 # - expect none to respond
1131 #
1132 for i in self.pg_interfaces:
1133 i.set_proxy_arp(0)
1134
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001135 self.send_and_assert_no_replies(self.pg0, arp_req_pg0, "ARP req from disable")
1136 self.send_and_assert_no_replies(self.pg1, arp_req_pg1, "ARP req from disable")
1137 self.send_and_assert_no_replies(self.pg2, arp_req_pg2, "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001138
1139 #
1140 # clean up on interface 2
1141 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001142 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001143
1144 def test_mpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001145 """MPLS"""
Neale Ranns37be7362017-02-21 17:30:26 -08001146
1147 #
1148 # Interface 2 does not yet have ip4 config
1149 #
1150 self.pg2.config_ip4()
1151 self.pg2.generate_remote_hosts(2)
1152
1153 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001154 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001155 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001156 ip_10_0_0_1 = VppIpRoute(
1157 self,
1158 "10.0.0.1",
1159 32,
1160 [
1161 VppRoutePath(
1162 self.pg2.remote_hosts[1].ip4, self.pg2.sw_if_index, labels=[55]
1163 )
1164 ],
1165 )
Neale Ranns37be7362017-02-21 17:30:26 -08001166 ip_10_0_0_1.add_vpp_config()
1167
1168 #
1169 # packets should generate an ARP request
1170 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001171 p = (
1172 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1173 / IP(src=self.pg0.remote_ip4, dst="10.0.0.1")
1174 / UDP(sport=1234, dport=1234)
1175 / Raw(b"\xa5" * 100)
1176 )
Neale Ranns37be7362017-02-21 17:30:26 -08001177
1178 self.pg0.add_stream(p)
1179 self.pg_enable_capture(self.pg_interfaces)
1180 self.pg_start()
1181
1182 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001183 self.verify_arp_req(
1184 rx[0], self.pg2.local_mac, self.pg2.local_ip4, self.pg2._remote_hosts[1].ip4
1185 )
Neale Ranns37be7362017-02-21 17:30:26 -08001186
1187 #
1188 # now resolve the neighbours
1189 #
1190 self.pg2.configure_ipv4_neighbors()
1191
1192 #
1193 # Now packet should be properly MPLS encapped.
1194 # This verifies that MPLS link-type adjacencies are completed
1195 # when the ARP entry resolves
1196 #
1197 self.pg0.add_stream(p)
1198 self.pg_enable_capture(self.pg_interfaces)
1199 self.pg_start()
1200
1201 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001202 self.verify_ip_o_mpls(
1203 rx[0],
1204 self.pg2.local_mac,
1205 self.pg2.remote_hosts[1].mac,
1206 55,
1207 self.pg0.remote_ip4,
1208 "10.0.0.1",
1209 )
Neale Ranns4b919a52017-03-11 05:55:21 -08001210 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001211
Matthew Smithcb9ab472017-05-16 21:35:56 -05001212 def test_arp_vrrp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001213 """ARP reply with VRRP virtual src hw addr"""
Matthew Smithcb9ab472017-05-16 21:35:56 -05001214
1215 #
1216 # IP packet destined for pg1 remote host arrives on pg0 resulting
1217 # in an ARP request for the address of the remote host on pg1
1218 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001219 p0 = (
1220 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1221 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1222 / UDP(sport=1234, dport=1234)
1223 / Raw()
1224 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001225
Neale Ranns37029302018-08-10 05:30:06 -07001226 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001227
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001228 self.verify_arp_req(
1229 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
1230 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001231
1232 #
1233 # ARP reply for address of pg1 remote host arrives on pg1 with
1234 # the hw src addr set to a value in the VRRP IPv4 range of
1235 # MAC addresses
1236 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001237 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
1238 op="is-at",
1239 hwdst=self.pg1.local_mac,
1240 hwsrc="00:00:5e:00:01:09",
1241 pdst=self.pg1.local_ip4,
1242 psrc=self.pg1.remote_ip4,
1243 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001244
Neale Ranns37029302018-08-10 05:30:06 -07001245 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001246
1247 #
1248 # IP packet destined for pg1 remote host arrives on pg0 again.
1249 # VPP should have an ARP entry for that address now and the packet
1250 # should be sent out pg1.
1251 #
Neale Ranns37029302018-08-10 05:30:06 -07001252 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001253
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001254 self.verify_ip(
1255 rx1[0],
1256 self.pg1.local_mac,
1257 "00:00:5e:00:01:09",
1258 self.pg0.remote_ip4,
1259 self.pg1.remote_ip4,
1260 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001261
1262 self.pg1.admin_down()
1263 self.pg1.admin_up()
1264
Neale Rannsdcd6d622017-05-26 02:59:16 -07001265 def test_arp_duplicates(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001266 """ARP Duplicates"""
Neale Rannsdcd6d622017-05-26 02:59:16 -07001267
1268 #
1269 # Generate some hosts on the LAN
1270 #
1271 self.pg1.generate_remote_hosts(3)
1272
1273 #
1274 # Add host 1 on pg1 and pg2
1275 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001276 arp_pg1 = VppNeighbor(
1277 self,
1278 self.pg1.sw_if_index,
1279 self.pg1.remote_hosts[1].mac,
1280 self.pg1.remote_hosts[1].ip4,
1281 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001282 arp_pg1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001283 arp_pg2 = VppNeighbor(
1284 self,
1285 self.pg2.sw_if_index,
1286 self.pg2.remote_mac,
1287 self.pg1.remote_hosts[1].ip4,
1288 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001289 arp_pg2.add_vpp_config()
1290
1291 #
1292 # IP packet destined for pg1 remote host arrives on pg1 again.
1293 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001294 p = (
1295 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1296 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1297 / UDP(sport=1234, dport=1234)
1298 / Raw()
1299 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001300
1301 self.pg0.add_stream(p)
1302 self.pg_enable_capture(self.pg_interfaces)
1303 self.pg_start()
1304
1305 rx1 = self.pg1.get_capture(1)
1306
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001307 self.verify_ip(
1308 rx1[0],
1309 self.pg1.local_mac,
1310 self.pg1.remote_hosts[1].mac,
1311 self.pg0.remote_ip4,
1312 self.pg1.remote_hosts[1].ip4,
1313 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001314
1315 #
1316 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001317 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001318 #
1319 arp_pg1.remove_vpp_config()
1320
1321 self.pg0.add_stream(p)
1322 self.pg_enable_capture(self.pg_interfaces)
1323 self.pg_start()
1324
1325 rx1 = self.pg1.get_capture(1)
1326
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001327 self.verify_arp_req(
1328 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_hosts[1].ip4
1329 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001330
1331 #
1332 # Add it back
1333 #
1334 arp_pg1.add_vpp_config()
1335
1336 self.pg0.add_stream(p)
1337 self.pg_enable_capture(self.pg_interfaces)
1338 self.pg_start()
1339
1340 rx1 = self.pg1.get_capture(1)
1341
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001342 self.verify_ip(
1343 rx1[0],
1344 self.pg1.local_mac,
1345 self.pg1.remote_hosts[1].mac,
1346 self.pg0.remote_ip4,
1347 self.pg1.remote_hosts[1].ip4,
1348 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001349
Neale Ranns15002542017-09-10 04:39:11 -07001350 def test_arp_static(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001351 """ARP Static"""
Neale Ranns15002542017-09-10 04:39:11 -07001352 self.pg2.generate_remote_hosts(3)
1353
1354 #
1355 # Add a static ARP entry
1356 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001357 static_arp = VppNeighbor(
1358 self,
1359 self.pg2.sw_if_index,
1360 self.pg2.remote_hosts[1].mac,
1361 self.pg2.remote_hosts[1].ip4,
1362 is_static=1,
1363 )
Neale Ranns15002542017-09-10 04:39:11 -07001364 static_arp.add_vpp_config()
1365
1366 #
1367 # Add the connected prefix to the interface
1368 #
1369 self.pg2.config_ip4()
1370
1371 #
1372 # We should now find the adj-fib
1373 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001374 self.assertTrue(
1375 find_nbr(
1376 self, self.pg2.sw_if_index, self.pg2.remote_hosts[1].ip4, is_static=1
1377 )
1378 )
1379 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32))
Neale Ranns15002542017-09-10 04:39:11 -07001380
1381 #
1382 # remove the connected
1383 #
1384 self.pg2.unconfig_ip4()
1385
1386 #
1387 # put the interface into table 1
1388 #
1389 self.pg2.set_table_ip4(1)
1390
1391 #
1392 # configure the same connected and expect to find the
1393 # adj fib in the new table
1394 #
1395 self.pg2.config_ip4()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001396 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32, table_id=1))
Neale Ranns15002542017-09-10 04:39:11 -07001397
1398 #
1399 # clean-up
1400 #
1401 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001402 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001403 self.pg2.set_table_ip4(0)
1404
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001405 def test_arp_static_replace_dynamic_same_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001406 """ARP Static can replace Dynamic (same mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001407 self.pg2.generate_remote_hosts(1)
1408
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001409 dyn_arp = VppNeighbor(
1410 self,
1411 self.pg2.sw_if_index,
1412 self.pg2.remote_hosts[0].mac,
1413 self.pg2.remote_hosts[0].ip4,
1414 )
1415 static_arp = VppNeighbor(
1416 self,
1417 self.pg2.sw_if_index,
1418 self.pg2.remote_hosts[0].mac,
1419 self.pg2.remote_hosts[0].ip4,
1420 is_static=1,
1421 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001422
1423 #
1424 # Add a dynamic ARP entry
1425 #
1426 dyn_arp.add_vpp_config()
1427
1428 #
1429 # We should find the dynamic nbr
1430 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001431 self.assertFalse(
1432 find_nbr(
1433 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1434 )
1435 )
1436 self.assertTrue(
1437 find_nbr(
1438 self,
1439 self.pg2.sw_if_index,
1440 self.pg2.remote_hosts[0].ip4,
1441 is_static=0,
1442 mac=self.pg2.remote_hosts[0].mac,
1443 )
1444 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001445
1446 #
1447 # Add a static ARP entry with the same mac
1448 #
1449 static_arp.add_vpp_config()
1450
1451 #
1452 # We should now find the static nbr with the same mac
1453 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001454 self.assertFalse(
1455 find_nbr(
1456 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1457 )
1458 )
1459 self.assertTrue(
1460 find_nbr(
1461 self,
1462 self.pg2.sw_if_index,
1463 self.pg2.remote_hosts[0].ip4,
1464 is_static=1,
1465 mac=self.pg2.remote_hosts[0].mac,
1466 )
1467 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001468
1469 #
1470 # clean-up
1471 #
1472 static_arp.remove_vpp_config()
1473
1474 def test_arp_static_replace_dynamic_diff_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001475 """ARP Static can replace Dynamic (diff mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001476 self.pg2.generate_remote_hosts(2)
1477
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001478 dyn_arp = VppNeighbor(
1479 self,
1480 self.pg2.sw_if_index,
1481 self.pg2.remote_hosts[0].mac,
1482 self.pg2.remote_hosts[0].ip4,
1483 )
1484 static_arp = VppNeighbor(
1485 self,
1486 self.pg2.sw_if_index,
1487 self.pg2.remote_hosts[1].mac,
1488 self.pg2.remote_hosts[0].ip4,
1489 is_static=1,
1490 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001491
1492 #
1493 # Add a dynamic ARP entry
1494 #
1495 dyn_arp.add_vpp_config()
1496
1497 #
1498 # We should find the dynamic nbr
1499 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001500 self.assertFalse(
1501 find_nbr(
1502 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1503 )
1504 )
1505 self.assertTrue(
1506 find_nbr(
1507 self,
1508 self.pg2.sw_if_index,
1509 self.pg2.remote_hosts[0].ip4,
1510 is_static=0,
1511 mac=self.pg2.remote_hosts[0].mac,
1512 )
1513 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001514
1515 #
1516 # Add a static ARP entry with a changed mac
1517 #
1518 static_arp.add_vpp_config()
1519
1520 #
1521 # We should now find the static nbr with a changed mac
1522 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001523 self.assertFalse(
1524 find_nbr(
1525 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1526 )
1527 )
1528 self.assertTrue(
1529 find_nbr(
1530 self,
1531 self.pg2.sw_if_index,
1532 self.pg2.remote_hosts[0].ip4,
1533 is_static=1,
1534 mac=self.pg2.remote_hosts[1].mac,
1535 )
1536 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001537
1538 #
1539 # clean-up
1540 #
1541 static_arp.remove_vpp_config()
1542
Neale Rannsc819fc62018-02-16 02:44:05 -08001543 def test_arp_incomplete(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001544 """ARP Incomplete"""
Neale Rannsea8adf72021-08-13 08:10:59 +00001545 self.pg1.generate_remote_hosts(4)
Neale Rannsc819fc62018-02-16 02:44:05 -08001546
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001547 p0 = (
1548 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1549 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1550 / UDP(sport=1234, dport=1234)
1551 / Raw()
1552 )
1553 p1 = (
1554 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1555 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
1556 / UDP(sport=1234, dport=1234)
1557 / Raw()
1558 )
1559 p2 = (
1560 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1561 / IP(src=self.pg0.remote_ip4, dst="1.1.1.1")
1562 / UDP(sport=1234, dport=1234)
1563 / Raw()
1564 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001565
1566 #
1567 # a packet to an unresolved destination generates an ARP request
1568 #
1569 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001570 self.verify_arp_req(
1571 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
1572 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001573
1574 #
1575 # add a neighbour for remote host 1
1576 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001577 static_arp = VppNeighbor(
1578 self,
1579 self.pg1.sw_if_index,
1580 self.pg1.remote_hosts[1].mac,
1581 self.pg1.remote_hosts[1].ip4,
1582 is_static=1,
1583 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001584 static_arp.add_vpp_config()
1585
1586 #
Neale Rannsea8adf72021-08-13 08:10:59 +00001587 # add a route through remote host 3 hence we get an incomplete
1588 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001589 VppIpRoute(
1590 self,
1591 "1.1.1.1",
1592 32,
1593 [VppRoutePath(self.pg1.remote_hosts[3].ip4, self.pg1.sw_if_index)],
1594 ).add_vpp_config()
Neale Rannsea8adf72021-08-13 08:10:59 +00001595 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001596 self.verify_arp_req(
1597 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[3].ip4
1598 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001599
1600 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001601 # change the interface's MAC
1602 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001603 self.vapi.sw_interface_set_mac_address(
1604 self.pg1.sw_if_index, "00:00:00:33:33:33"
1605 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001606
1607 #
1608 # now ARP requests come from the new source mac
1609 #
1610 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001611 self.verify_arp_req(
1612 rx[0],
1613 "00:00:00:33:33:33",
1614 self.pg1.local_ip4,
1615 self.pg1._remote_hosts[2].ip4,
1616 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001617 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001618 self.verify_arp_req(
1619 rx[0],
1620 "00:00:00:33:33:33",
1621 self.pg1.local_ip4,
1622 self.pg1._remote_hosts[3].ip4,
1623 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001624
1625 #
1626 # packets to the resolved host also have the new source mac
1627 #
1628 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001629 self.verify_ip(
1630 rx[0],
1631 "00:00:00:33:33:33",
1632 self.pg1.remote_hosts[1].mac,
1633 self.pg0.remote_ip4,
1634 self.pg1.remote_hosts[1].ip4,
1635 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001636
1637 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001638 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001639 # configured subnet and thus no glean
1640 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001641 self.vapi.sw_interface_set_mac_address(
1642 self.pg2.sw_if_index, "00:00:00:33:33:33"
1643 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001644
Neale Ranns59ae61e2018-06-07 18:09:49 -07001645 def test_garp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001646 """GARP"""
Neale Ranns59ae61e2018-06-07 18:09:49 -07001647
1648 #
1649 # Generate some hosts on the LAN
1650 #
1651 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001652 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001653
1654 #
1655 # And an ARP entry
1656 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001657 arp = VppNeighbor(
1658 self,
1659 self.pg1.sw_if_index,
1660 self.pg1.remote_hosts[1].mac,
1661 self.pg1.remote_hosts[1].ip4,
1662 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001663 arp.add_vpp_config()
1664
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001665 self.assertTrue(
1666 find_nbr(
1667 self,
1668 self.pg1.sw_if_index,
1669 self.pg1.remote_hosts[1].ip4,
1670 mac=self.pg1.remote_hosts[1].mac,
1671 )
1672 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001673
1674 #
1675 # Send a GARP (request) to swap the host 1's address to that of host 2
1676 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001677 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[2].mac) / ARP(
1678 op="who-has",
1679 hwdst=self.pg1.local_mac,
1680 hwsrc=self.pg1.remote_hosts[2].mac,
1681 pdst=self.pg1.remote_hosts[1].ip4,
1682 psrc=self.pg1.remote_hosts[1].ip4,
1683 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001684
1685 self.pg1.add_stream(p1)
1686 self.pg_enable_capture(self.pg_interfaces)
1687 self.pg_start()
1688
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001689 self.assertTrue(
1690 find_nbr(
1691 self,
1692 self.pg1.sw_if_index,
1693 self.pg1.remote_hosts[1].ip4,
1694 mac=self.pg1.remote_hosts[2].mac,
1695 )
1696 )
Neale Rannsfd2417b2021-07-16 14:00:16 +00001697 self.assert_equal(self.get_arp_rx_garp(self.pg1), 1)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001698
1699 #
1700 # Send a GARP (reply) to swap the host 1's address to that of host 3
1701 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001702 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1703 op="is-at",
1704 hwdst=self.pg1.local_mac,
1705 hwsrc=self.pg1.remote_hosts[3].mac,
1706 pdst=self.pg1.remote_hosts[1].ip4,
1707 psrc=self.pg1.remote_hosts[1].ip4,
1708 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001709
1710 self.pg1.add_stream(p1)
1711 self.pg_enable_capture(self.pg_interfaces)
1712 self.pg_start()
1713
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001714 self.assertTrue(
1715 find_nbr(
1716 self,
1717 self.pg1.sw_if_index,
1718 self.pg1.remote_hosts[1].ip4,
1719 mac=self.pg1.remote_hosts[3].mac,
1720 )
1721 )
Neale Rannsfd2417b2021-07-16 14:00:16 +00001722 self.assert_equal(self.get_arp_rx_garp(self.pg1), 2)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001723
1724 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001725 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001726 # don't result in new neighbour entries
1727 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001728 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1729 op="who-has",
1730 hwdst=self.pg1.local_mac,
1731 hwsrc=self.pg1.remote_hosts[3].mac,
1732 pdst=self.pg1.remote_hosts[2].ip4,
1733 psrc=self.pg1.remote_hosts[2].ip4,
1734 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001735
1736 self.pg1.add_stream(p1)
1737 self.pg_enable_capture(self.pg_interfaces)
1738 self.pg_start()
1739
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001740 self.assertFalse(
1741 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1742 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001743
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001744 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1745 op="is-at",
1746 hwdst=self.pg1.local_mac,
1747 hwsrc=self.pg1.remote_hosts[3].mac,
1748 pdst=self.pg1.remote_hosts[2].ip4,
1749 psrc=self.pg1.remote_hosts[2].ip4,
1750 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001751
1752 self.pg1.add_stream(p1)
1753 self.pg_enable_capture(self.pg_interfaces)
1754 self.pg_start()
1755
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001756 self.assertFalse(
1757 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1758 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001759
Neale Ranns22eefd72020-09-23 11:25:21 +00001760 #
1761 # IP address in different subnets are not learnt
1762 #
1763 self.pg2.configure_ipv4_neighbors()
1764
Benoît Ganne114b1542022-09-12 17:56:16 +02001765 cntr = self.statistics.get_err_counter(
1766 "/err/arp-reply/l3_dst_address_not_local"
1767 )
1768
Neale Ranns22eefd72020-09-23 11:25:21 +00001769 for op in ["is-at", "who-has"]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001770 p1 = [
1771 (
1772 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1773 / ARP(
1774 op=op,
1775 hwdst=self.pg2.local_mac,
1776 hwsrc=self.pg2.remote_hosts[1].mac,
1777 pdst=self.pg2.remote_hosts[1].ip4,
1778 psrc=self.pg2.remote_hosts[1].ip4,
1779 )
1780 ),
1781 (
1782 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1783 / ARP(
1784 op=op,
1785 hwdst="ff:ff:ff:ff:ff:ff",
1786 hwsrc=self.pg2.remote_hosts[1].mac,
1787 pdst=self.pg2.remote_hosts[1].ip4,
1788 psrc=self.pg2.remote_hosts[1].ip4,
1789 )
1790 ),
1791 ]
Neale Ranns22eefd72020-09-23 11:25:21 +00001792
1793 self.send_and_assert_no_replies(self.pg1, p1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001794 self.assertFalse(
1795 find_nbr(self, self.pg1.sw_if_index, self.pg2.remote_hosts[1].ip4)
1796 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001797
1798 # they are all dropped because the subnet's don't match
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001799 self.assertEqual(
Benoît Ganne114b1542022-09-12 17:56:16 +02001800 cntr + 4,
Neale Ranns13a74ae2022-08-09 00:59:37 +00001801 self.statistics.get_err_counter("/err/arp-reply/l3_dst_address_not_local"),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001802 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001803
Neale Ranns77f91622020-11-23 16:25:27 +00001804 def test_arp_incomplete2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001805 """Incomplete Entries"""
Neale Rannsc8352bc2018-08-29 10:23:58 -07001806
1807 #
Neale Rannscd35e532018-08-31 02:51:45 -07001808 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001809 #
1810 self.pg0.generate_remote_hosts(2)
1811
Neale Rannscd35e532018-08-31 02:51:45 -07001812 #
1813 # IPv4/ARP
1814 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001815 ip_10_0_0_1 = VppIpRoute(
1816 self,
1817 "10.0.0.1",
1818 32,
1819 [VppRoutePath(self.pg0.remote_hosts[1].ip4, self.pg0.sw_if_index)],
1820 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001821 ip_10_0_0_1.add_vpp_config()
1822
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001823 p1 = (
1824 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1825 / IP(src=self.pg1.remote_ip4, dst="10.0.0.1")
1826 / UDP(sport=1234, dport=1234)
1827 / Raw()
1828 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001829
1830 self.pg1.add_stream(p1 * 257)
1831 self.pg_enable_capture(self.pg_interfaces)
1832 self.pg_start()
1833 rx = self.pg0._get_capture(1)
1834
1835 #
1836 # how many we get is going to be dependent on the time for packet
1837 # processing but it should be small
1838 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001839 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001840
Neale Rannscd35e532018-08-31 02:51:45 -07001841 #
1842 # IPv6/ND
1843 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001844 ip_10_1 = VppIpRoute(
1845 self,
1846 "10::1",
1847 128,
1848 [
1849 VppRoutePath(
1850 self.pg0.remote_hosts[1].ip6,
1851 self.pg0.sw_if_index,
1852 proto=DpoProto.DPO_PROTO_IP6,
1853 )
1854 ],
1855 )
Neale Rannscd35e532018-08-31 02:51:45 -07001856 ip_10_1.add_vpp_config()
1857
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001858 p1 = (
1859 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1860 / IPv6(src=self.pg1.remote_ip6, dst="10::1")
1861 / UDP(sport=1234, dport=1234)
1862 / Raw()
1863 )
Neale Rannscd35e532018-08-31 02:51:45 -07001864
1865 self.pg1.add_stream(p1 * 257)
1866 self.pg_enable_capture(self.pg_interfaces)
1867 self.pg_start()
1868 rx = self.pg0._get_capture(1)
1869
1870 #
1871 # how many we get is going to be dependent on the time for packet
1872 # processing but it should be small
1873 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001874 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001875
Neale Ranns7425f922019-01-23 00:36:16 -08001876 def test_arp_forus(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001877 """ARP for for-us"""
Neale Ranns7425f922019-01-23 00:36:16 -08001878
1879 #
1880 # Test that VPP responds with ARP requests to addresses that
1881 # are connected and local routes.
1882 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001883 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001884 # address added to an interface
1885 #
1886 self.pg0.generate_remote_hosts(2)
1887
Neale Ranns097fa662018-05-01 05:17:55 -07001888 forus = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001889 self,
1890 self.pg0.remote_hosts[1].ip4,
1891 32,
1892 [
1893 VppRoutePath(
1894 "0.0.0.0",
1895 self.pg0.sw_if_index,
1896 type=FibPathType.FIB_PATH_TYPE_LOCAL,
1897 )
1898 ],
1899 )
Neale Ranns7425f922019-01-23 00:36:16 -08001900 forus.add_vpp_config()
1901
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001902 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
1903 op="who-has",
1904 hwdst=self.pg0.local_mac,
1905 hwsrc=self.pg0.remote_mac,
1906 pdst=self.pg0.remote_hosts[1].ip4,
1907 psrc=self.pg0.remote_ip4,
1908 )
Neale Ranns7425f922019-01-23 00:36:16 -08001909
1910 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1911
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001912 self.verify_arp_resp(
1913 rx[0],
1914 self.pg0.local_mac,
1915 self.pg0.remote_mac,
1916 self.pg0.remote_hosts[1].ip4,
1917 self.pg0.remote_ip4,
1918 )
Neale Ranns7425f922019-01-23 00:36:16 -08001919
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001920 def test_arp_table_swap(self):
1921 #
1922 # Generate some hosts on the LAN
1923 #
1924 N_NBRS = 4
1925 self.pg1.generate_remote_hosts(N_NBRS)
1926
1927 for n in range(N_NBRS):
1928 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001929 VppIpRoute(
1930 self,
1931 "10.0.0.%d" % n,
1932 32,
1933 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
1934 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001935
1936 # resolve each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001937 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
1938 op="is-at",
1939 hwdst=self.pg1.local_mac,
1940 hwsrc="00:00:5e:00:01:09",
1941 pdst=self.pg1.local_ip4,
1942 psrc=self.pg1.remote_hosts[n].ip4,
1943 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001944
1945 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1946
1947 self.logger.info(self.vapi.cli("sh ip neighbors"))
1948
1949 #
1950 # swap the table pg1 is in
1951 #
1952 table = VppIpTable(self, 100).add_vpp_config()
1953
1954 self.pg1.unconfig_ip4()
1955 self.pg1.set_table_ip4(100)
1956 self.pg1.config_ip4()
1957
1958 #
1959 # all neighbours are cleared
1960 #
1961 for n in range(N_NBRS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001962 self.assertFalse(
1963 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip4)
1964 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001965
1966 #
1967 # packets to all neighbours generate ARP requests
1968 #
1969 for n in range(N_NBRS):
1970 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001971 VppIpRoute(
1972 self,
1973 "10.0.0.%d" % n,
1974 32,
1975 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
1976 table_id=100,
1977 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001978
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001979 p = (
1980 Ether(src=self.pg1.remote_hosts[n].mac, dst=self.pg1.local_mac)
1981 / IP(src=self.pg1.remote_hosts[n].ip4, dst="10.0.0.%d" % n)
1982 / Raw(b"0x5" * 100)
1983 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001984 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1985 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001986 self.verify_arp_req(
1987 rx,
1988 self.pg1.local_mac,
1989 self.pg1.local_ip4,
1990 self.pg1.remote_hosts[n].ip4,
1991 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001992
1993 self.pg1.unconfig_ip4()
1994 self.pg1.set_table_ip4(0)
1995
Neale Rannse2fe0972020-11-26 08:37:27 +00001996 def test_glean_src_select(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001997 """Multi Connecteds"""
Neale Rannse2fe0972020-11-26 08:37:27 +00001998
1999 #
2000 # configure multiple connected subnets on an interface
2001 # and ensure that ARP requests for hosts on those subnets
2002 # pick up the correct source address
2003 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002004 conn1 = VppIpInterfaceAddress(self, self.pg1, "10.0.0.1", 24).add_vpp_config()
2005 conn2 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.1", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002006
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002007 p1 = (
2008 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2009 / IP(src=self.pg1.remote_ip4, dst="10.0.0.128")
2010 / Raw(b"0x5" * 100)
2011 )
Neale Rannse2fe0972020-11-26 08:37:27 +00002012
2013 rxs = self.send_and_expect(self.pg0, [p1], self.pg1)
2014 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002015 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.0.1", "10.0.0.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002016
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002017 p2 = (
2018 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2019 / IP(src=self.pg1.remote_ip4, dst="10.0.1.128")
2020 / Raw(b"0x5" * 100)
2021 )
Neale Rannse2fe0972020-11-26 08:37:27 +00002022
2023 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2024 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002025 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002026
2027 #
2028 # add a local address in the same subnet
2029 # the source addresses are equivalent. VPP happens to
2030 # choose the last one that was added
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002031 conn3 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.2", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002032
2033 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2034 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002035 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002036
2037 #
2038 # remove
2039 #
2040 conn3.remove_vpp_config()
2041 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2042 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002043 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002044
2045 #
2046 # add back, this time remove the first one
2047 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002048 conn3 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.2", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002049
2050 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2051 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002052 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002053
2054 conn1.remove_vpp_config()
2055 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2056 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002057 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002058
Neale Ranns66edaf22021-07-09 13:03:52 +00002059 # apply a connected prefix to an interface in a different table
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002060 VppIpRoute(
2061 self,
2062 "10.0.1.0",
2063 24,
2064 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
2065 table_id=1,
2066 ).add_vpp_config()
Neale Ranns66edaf22021-07-09 13:03:52 +00002067
2068 rxs = self.send_and_expect(self.pg3, [p2], self.pg1)
2069 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002070 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Ranns66edaf22021-07-09 13:03:52 +00002071
Neale Rannse2fe0972020-11-26 08:37:27 +00002072 # cleanup
2073 conn3.remove_vpp_config()
2074 conn2.remove_vpp_config()
2075
Neale Rannsdcd6d622017-05-26 02:59:16 -07002076
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002077@tag_fixme_vpp_workers
Neale Ranns14260392018-09-28 05:00:57 -07002078class NeighborStatsTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002079 """ARP/ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002080
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002081 @classmethod
2082 def setUpClass(cls):
2083 super(NeighborStatsTestCase, cls).setUpClass()
2084
2085 @classmethod
2086 def tearDownClass(cls):
2087 super(NeighborStatsTestCase, cls).tearDownClass()
2088
Neale Ranns14260392018-09-28 05:00:57 -07002089 def setUp(self):
2090 super(NeighborStatsTestCase, self).setUp()
2091
2092 self.create_pg_interfaces(range(2))
2093
2094 # pg0 configured with ip4 and 6 addresses used for input
2095 # pg1 configured with ip4 and 6 addresses used for output
2096 # pg2 is unnumbered to pg0
2097 for i in self.pg_interfaces:
2098 i.admin_up()
2099 i.config_ip4()
2100 i.config_ip6()
2101 i.resolve_arp()
2102 i.resolve_ndp()
2103
2104 def tearDown(self):
2105 super(NeighborStatsTestCase, self).tearDown()
2106
2107 for i in self.pg_interfaces:
2108 i.unconfig_ip4()
2109 i.unconfig_ip6()
2110 i.admin_down()
2111
2112 def test_arp_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002113 """ARP Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002114
2115 self.vapi.cli("adj counters enable")
2116 self.pg1.generate_remote_hosts(2)
2117
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002118 arp1 = VppNeighbor(
2119 self,
2120 self.pg1.sw_if_index,
2121 self.pg1.remote_hosts[0].mac,
2122 self.pg1.remote_hosts[0].ip4,
2123 )
Neale Ranns14260392018-09-28 05:00:57 -07002124 arp1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002125 arp2 = VppNeighbor(
2126 self,
2127 self.pg1.sw_if_index,
2128 self.pg1.remote_hosts[1].mac,
2129 self.pg1.remote_hosts[1].ip4,
2130 )
Neale Ranns14260392018-09-28 05:00:57 -07002131 arp2.add_vpp_config()
2132
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002133 p1 = (
2134 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2135 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[0].ip4)
2136 / UDP(sport=1234, dport=1234)
2137 / Raw()
2138 )
2139 p2 = (
2140 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2141 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
2142 / UDP(sport=1234, dport=1234)
2143 / Raw()
2144 )
Neale Ranns14260392018-09-28 05:00:57 -07002145
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002146 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
2147 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07002148
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002149 self.assertEqual(NUM_PKTS, arp1.get_stats()["packets"])
2150 self.assertEqual(NUM_PKTS, arp2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002151
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002152 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002153 self.assertEqual(NUM_PKTS * 2, arp1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002154
2155 def test_nd_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002156 """ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002157
2158 self.vapi.cli("adj counters enable")
2159 self.pg0.generate_remote_hosts(3)
2160
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002161 nd1 = VppNeighbor(
2162 self,
2163 self.pg0.sw_if_index,
2164 self.pg0.remote_hosts[1].mac,
2165 self.pg0.remote_hosts[1].ip6,
2166 )
Neale Ranns14260392018-09-28 05:00:57 -07002167 nd1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002168 nd2 = VppNeighbor(
2169 self,
2170 self.pg0.sw_if_index,
2171 self.pg0.remote_hosts[2].mac,
2172 self.pg0.remote_hosts[2].ip6,
2173 )
Neale Ranns14260392018-09-28 05:00:57 -07002174 nd2.add_vpp_config()
2175
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002176 p1 = (
2177 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2178 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[1].ip6)
2179 / UDP(sport=1234, dport=1234)
2180 / Raw()
2181 )
2182 p2 = (
2183 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2184 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[2].ip6)
2185 / UDP(sport=1234, dport=1234)
2186 / Raw()
2187 )
Neale Ranns14260392018-09-28 05:00:57 -07002188
2189 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
2190 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
2191
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002192 self.assertEqual(16, nd1.get_stats()["packets"])
2193 self.assertEqual(16, nd2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002194
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002195 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002196 self.assertEqual(NUM_PKTS + 16, nd1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002197
2198
Dave Wallace670724c2022-09-20 21:52:18 -04002199@tag_fixme_ubuntu2204
Neale Rannscbe25aa2019-09-30 10:53:31 +00002200class NeighborAgeTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002201 """ARP/ND Aging"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002202
2203 @classmethod
2204 def setUpClass(cls):
2205 super(NeighborAgeTestCase, cls).setUpClass()
2206
2207 @classmethod
2208 def tearDownClass(cls):
2209 super(NeighborAgeTestCase, cls).tearDownClass()
2210
2211 def setUp(self):
2212 super(NeighborAgeTestCase, self).setUp()
2213
2214 self.create_pg_interfaces(range(1))
2215
2216 # pg0 configured with ip4 and 6 addresses used for input
2217 # pg1 configured with ip4 and 6 addresses used for output
2218 # pg2 is unnumbered to pg0
2219 for i in self.pg_interfaces:
2220 i.admin_up()
2221 i.config_ip4()
2222 i.config_ip6()
2223 i.resolve_arp()
2224 i.resolve_ndp()
2225
2226 def tearDown(self):
2227 super(NeighborAgeTestCase, self).tearDown()
2228
2229 for i in self.pg_interfaces:
2230 i.unconfig_ip4()
2231 i.unconfig_ip6()
2232 i.admin_down()
2233
Neale Rannscbe25aa2019-09-30 10:53:31 +00002234 def verify_arp_req(self, rx, smac, sip, dip):
2235 ether = rx[Ether]
2236 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2237 self.assertEqual(ether.src, smac)
2238
2239 arp = rx[ARP]
2240 self.assertEqual(arp.hwtype, 1)
2241 self.assertEqual(arp.ptype, 0x800)
2242 self.assertEqual(arp.hwlen, 6)
2243 self.assertEqual(arp.plen, 4)
2244 self.assertEqual(arp.op, arp_opts["who-has"])
2245 self.assertEqual(arp.hwsrc, smac)
2246 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2247 self.assertEqual(arp.psrc, sip)
2248 self.assertEqual(arp.pdst, dip)
2249
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002250 def verify_ip_neighbor_config(self, af, max_number, max_age, recycle):
2251 config = self.vapi.ip_neighbor_config_get(af)
2252
2253 self.assertEqual(config.af, af)
2254 self.assertEqual(config.max_number, max_number)
2255 self.assertEqual(config.max_age, max_age)
2256 self.assertEqual(config.recycle, recycle)
2257
Neale Rannscbe25aa2019-09-30 10:53:31 +00002258 def test_age(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002259 """Aging/Recycle"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002260
2261 self.vapi.cli("set logging unthrottle 0")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002262 self.vapi.cli("set logging size %d" % 0xFFFF)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002263
2264 self.pg0.generate_remote_hosts(201)
2265
2266 vaf = VppEnum.vl_api_address_family_t
2267
2268 #
2269 # start listening on all interfaces
2270 #
2271 self.pg_enable_capture(self.pg_interfaces)
2272
2273 #
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002274 # Verify neighbor configuration defaults
2275 #
2276 self.verify_ip_neighbor_config(
2277 af=vaf.ADDRESS_IP4, max_number=50000, max_age=0, recycle=False
2278 )
2279
2280 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002281 # Set the neighbor configuration:
2282 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002283 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00002284 # recycle = false
2285 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002286 self.vapi.ip_neighbor_config(
2287 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2288 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002289 self.verify_ip_neighbor_config(
2290 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2291 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002292
2293 self.vapi.cli("sh ip neighbor-config")
2294
2295 # add the 198 neighbours that should pass (-1 for one created in setup)
2296 for ii in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002297 VppNeighbor(
2298 self,
2299 self.pg0.sw_if_index,
2300 self.pg0.remote_hosts[ii].mac,
2301 self.pg0.remote_hosts[ii].ip4,
2302 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002303
2304 # one more neighbor over the limit should fail
2305 with self.vapi.assert_negative_api_retval():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002306 VppNeighbor(
2307 self,
2308 self.pg0.sw_if_index,
2309 self.pg0.remote_hosts[200].mac,
2310 self.pg0.remote_hosts[200].ip4,
2311 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002312
2313 #
2314 # change the config to allow recycling the old neighbors
2315 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002316 self.vapi.ip_neighbor_config(
2317 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=True
2318 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002319 self.verify_ip_neighbor_config(
2320 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=True
2321 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002322
2323 # now new additions are allowed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002324 VppNeighbor(
2325 self,
2326 self.pg0.sw_if_index,
2327 self.pg0.remote_hosts[200].mac,
2328 self.pg0.remote_hosts[200].ip4,
2329 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002330
2331 # add the first neighbor we configured has been re-used
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002332 self.assertFalse(
2333 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2334 )
2335 self.assertTrue(
2336 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[200].ip4)
2337 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002338
2339 #
2340 # change the config to age old neighbors
2341 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002342 self.vapi.ip_neighbor_config(
2343 af=vaf.ADDRESS_IP4, max_number=200, max_age=2, recycle=True
2344 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002345 self.verify_ip_neighbor_config(
2346 af=vaf.ADDRESS_IP4, max_number=200, max_age=2, recycle=True
2347 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002348
2349 self.vapi.cli("sh ip4 neighbor-sorted")
2350
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002351 # age out neighbors
2352 self.virtual_sleep(3)
2353
Neale Rannscbe25aa2019-09-30 10:53:31 +00002354 #
2355 # expect probes from all these ARP entries as they age
2356 # 3 probes for each neighbor 3*200 = 600
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002357 rxs = self.pg0.get_capture(600, timeout=2)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002358
2359 for ii in range(3):
2360 for jj in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002361 rx = rxs[ii * 200 + jj]
Neale Rannscbe25aa2019-09-30 10:53:31 +00002362 # rx.show()
2363
2364 #
2365 # 3 probes sent then 1 more second to see if a reply comes, before
2366 # they age out
2367 #
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002368 self.virtual_sleep(1)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002369
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002370 self.assertFalse(
2371 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2372 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002373
2374 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002375 # load up some neighbours again with 2s aging enabled
2376 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002377 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002378 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002379 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2380
2381 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002382 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002383 VppNeighbor(
2384 self,
2385 self.pg0.sw_if_index,
2386 self.pg0.remote_hosts[ii].mac,
2387 self.pg0.remote_hosts[ii].ip4,
2388 ).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002389
2390 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002391 self.assertEqual(e.flags, enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2392 self.assertEqual(str(e.neighbor.ip_address), self.pg0.remote_hosts[ii].ip4)
2393 self.assertEqual(e.neighbor.mac_address, self.pg0.remote_hosts[ii].mac)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002394
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002395 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002396 self.assertFalse(
2397 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2398 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002399
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002400 evs = []
2401 for ii in range(10):
2402 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002403 self.assertEqual(e.flags, enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002404 evs.append(e)
2405
2406 # check we got the correct mac/ip pairs - done separately
2407 # because we don't care about the order the remove notifications
2408 # arrive
2409 for ii in range(10):
2410 found = False
2411 mac = self.pg0.remote_hosts[ii].mac
2412 ip = self.pg0.remote_hosts[ii].ip4
2413
2414 for e in evs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002415 if e.neighbor.mac_address == mac and str(e.neighbor.ip_address) == ip:
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002416 found = True
2417 break
2418 self.assertTrue(found)
2419
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002420 #
2421 # check if we can set age and recycle with empty neighbor list
2422 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002423 self.vapi.ip_neighbor_config(
2424 af=vaf.ADDRESS_IP4, max_number=200, max_age=1000, recycle=True
2425 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002426 self.verify_ip_neighbor_config(
2427 af=vaf.ADDRESS_IP4, max_number=200, max_age=1000, recycle=True
2428 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002429
2430 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002431 # load up some neighbours again, then disable the aging
2432 # they should still be there in 10 seconds time
2433 #
2434 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002435 VppNeighbor(
2436 self,
2437 self.pg0.sw_if_index,
2438 self.pg0.remote_hosts[ii].mac,
2439 self.pg0.remote_hosts[ii].ip4,
2440 ).add_vpp_config()
2441 self.vapi.ip_neighbor_config(
2442 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2443 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002444 self.verify_ip_neighbor_config(
2445 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2446 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002447
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002448 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002449 self.assertTrue(
2450 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2451 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002452
2453
Neale Rannsc87fbb42020-04-02 17:08:28 +00002454class NeighborReplaceTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002455 """ARP/ND Replacement"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002456
2457 @classmethod
2458 def setUpClass(cls):
2459 super(NeighborReplaceTestCase, cls).setUpClass()
2460
2461 @classmethod
2462 def tearDownClass(cls):
2463 super(NeighborReplaceTestCase, cls).tearDownClass()
2464
2465 def setUp(self):
2466 super(NeighborReplaceTestCase, self).setUp()
2467
2468 self.create_pg_interfaces(range(4))
2469
2470 # pg0 configured with ip4 and 6 addresses used for input
2471 # pg1 configured with ip4 and 6 addresses used for output
2472 # pg2 is unnumbered to pg0
2473 for i in self.pg_interfaces:
2474 i.admin_up()
2475 i.config_ip4()
2476 i.config_ip6()
2477 i.resolve_arp()
2478 i.resolve_ndp()
2479
2480 def tearDown(self):
2481 super(NeighborReplaceTestCase, self).tearDown()
2482
2483 for i in self.pg_interfaces:
2484 i.unconfig_ip4()
2485 i.unconfig_ip6()
2486 i.admin_down()
2487
2488 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002489 """replace"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002490
2491 N_HOSTS = 16
2492
2493 for i in self.pg_interfaces:
2494 i.generate_remote_hosts(N_HOSTS)
2495 i.configure_ipv4_neighbors()
2496 i.configure_ipv6_neighbors()
2497
2498 # replace them all
2499 self.vapi.ip_neighbor_replace_begin()
2500 self.vapi.ip_neighbor_replace_end()
2501
2502 for i in self.pg_interfaces:
2503 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002504 self.assertFalse(
2505 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip4)
2506 )
2507 self.assertFalse(
2508 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip6)
2509 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002510
2511 #
2512 # and them all back via the API
2513 #
2514 for i in self.pg_interfaces:
2515 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002516 VppNeighbor(
2517 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip4
2518 ).add_vpp_config()
2519 VppNeighbor(
2520 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip6
2521 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002522
2523 #
2524 # begin the replacement again, this time touch some
2525 # the neighbours on pg1 so they are not deleted
2526 #
2527 self.vapi.ip_neighbor_replace_begin()
2528
2529 # update from the API all neighbours on pg1
2530 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002531 VppNeighbor(
2532 self,
2533 self.pg1.sw_if_index,
2534 self.pg1.remote_hosts[h].mac,
2535 self.pg1.remote_hosts[h].ip4,
2536 ).add_vpp_config()
2537 VppNeighbor(
2538 self,
2539 self.pg1.sw_if_index,
2540 self.pg1.remote_hosts[h].mac,
2541 self.pg1.remote_hosts[h].ip6,
2542 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002543
2544 # update from the data-plane all neighbours on pg3
2545 self.pg3.configure_ipv4_neighbors()
2546 self.pg3.configure_ipv6_neighbors()
2547
2548 # complete the replacement
2549 self.logger.info(self.vapi.cli("sh ip neighbors"))
2550 self.vapi.ip_neighbor_replace_end()
2551
2552 for i in self.pg_interfaces:
2553 if i == self.pg1 or i == self.pg3:
2554 # neighbours on pg1 and pg3 are still present
2555 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002556 self.assertTrue(
2557 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2558 )
2559 self.assertTrue(
2560 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2561 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002562 else:
2563 # all other neighbours are toast
2564 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002565 self.assertFalse(
2566 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2567 )
2568 self.assertFalse(
2569 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2570 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002571
2572
Neale Ranns240dcb22020-04-23 09:04:59 +00002573class NeighborFlush(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002574 """Neighbor Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002575
2576 @classmethod
2577 def setUpClass(cls):
2578 super(NeighborFlush, cls).setUpClass()
2579
2580 @classmethod
2581 def tearDownClass(cls):
2582 super(NeighborFlush, cls).tearDownClass()
2583
2584 def setUp(self):
2585 super(NeighborFlush, self).setUp()
2586
2587 self.create_pg_interfaces(range(2))
2588
2589 for i in self.pg_interfaces:
2590 i.admin_up()
2591 i.config_ip4()
2592 i.config_ip6()
2593 i.resolve_arp()
2594 i.resolve_ndp()
2595
2596 def tearDown(self):
2597 super(NeighborFlush, self).tearDown()
2598
2599 for i in self.pg_interfaces:
2600 i.unconfig_ip4()
2601 i.unconfig_ip6()
2602 i.admin_down()
2603
2604 def test_flush(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002605 """Neighbour Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002606
2607 e = VppEnum
2608 nf = e.vl_api_ip_neighbor_flags_t
2609 af = e.vl_api_address_family_t
2610 N_HOSTS = 16
2611 static = [False, True]
2612 self.pg0.generate_remote_hosts(N_HOSTS)
2613 self.pg1.generate_remote_hosts(N_HOSTS)
2614
2615 for s in static:
2616 # a few v4 and v6 dynamic neoghbors
2617 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002618 VppNeighbor(
2619 self,
2620 self.pg0.sw_if_index,
2621 self.pg0.remote_hosts[n].mac,
2622 self.pg0.remote_hosts[n].ip4,
2623 is_static=s,
2624 ).add_vpp_config()
2625 VppNeighbor(
2626 self,
2627 self.pg1.sw_if_index,
2628 self.pg1.remote_hosts[n].mac,
2629 self.pg1.remote_hosts[n].ip6,
2630 is_static=s,
2631 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002632
2633 # flush the interfaces individually
2634 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2635
2636 # check we haven't flushed that which we shouldn't
2637 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002638 self.assertTrue(
2639 find_nbr(
2640 self,
2641 self.pg1.sw_if_index,
2642 self.pg1.remote_hosts[n].ip6,
2643 is_static=s,
2644 )
2645 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002646
2647 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2648
2649 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002650 self.assertFalse(
2651 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2652 )
2653 self.assertFalse(
2654 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2655 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002656
2657 # add the nieghbours back
2658 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002659 VppNeighbor(
2660 self,
2661 self.pg0.sw_if_index,
2662 self.pg0.remote_hosts[n].mac,
2663 self.pg0.remote_hosts[n].ip4,
2664 is_static=s,
2665 ).add_vpp_config()
2666 VppNeighbor(
2667 self,
2668 self.pg1.sw_if_index,
2669 self.pg1.remote_hosts[n].mac,
2670 self.pg1.remote_hosts[n].ip6,
2671 is_static=s,
2672 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002673
2674 self.logger.info(self.vapi.cli("sh ip neighbor"))
2675
2676 # flush both interfaces at the same time
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002677 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002678
2679 # check we haven't flushed that which we shouldn't
2680 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002681 self.assertTrue(
2682 find_nbr(
2683 self,
2684 self.pg0.sw_if_index,
2685 self.pg0.remote_hosts[n].ip4,
2686 is_static=s,
2687 )
2688 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002689
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002690 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002691
2692 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002693 self.assertFalse(
2694 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2695 )
2696 self.assertFalse(
2697 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2698 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002699
2700
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002701if __name__ == "__main__":
Neale Ranns37be7362017-02-21 17:30:26 -08002702 unittest.main(testRunner=VppTestRunner)