blob: 7338eff86d3cf928717730b16a3ec121a7de9ead [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 -08005
Dave Wallace8800f732023-08-31 00:47:44 -04006from framework import VppTestCase
7from asfframework import VppTestRunner, tag_fixme_vpp_workers, tag_fixme_ubuntu2204
Neale Ranns39f9d8b2017-02-16 21:57:05 -08008from vpp_neighbor import VppNeighbor, find_nbr
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02009from vpp_ip_route import (
10 VppIpRoute,
11 VppRoutePath,
12 find_route,
13 VppIpTable,
14 DpoProto,
15 FibPathType,
16 VppIpInterfaceAddress,
17)
Alexander Chernavin8a92b682023-05-22 14:27:24 +000018from vpp_papi import VppEnum, MACAddress
Jakub Grajciar2df2f752020-12-01 11:23:44 +010019from vpp_ip import VppIpPuntRedirect
Alexander Chernavin8a92b682023-05-22 14:27:24 +000020from vpp_sub_interface import VppDot1ADSubint
Neale Ranns39f9d8b2017-02-16 21:57:05 -080021
22from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070023from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000024from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070025from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080026from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070027from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080028
Paul Vinciguerra4271c972019-05-14 13:25:49 -040029
30NUM_PKTS = 67
31
Neale Ranns39f9d8b2017-02-16 21:57:05 -080032# not exported by scapy, so redefined here
33arp_opts = {"who-has": 1, "is-at": 2}
34
35
36class ARPTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020037 """ARP Test Case"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -080038
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070039 @classmethod
40 def setUpClass(cls):
41 super(ARPTestCase, cls).setUpClass()
42
43 @classmethod
44 def tearDownClass(cls):
45 super(ARPTestCase, cls).tearDownClass()
46
Neale Ranns39f9d8b2017-02-16 21:57:05 -080047 def setUp(self):
48 super(ARPTestCase, self).setUp()
49
50 # create 3 pg interfaces
51 self.create_pg_interfaces(range(4))
52
53 # pg0 configured with ip4 and 6 addresses used for input
54 # pg1 configured with ip4 and 6 addresses used for output
55 # pg2 is unnumbered to pg0
56 for i in self.pg_interfaces:
57 i.admin_up()
58
59 self.pg0.config_ip4()
60 self.pg0.config_ip6()
61 self.pg0.resolve_arp()
62
63 self.pg1.config_ip4()
64 self.pg1.config_ip6()
65
66 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070067 self.tbl = VppIpTable(self, 1)
68 self.tbl.add_vpp_config()
69
Neale Ranns39f9d8b2017-02-16 21:57:05 -080070 self.pg3.set_table_ip4(1)
71 self.pg3.config_ip4()
72
Neale Ranns4008ac92017-02-13 23:20:04 -080073 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080074 self.pg0.unconfig_ip4()
75 self.pg0.unconfig_ip6()
76
77 self.pg1.unconfig_ip4()
78 self.pg1.unconfig_ip6()
79
80 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070081 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080082
Neale Ranns4008ac92017-02-13 23:20:04 -080083 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080084 i.admin_down()
85
Neale Ranns15002542017-09-10 04:39:11 -070086 super(ARPTestCase, self).tearDown()
87
Alexander Chernavin8a92b682023-05-22 14:27:24 +000088 def verify_arp_req(self, rx, smac, sip, dip, etype=0x0806):
Neale Ranns39f9d8b2017-02-16 21:57:05 -080089 ether = rx[Ether]
90 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
91 self.assertEqual(ether.src, smac)
Alexander Chernavin8a92b682023-05-22 14:27:24 +000092 self.assertEqual(ether.type, etype)
Neale Ranns39f9d8b2017-02-16 21:57:05 -080093
94 arp = rx[ARP]
95 self.assertEqual(arp.hwtype, 1)
96 self.assertEqual(arp.ptype, 0x800)
97 self.assertEqual(arp.hwlen, 6)
98 self.assertEqual(arp.plen, 4)
99 self.assertEqual(arp.op, arp_opts["who-has"])
100 self.assertEqual(arp.hwsrc, smac)
101 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
102 self.assertEqual(arp.psrc, sip)
103 self.assertEqual(arp.pdst, dip)
104
105 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
106 ether = rx[Ether]
107 self.assertEqual(ether.dst, dmac)
108 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100109 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800110
111 arp = rx[ARP]
112 self.assertEqual(arp.hwtype, 1)
113 self.assertEqual(arp.ptype, 0x800)
114 self.assertEqual(arp.hwlen, 6)
115 self.assertEqual(arp.plen, 4)
116 self.assertEqual(arp.op, arp_opts["is-at"])
117 self.assertEqual(arp.hwsrc, smac)
118 self.assertEqual(arp.hwdst, dmac)
119 self.assertEqual(arp.psrc, sip)
120 self.assertEqual(arp.pdst, dip)
121
Matthew Smithcb9ab472017-05-16 21:35:56 -0500122 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
123 ether = rx[Ether]
124 self.assertEqual(ether.dst, dmac)
125 self.assertEqual(ether.src, smac)
126
127 arp = rx[ARP]
128 self.assertEqual(arp.hwtype, 1)
129 self.assertEqual(arp.ptype, 0x800)
130 self.assertEqual(arp.hwlen, 6)
131 self.assertEqual(arp.plen, 4)
132 self.assertEqual(arp.op, arp_opts["is-at"])
133 self.assertNotEqual(arp.hwsrc, smac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200134 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 -0500135 self.assertEqual(arp.hwdst, dmac)
136 self.assertEqual(arp.psrc, sip)
137 self.assertEqual(arp.pdst, dip)
138
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800139 def verify_ip(self, rx, smac, dmac, sip, dip):
140 ether = rx[Ether]
141 self.assertEqual(ether.dst, dmac)
142 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100143 self.assertEqual(ether.type, 0x0800)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800144
145 ip = rx[IP]
146 self.assertEqual(ip.src, sip)
147 self.assertEqual(ip.dst, dip)
148
Neale Ranns37be7362017-02-21 17:30:26 -0800149 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
150 ether = rx[Ether]
151 self.assertEqual(ether.dst, dmac)
152 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100153 self.assertEqual(ether.type, 0x8847)
Neale Ranns37be7362017-02-21 17:30:26 -0800154
155 mpls = rx[MPLS]
156 self.assertTrue(mpls.label, label)
157
158 ip = rx[IP]
159 self.assertEqual(ip.src, sip)
160 self.assertEqual(ip.dst, dip)
161
Neale Rannsfd2417b2021-07-16 14:00:16 +0000162 def get_arp_rx_requests(self, itf):
163 """Get ARP RX request stats for and interface"""
164 return self.statistics["/net/arp/rx/requests"][:, itf.sw_if_index].sum()
165
166 def get_arp_tx_requests(self, itf):
167 """Get ARP TX request stats for and interface"""
168 return self.statistics["/net/arp/tx/requests"][:, itf.sw_if_index].sum()
169
170 def get_arp_rx_replies(self, itf):
171 """Get ARP RX replies stats for and interface"""
172 return self.statistics["/net/arp/rx/replies"][:, itf.sw_if_index].sum()
173
174 def get_arp_tx_replies(self, itf):
175 """Get ARP TX replies stats for and interface"""
176 return self.statistics["/net/arp/tx/replies"][:, itf.sw_if_index].sum()
177
178 def get_arp_rx_garp(self, itf):
179 """Get ARP RX grat stats for and interface"""
180 return self.statistics["/net/arp/rx/gratuitous"][:, itf.sw_if_index].sum()
181
182 def get_arp_tx_garp(self, itf):
183 """Get ARP RX grat stats for and interface"""
184 return self.statistics["/net/arp/tx/gratuitous"][:, itf.sw_if_index].sum()
185
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800186 def test_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200187 """ARP"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800188
189 #
190 # Generate some hosts on the LAN
191 #
Neale Rannsca193612017-06-14 06:50:08 -0700192 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800193
194 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000195 # watch for:
196 # - all neighbour events
197 # - all neighbor events on pg1
198 # - neighbor events for host[1] on pg1
199 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200200 self.vapi.want_ip_neighbor_events(enable=1, pid=os.getpid())
201 self.vapi.want_ip_neighbor_events(
202 enable=1, pid=os.getpid(), sw_if_index=self.pg1.sw_if_index
203 )
204 self.vapi.want_ip_neighbor_events(
205 enable=1,
206 pid=os.getpid(),
207 sw_if_index=self.pg1.sw_if_index,
208 ip=self.pg1.remote_hosts[1].ip4,
209 )
Neale Rannscbe25aa2019-09-30 10:53:31 +0000210
211 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
212
213 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800214 # Send IP traffic to one of these unresolved hosts.
215 # expect the generation of an ARP request
216 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200217 p = (
218 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
219 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4)
220 / UDP(sport=1234, dport=1234)
221 / Raw()
222 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800223
224 self.pg0.add_stream(p)
225 self.pg_enable_capture(self.pg_interfaces)
226 self.pg_start()
227
228 rx = self.pg1.get_capture(1)
229
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200230 self.verify_arp_req(
231 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
232 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800233
Neale Rannsfd2417b2021-07-16 14:00:16 +0000234 self.logger.info(self.vapi.cli("sh ip neighbor-stats"))
235 self.logger.info(self.vapi.cli("sh ip neighbor-stats pg1"))
236 self.assert_equal(self.get_arp_tx_requests(self.pg1), 1)
237
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800238 #
239 # And a dynamic ARP entry for host 1
240 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200241 dyn_arp = VppNeighbor(
242 self,
243 self.pg1.sw_if_index,
244 self.pg1.remote_hosts[1].mac,
245 self.pg1.remote_hosts[1].ip4,
246 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800247 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000248 self.assertTrue(dyn_arp.query_vpp_config())
249
Neale Rannsdc617b82020-08-20 08:22:56 +0000250 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
251
Neale Rannscbe25aa2019-09-30 10:53:31 +0000252 # this matches all of the listnerers
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200253 es = [self.vapi.wait_for_event(1, "ip_neighbor_event") for i in range(3)]
Neale Rannscbe25aa2019-09-30 10:53:31 +0000254 for e in es:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200255 self.assertEqual(str(e.neighbor.ip_address), self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800256
257 #
258 # now we expect IP traffic forwarded
259 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200260 dyn_p = (
261 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
262 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4)
263 / UDP(sport=1234, dport=1234)
264 / Raw()
265 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800266
267 self.pg0.add_stream(dyn_p)
268 self.pg_enable_capture(self.pg_interfaces)
269 self.pg_start()
270
271 rx = self.pg1.get_capture(1)
272
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200273 self.verify_ip(
274 rx[0],
275 self.pg1.local_mac,
276 self.pg1.remote_hosts[1].mac,
277 self.pg0.remote_ip4,
278 self.pg1._remote_hosts[1].ip4,
279 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800280
281 #
282 # And a Static ARP entry for host 2
283 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200284 static_arp = VppNeighbor(
285 self,
286 self.pg1.sw_if_index,
287 self.pg1.remote_hosts[2].mac,
288 self.pg1.remote_hosts[2].ip4,
289 is_static=1,
290 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800291 static_arp.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200292 es = [self.vapi.wait_for_event(1, "ip_neighbor_event") for i in range(2)]
Neale Rannscbe25aa2019-09-30 10:53:31 +0000293 for e in es:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200294 self.assertEqual(str(e.neighbor.ip_address), self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800295
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200296 static_p = (
297 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
298 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[2].ip4)
299 / UDP(sport=1234, dport=1234)
300 / Raw()
301 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800302
303 self.pg0.add_stream(static_p)
304 self.pg_enable_capture(self.pg_interfaces)
305 self.pg_start()
306
307 rx = self.pg1.get_capture(1)
308
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200309 self.verify_ip(
310 rx[0],
311 self.pg1.local_mac,
312 self.pg1.remote_hosts[2].mac,
313 self.pg0.remote_ip4,
314 self.pg1._remote_hosts[2].ip4,
315 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800316
317 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000318 # remove all the listeners
319 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200320 self.vapi.want_ip_neighbor_events(enable=0, pid=os.getpid())
321 self.vapi.want_ip_neighbor_events(
322 enable=0, pid=os.getpid(), sw_if_index=self.pg1.sw_if_index
323 )
324 self.vapi.want_ip_neighbor_events(
325 enable=0,
326 pid=os.getpid(),
327 sw_if_index=self.pg1.sw_if_index,
328 ip=self.pg1.remote_hosts[1].ip4,
329 )
Neale Rannscbe25aa2019-09-30 10:53:31 +0000330
331 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800332 # flap the link. dynamic ARPs get flush, statics don't
333 #
334 self.pg1.admin_down()
335 self.pg1.admin_up()
336
337 self.pg0.add_stream(static_p)
338 self.pg_enable_capture(self.pg_interfaces)
339 self.pg_start()
340 rx = self.pg1.get_capture(1)
341
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200342 self.verify_ip(
343 rx[0],
344 self.pg1.local_mac,
345 self.pg1.remote_hosts[2].mac,
346 self.pg0.remote_ip4,
347 self.pg1._remote_hosts[2].ip4,
348 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800349
350 self.pg0.add_stream(dyn_p)
351 self.pg_enable_capture(self.pg_interfaces)
352 self.pg_start()
353
354 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200355 self.verify_arp_req(
356 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
357 )
Neale Rannsfd2417b2021-07-16 14:00:16 +0000358 self.assert_equal(self.get_arp_tx_requests(self.pg1), 2)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800359
Neale Rannscbe25aa2019-09-30 10:53:31 +0000360 self.assertFalse(dyn_arp.query_vpp_config())
361 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800362 #
363 # Send an ARP request from one of the so-far unlearned remote hosts
364 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200365 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[3].mac) / ARP(
366 op="who-has",
367 hwsrc=self.pg1._remote_hosts[3].mac,
368 pdst=self.pg1.local_ip4,
369 psrc=self.pg1._remote_hosts[3].ip4,
370 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800371
372 self.pg1.add_stream(p)
373 self.pg_enable_capture(self.pg_interfaces)
374 self.pg_start()
375
376 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200377 self.verify_arp_resp(
378 rx[0],
379 self.pg1.local_mac,
380 self.pg1._remote_hosts[3].mac,
381 self.pg1.local_ip4,
382 self.pg1._remote_hosts[3].ip4,
383 )
Neale Rannsfd2417b2021-07-16 14:00:16 +0000384 self.logger.info(self.vapi.cli("sh ip neighbor-stats pg1"))
385 self.assert_equal(self.get_arp_rx_requests(self.pg1), 1)
386 self.assert_equal(self.get_arp_tx_replies(self.pg1), 1)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800387
388 #
389 # VPP should have learned the mapping for the remote host
390 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200391 self.assertTrue(
392 find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[3].ip4)
393 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800394 #
395 # Fire in an ARP request before the interface becomes IP enabled
396 #
397 self.pg2.generate_remote_hosts(4)
398
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200399 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
400 op="who-has",
401 hwsrc=self.pg2.remote_mac,
402 pdst=self.pg1.local_ip4,
403 psrc=self.pg2.remote_hosts[3].ip4,
404 )
405 pt = (
406 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac)
407 / Dot1Q(vlan=0)
408 / ARP(
409 op="who-has",
410 hwsrc=self.pg2.remote_mac,
411 pdst=self.pg1.local_ip4,
412 psrc=self.pg2.remote_hosts[3].ip4,
413 )
414 )
415 self.send_and_assert_no_replies(self.pg2, p, "interface not IP enabled")
Neale Ranns4b919a52017-03-11 05:55:21 -0800416
417 #
418 # Make pg2 un-numbered to pg1
419 #
420 self.pg2.set_unnumbered(self.pg1.sw_if_index)
421
Neale Rannsac3e72c2019-10-06 01:04:26 -0700422 #
423 # test the unnumbered dump both by all interfaces and just the enabled
424 # one
425 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700426 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700427 self.assertTrue(len(unnum))
428 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
429 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
430 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
431 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700432 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
433 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
434
Neale Ranns4b919a52017-03-11 05:55:21 -0800435 #
436 # We should respond to ARP requests for the unnumbered to address
437 # once an attached route to the source is known
438 #
439 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200440 self.pg2, p, "ARP req for unnumbered address - no source"
441 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800442
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200443 attached_host = VppIpRoute(
444 self,
445 self.pg2.remote_hosts[3].ip4,
446 32,
447 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
448 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800449 attached_host.add_vpp_config()
450
451 self.pg2.add_stream(p)
452 self.pg_enable_capture(self.pg_interfaces)
453 self.pg_start()
454
455 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200456 self.verify_arp_resp(
457 rx[0],
458 self.pg2.local_mac,
459 self.pg2.remote_mac,
460 self.pg1.local_ip4,
461 self.pg2.remote_hosts[3].ip4,
462 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800463
Neale Ranns30d0fd42017-05-30 07:30:04 -0700464 self.pg2.add_stream(pt)
465 self.pg_enable_capture(self.pg_interfaces)
466 self.pg_start()
467
468 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200469 self.verify_arp_resp(
470 rx[0],
471 self.pg2.local_mac,
472 self.pg2.remote_mac,
473 self.pg1.local_ip4,
474 self.pg2.remote_hosts[3].ip4,
475 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700476
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800477 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800478 # A neighbor entry that has no associated FIB-entry
479 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200480 arp_no_fib = VppNeighbor(
481 self,
482 self.pg1.sw_if_index,
483 self.pg1.remote_hosts[4].mac,
484 self.pg1.remote_hosts[4].ip4,
485 is_no_fib_entry=1,
486 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800487 arp_no_fib.add_vpp_config()
488
489 #
490 # check we have the neighbor, but no route
491 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200492 self.assertTrue(
493 find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[4].ip4)
494 )
495 self.assertFalse(find_route(self, self.pg1._remote_hosts[4].ip4, 32))
Neale Ranns3983ac22017-03-10 11:53:27 -0800496 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800497 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
498 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800499 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200500 arp_unnum = VppNeighbor(
501 self,
502 self.pg2.sw_if_index,
503 self.pg1.remote_hosts[5].mac,
504 self.pg1.remote_hosts[5].ip4,
505 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800506 arp_unnum.add_vpp_config()
507
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200508 p = (
509 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
510 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[5].ip4)
511 / UDP(sport=1234, dport=1234)
512 / Raw()
513 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800514
515 self.pg0.add_stream(p)
516 self.pg_enable_capture(self.pg_interfaces)
517 self.pg_start()
518
519 rx = self.pg2.get_capture(1)
520
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200521 self.verify_ip(
522 rx[0],
523 self.pg2.local_mac,
524 self.pg1.remote_hosts[5].mac,
525 self.pg0.remote_ip4,
526 self.pg1._remote_hosts[5].ip4,
527 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800528
529 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800530 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
531 # with the unnumbered interface's address as the source
532 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200533 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
534 op="who-has",
535 hwsrc=self.pg2.remote_mac,
536 pdst=self.pg1.local_ip4,
537 psrc=self.pg1.remote_hosts[6].ip4,
538 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800539
540 self.pg2.add_stream(p)
541 self.pg_enable_capture(self.pg_interfaces)
542 self.pg_start()
543
544 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200545 self.verify_arp_resp(
546 rx[0],
547 self.pg2.local_mac,
548 self.pg2.remote_mac,
549 self.pg1.local_ip4,
550 self.pg1.remote_hosts[6].ip4,
551 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800552
553 #
554 # An attached host route out of pg2 for an undiscovered hosts generates
555 # an ARP request with the unnumbered address as the source
556 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200557 att_unnum = VppIpRoute(
558 self,
559 self.pg1.remote_hosts[7].ip4,
560 32,
561 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
562 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800563 att_unnum.add_vpp_config()
564
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200565 p = (
566 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
567 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[7].ip4)
568 / UDP(sport=1234, dport=1234)
569 / Raw()
570 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800571
572 self.pg0.add_stream(p)
573 self.pg_enable_capture(self.pg_interfaces)
574 self.pg_start()
575
576 rx = self.pg2.get_capture(1)
577
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200578 self.verify_arp_req(
579 rx[0], self.pg2.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[7].ip4
580 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800581
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200582 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
583 op="who-has",
584 hwsrc=self.pg2.remote_mac,
585 pdst=self.pg1.local_ip4,
586 psrc=self.pg1.remote_hosts[7].ip4,
587 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800588
589 self.pg2.add_stream(p)
590 self.pg_enable_capture(self.pg_interfaces)
591 self.pg_start()
592
593 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200594 self.verify_arp_resp(
595 rx[0],
596 self.pg2.local_mac,
597 self.pg2.remote_mac,
598 self.pg1.local_ip4,
599 self.pg1.remote_hosts[7].ip4,
600 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800601
602 #
603 # An attached host route as yet unresolved out of pg2 for an
604 # undiscovered host, an ARP requests begets a response.
605 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200606 att_unnum1 = VppIpRoute(
607 self,
608 self.pg1.remote_hosts[8].ip4,
609 32,
610 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
611 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800612 att_unnum1.add_vpp_config()
613
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200614 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
615 op="who-has",
616 hwsrc=self.pg2.remote_mac,
617 pdst=self.pg1.local_ip4,
618 psrc=self.pg1.remote_hosts[8].ip4,
619 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800620
621 self.pg2.add_stream(p)
622 self.pg_enable_capture(self.pg_interfaces)
623 self.pg_start()
624
625 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200626 self.verify_arp_resp(
627 rx[0],
628 self.pg2.local_mac,
629 self.pg2.remote_mac,
630 self.pg1.local_ip4,
631 self.pg1.remote_hosts[8].ip4,
632 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800633
634 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700635 # Send an ARP request from one of the so-far unlearned remote hosts
636 # with a VLAN0 tag
637 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200638 p = (
639 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[9].mac)
640 / Dot1Q(vlan=0)
641 / ARP(
642 op="who-has",
643 hwsrc=self.pg1._remote_hosts[9].mac,
644 pdst=self.pg1.local_ip4,
645 psrc=self.pg1._remote_hosts[9].ip4,
646 )
647 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700648
649 self.pg1.add_stream(p)
650 self.pg_enable_capture(self.pg_interfaces)
651 self.pg_start()
652
653 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200654 self.verify_arp_resp(
655 rx[0],
656 self.pg1.local_mac,
657 self.pg1._remote_hosts[9].mac,
658 self.pg1.local_ip4,
659 self.pg1._remote_hosts[9].ip4,
660 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700661
662 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700663 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700664 # Should still get an ARP resp since the cover is attached
665 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200666 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) / ARP(
667 op="who-has",
668 hwsrc=self.pg1.remote_mac,
669 pdst=self.pg1.local_ip4,
670 psrc=self.pg1.remote_hosts[10].ip4,
671 )
Neale Rannsca193612017-06-14 06:50:08 -0700672
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200673 r1 = VppIpRoute(
674 self,
675 self.pg1.remote_hosts[10].ip4,
676 30,
677 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
678 )
Neale Rannsca193612017-06-14 06:50:08 -0700679 r1.add_vpp_config()
680
681 self.pg1.add_stream(p)
682 self.pg_enable_capture(self.pg_interfaces)
683 self.pg_start()
684 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200685 self.verify_arp_resp(
686 rx[0],
687 self.pg1.local_mac,
688 self.pg1.remote_mac,
689 self.pg1.local_ip4,
690 self.pg1.remote_hosts[10].ip4,
691 )
Neale Rannsca193612017-06-14 06:50:08 -0700692
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200693 r2 = VppIpRoute(
694 self,
695 self.pg1.remote_hosts[10].ip4,
696 32,
697 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
698 )
Neale Rannsca193612017-06-14 06:50:08 -0700699 r2.add_vpp_config()
700
701 self.pg1.add_stream(p)
702 self.pg_enable_capture(self.pg_interfaces)
703 self.pg_start()
704 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200705 self.verify_arp_resp(
706 rx[0],
707 self.pg1.local_mac,
708 self.pg1.remote_mac,
709 self.pg1.local_ip4,
710 self.pg1.remote_hosts[10].ip4,
711 )
Neale Rannsca193612017-06-14 06:50:08 -0700712
713 #
714 # add an ARP entry that's not on the sub-net and so whose
715 # adj-fib fails the refinement check. then send an ARP request
716 # from that source
717 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200718 a1 = VppNeighbor(
719 self, self.pg0.sw_if_index, self.pg0.remote_mac, "100.100.100.50"
720 )
Neale Rannsca193612017-06-14 06:50:08 -0700721 a1.add_vpp_config()
722
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200723 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
724 op="who-has",
725 hwsrc=self.pg0.remote_mac,
726 psrc="100.100.100.50",
727 pdst=self.pg0.remote_ip4,
728 )
729 self.send_and_assert_no_replies(self.pg0, p, "ARP req for from failed adj-fib")
Neale Rannsca193612017-06-14 06:50:08 -0700730
731 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800732 # ERROR Cases
733 # 1 - don't respond to ARP request for address not within the
734 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700735 # 1b - nor within the unnumbered subnet
736 # 1c - nor within the subnet of a different interface
737 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200738 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
739 op="who-has",
740 hwsrc=self.pg0.remote_mac,
741 pdst="10.10.10.3",
742 psrc=self.pg0.remote_ip4,
743 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800744 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200745 self.pg0, p, "ARP req for non-local destination"
746 )
747 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, "10.10.10.3"))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800748
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200749 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
750 op="who-has",
751 hwsrc=self.pg2.remote_mac,
752 pdst="10.10.10.3",
753 psrc=self.pg1.remote_hosts[7].ip4,
754 )
755 self.send_and_assert_no_replies(
756 self.pg0, p, "ARP req for non-local destination - unnum"
757 )
758
759 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
760 op="who-has",
761 hwsrc=self.pg0.remote_mac,
762 pdst=self.pg1.local_ip4,
763 psrc=self.pg1.remote_ip4,
764 )
765 self.send_and_assert_no_replies(self.pg0, p, "ARP req diff sub-net")
766 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700767
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800768 #
769 # 2 - don't respond to ARP request from an address not within the
770 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700771 # 2b - to a proxied address
772 # 2c - not within a different interface's sub-net
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200773 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
774 op="who-has",
775 hwsrc=self.pg0.remote_mac,
776 psrc="10.10.10.3",
777 pdst=self.pg0.local_ip4,
778 )
779 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
780 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
781 op="who-has",
782 hwsrc=self.pg2.remote_mac,
783 psrc="10.10.10.3",
784 pdst=self.pg0.local_ip4,
785 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800786 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200787 self.pg0, p, "ARP req for non-local source - unnum"
788 )
789 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
790 op="who-has",
791 hwsrc=self.pg0.remote_mac,
792 psrc=self.pg1.remote_ip4,
793 pdst=self.pg0.local_ip4,
794 )
795 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800796
797 #
798 # 3 - don't respond to ARP request from an address that belongs to
799 # the router
800 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200801 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
802 op="who-has",
803 hwsrc=self.pg0.remote_mac,
804 psrc=self.pg0.local_ip4,
805 pdst=self.pg0.local_ip4,
806 )
807 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800808
809 #
810 # 4 - don't respond to ARP requests that has mac source different
811 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800812 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200813 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
814 op="who-has",
815 hwsrc="00:00:00:DE:AD:BE",
816 psrc=self.pg0.remote_ip4,
817 pdst=self.pg0.local_ip4,
818 )
819 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800820
821 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800822 # 5 - don't respond to ARP requests for address within the
823 # interface's sub-net but not the interface's address
824 #
825 self.pg0.generate_remote_hosts(2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200826 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
827 op="who-has",
828 hwsrc=self.pg0.remote_mac,
829 psrc=self.pg0.remote_hosts[0].ip4,
830 pdst=self.pg0.remote_hosts[1].ip4,
831 )
832 self.send_and_assert_no_replies(
833 self.pg0, p, "ARP req for non-local destination"
834 )
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800835
836 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800837 # cleanup
838 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800839 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800840 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800841
Neale Ranns4b919a52017-03-11 05:55:21 -0800842 # need this to flush the adj-fibs
843 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
844 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700845 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800846
Alexander Chernavin8a92b682023-05-22 14:27:24 +0000847 def test_arp_after_mac_change(self):
848 """ARP (after MAC address change)"""
849
850 #
851 # Prepare a subinterface
852 #
853 subif0 = VppDot1ADSubint(self, self.pg1, 0, 300, 400)
854 subif0.admin_up()
855 subif0.config_ip4()
856
857 #
858 # Send a packet to cause ARP generation for the parent interface's remote host
859 #
860 p1 = (
861 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
862 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
863 / UDP(sport=1234, dport=1234)
864 / Raw()
865 )
866
867 self.pg0.add_stream(p1)
868 self.pg_enable_capture(self.pg_interfaces)
869 self.pg_start()
870
871 rx = self.pg1.get_capture(1)
872
873 self.verify_arp_req(
874 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
875 )
876
877 #
878 # Send a packet to cause ARP generation for the subinterface's remote host
879 #
880 p2 = (
881 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
882 / IP(src=self.pg0.remote_ip4, dst=subif0.remote_ip4)
883 / UDP(sport=1234, dport=1234)
884 / Raw()
885 )
886
887 self.pg0.add_stream(p2)
888 self.pg_enable_capture(self.pg_interfaces)
889 self.pg_start()
890
891 rx = self.pg1.get_capture(1)
892
893 self.verify_arp_req(
894 rx[0],
895 self.pg1.local_mac,
896 subif0.local_ip4,
897 subif0.remote_ip4,
898 subif0.DOT1AD_TYPE,
899 )
900
901 #
902 # Change MAC address of the parent interface
903 #
904 pg1_mac_saved = self.pg1.local_mac
905 self.pg1.set_mac(MACAddress("00:00:00:11:22:33"))
906
907 #
908 # Send a packet to cause ARP generation for the parent interface's remote host
909 # - expect new MAC address is used as the source
910 #
911 self.pg0.add_stream(p1)
912 self.pg_enable_capture(self.pg_interfaces)
913 self.pg_start()
914
915 rx = self.pg1.get_capture(1)
916
917 self.verify_arp_req(
918 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
919 )
920
921 #
922 # Send a packet to cause ARP generation for the subinterface's remote host
923 # - expect new MAC address is used as the source
924 #
925
926 self.pg0.add_stream(p2)
927 self.pg_enable_capture(self.pg_interfaces)
928 self.pg_start()
929
930 rx = self.pg1.get_capture(1)
931
932 self.verify_arp_req(
933 rx[0],
934 self.pg1.local_mac,
935 subif0.local_ip4,
936 subif0.remote_ip4,
937 subif0.DOT1AD_TYPE,
938 )
939
940 #
941 # Cleanup
942 #
943 subif0.remove_vpp_config()
944 self.pg1.set_mac(MACAddress(pg1_mac_saved))
945
Neale Ranns24b170a2017-08-15 05:33:11 -0700946 def test_proxy_mirror_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200947 """Interface Mirror Proxy ARP"""
Neale Ranns24b170a2017-08-15 05:33:11 -0700948
949 #
950 # When VPP has an interface whose address is also applied to a TAP
951 # interface on the host, then VPP's TAP interface will be unnumbered
952 # to the 'real' interface and do proxy ARP from the host.
953 # the curious aspect of this setup is that ARP requests from the host
954 # will come from the VPP's own address.
955 #
956 self.pg0.generate_remote_hosts(2)
957
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200958 arp_req_from_me = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
959 op="who-has",
960 hwsrc=self.pg2.remote_mac,
961 pdst=self.pg0.remote_hosts[1].ip4,
962 psrc=self.pg0.local_ip4,
963 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700964
965 #
966 # Configure Proxy ARP for the subnet on PG0addresses on pg0
967 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200968 self.vapi.proxy_arp_add_del(
969 proxy={
970 "table_id": 0,
971 "low": self.pg0._local_ip4_subnet,
972 "hi": self.pg0._local_ip4_bcast,
973 },
974 is_add=1,
975 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700976
977 # Make pg2 un-numbered to pg0
978 #
979 self.pg2.set_unnumbered(self.pg0.sw_if_index)
980
981 #
982 # Enable pg2 for proxy ARP
983 #
984 self.pg2.set_proxy_arp()
985
986 #
987 # Send the ARP request with an originating address that
988 # is VPP's own address
989 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000990 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200991 self.verify_arp_resp(
992 rx[0],
993 self.pg2.local_mac,
994 self.pg2.remote_mac,
995 self.pg0.remote_hosts[1].ip4,
996 self.pg0.local_ip4,
997 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700998
999 #
1000 # validate we have not learned an ARP entry as a result of this
1001 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001002 self.assertFalse(find_nbr(self, self.pg2.sw_if_index, self.pg0.local_ip4))
Neale Ranns24b170a2017-08-15 05:33:11 -07001003
1004 #
Neale Ranns240dcb22020-04-23 09:04:59 +00001005 # setup a punt redirect so packets from the uplink go to the tap
1006 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001007 redirect = VppIpPuntRedirect(
1008 self, self.pg0.sw_if_index, self.pg2.sw_if_index, self.pg0.local_ip4
1009 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001010 redirect.add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00001011
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001012 p_tcp = (
1013 Ether(
1014 src=self.pg0.remote_mac,
1015 dst=self.pg0.local_mac,
1016 )
1017 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
1018 / TCP(sport=80, dport=80)
1019 / Raw()
1020 )
Neale Ranns240dcb22020-04-23 09:04:59 +00001021 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
1022
1023 # there's no ARP entry so this is an ARP req
1024 self.assertTrue(rx[0].haslayer(ARP))
1025
1026 # and ARP entry for VPP's pg0 address on the host interface
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001027 n1 = VppNeighbor(
1028 self,
1029 self.pg2.sw_if_index,
1030 self.pg2.remote_mac,
1031 self.pg0.local_ip4,
1032 is_no_fib_entry=True,
1033 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00001034 # now the packets shold forward
1035 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
1036 self.assertFalse(rx[0].haslayer(ARP))
1037 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
1038
1039 #
1040 # flush the neighbor cache on the uplink
1041 #
1042 af = VppEnum.vl_api_address_family_t
1043 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
1044
1045 # ensure we can still resolve the ARPs on the uplink
1046 self.pg0.resolve_arp()
1047
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001048 self.assertTrue(find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_ip4))
Neale Ranns240dcb22020-04-23 09:04:59 +00001049
1050 #
Neale Ranns24b170a2017-08-15 05:33:11 -07001051 # cleanup
1052 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001053 self.vapi.proxy_arp_add_del(
1054 proxy={
1055 "table_id": 0,
1056 "low": self.pg0._local_ip4_subnet,
1057 "hi": self.pg0._local_ip4_bcast,
1058 },
1059 is_add=0,
1060 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001061 redirect.remove_vpp_config()
Neale Ranns24b170a2017-08-15 05:33:11 -07001062
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001063 def test_proxy_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001064 """Proxy ARP"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001065
Neale Rannsd5b6aa12017-05-16 08:46:45 -07001066 self.pg1.generate_remote_hosts(2)
1067
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001068 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001069 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001070 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001071 arp_req_pg0 = Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1072 op="who-has",
1073 hwsrc=self.pg0.remote_mac,
1074 pdst="10.10.10.3",
1075 psrc=self.pg0.remote_ip4,
1076 )
1077 arp_req_pg0_tagged = (
1078 Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff")
1079 / Dot1Q(vlan=0)
1080 / ARP(
1081 op="who-has",
1082 hwsrc=self.pg0.remote_mac,
1083 pdst="10.10.10.3",
1084 psrc=self.pg0.remote_ip4,
1085 )
1086 )
1087 arp_req_pg1 = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1088 op="who-has",
1089 hwsrc=self.pg1.remote_mac,
1090 pdst="10.10.10.3",
1091 psrc=self.pg1.remote_ip4,
1092 )
1093 arp_req_pg2 = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1094 op="who-has",
1095 hwsrc=self.pg2.remote_mac,
1096 pdst="10.10.10.3",
1097 psrc=self.pg1.remote_hosts[1].ip4,
1098 )
1099 arp_req_pg3 = Ether(src=self.pg3.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1100 op="who-has",
1101 hwsrc=self.pg3.remote_mac,
1102 pdst="10.10.10.3",
1103 psrc=self.pg3.remote_ip4,
1104 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001105
1106 #
1107 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
1108 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001109 self.vapi.proxy_arp_add_del(
1110 proxy={"table_id": 0, "low": "10.10.10.2", "hi": "10.10.10.124"}, is_add=1
1111 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001112
1113 #
1114 # No responses are sent when the interfaces are not enabled for proxy
1115 # ARP
1116 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001117 self.send_and_assert_no_replies(
1118 self.pg0, arp_req_pg0, "ARP req from unconfigured interface"
1119 )
1120 self.send_and_assert_no_replies(
1121 self.pg2, arp_req_pg2, "ARP req from unconfigured interface"
1122 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001123
1124 #
1125 # Make pg2 un-numbered to pg1
1126 # still won't reply.
1127 #
1128 self.pg2.set_unnumbered(self.pg1.sw_if_index)
1129
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001130 self.send_and_assert_no_replies(
1131 self.pg2, arp_req_pg2, "ARP req from unnumbered interface"
1132 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001133
1134 #
1135 # Enable each interface to reply to proxy ARPs
1136 #
1137 for i in self.pg_interfaces:
1138 i.set_proxy_arp()
1139
1140 #
1141 # Now each of the interfaces should reply to a request to a proxied
1142 # address
1143 #
1144 self.pg0.add_stream(arp_req_pg0)
1145 self.pg_enable_capture(self.pg_interfaces)
1146 self.pg_start()
1147
1148 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001149 self.verify_arp_resp(
1150 rx[0],
1151 self.pg0.local_mac,
1152 self.pg0.remote_mac,
1153 "10.10.10.3",
1154 self.pg0.remote_ip4,
1155 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001156
Neale Ranns30d0fd42017-05-30 07:30:04 -07001157 self.pg0.add_stream(arp_req_pg0_tagged)
1158 self.pg_enable_capture(self.pg_interfaces)
1159 self.pg_start()
1160
1161 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001162 self.verify_arp_resp(
1163 rx[0],
1164 self.pg0.local_mac,
1165 self.pg0.remote_mac,
1166 "10.10.10.3",
1167 self.pg0.remote_ip4,
1168 )
Neale Ranns30d0fd42017-05-30 07:30:04 -07001169
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001170 self.pg1.add_stream(arp_req_pg1)
1171 self.pg_enable_capture(self.pg_interfaces)
1172 self.pg_start()
1173
1174 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001175 self.verify_arp_resp(
1176 rx[0],
1177 self.pg1.local_mac,
1178 self.pg1.remote_mac,
1179 "10.10.10.3",
1180 self.pg1.remote_ip4,
1181 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001182
1183 self.pg2.add_stream(arp_req_pg2)
1184 self.pg_enable_capture(self.pg_interfaces)
1185 self.pg_start()
1186
1187 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001188 self.verify_arp_resp(
1189 rx[0],
1190 self.pg2.local_mac,
1191 self.pg2.remote_mac,
1192 "10.10.10.3",
1193 self.pg1.remote_hosts[1].ip4,
1194 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001195
1196 #
1197 # A request for an address out of the configured range
1198 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001199 arp_req_pg1_hi = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1200 op="who-has",
1201 hwsrc=self.pg1.remote_mac,
1202 pdst="10.10.10.125",
1203 psrc=self.pg1.remote_ip4,
1204 )
1205 self.send_and_assert_no_replies(
1206 self.pg1, arp_req_pg1_hi, "ARP req out of range HI"
1207 )
1208 arp_req_pg1_low = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1209 op="who-has",
1210 hwsrc=self.pg1.remote_mac,
1211 pdst="10.10.10.1",
1212 psrc=self.pg1.remote_ip4,
1213 )
1214 self.send_and_assert_no_replies(
1215 self.pg1, arp_req_pg1_low, "ARP req out of range Low"
1216 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001217
1218 #
1219 # Request for an address in the proxy range but from an interface
1220 # in a different VRF
1221 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001222 self.send_and_assert_no_replies(
1223 self.pg3, arp_req_pg3, "ARP req from different VRF"
1224 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001225
1226 #
1227 # Disable Each interface for proxy ARP
1228 # - expect none to respond
1229 #
1230 for i in self.pg_interfaces:
1231 i.set_proxy_arp(0)
1232
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001233 self.send_and_assert_no_replies(self.pg0, arp_req_pg0, "ARP req from disable")
1234 self.send_and_assert_no_replies(self.pg1, arp_req_pg1, "ARP req from disable")
1235 self.send_and_assert_no_replies(self.pg2, arp_req_pg2, "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001236
1237 #
1238 # clean up on interface 2
1239 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001240 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001241
1242 def test_mpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001243 """MPLS"""
Neale Ranns37be7362017-02-21 17:30:26 -08001244
1245 #
1246 # Interface 2 does not yet have ip4 config
1247 #
1248 self.pg2.config_ip4()
1249 self.pg2.generate_remote_hosts(2)
1250
1251 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001252 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001253 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001254 ip_10_0_0_1 = VppIpRoute(
1255 self,
1256 "10.0.0.1",
1257 32,
1258 [
1259 VppRoutePath(
1260 self.pg2.remote_hosts[1].ip4, self.pg2.sw_if_index, labels=[55]
1261 )
1262 ],
1263 )
Neale Ranns37be7362017-02-21 17:30:26 -08001264 ip_10_0_0_1.add_vpp_config()
1265
1266 #
1267 # packets should generate an ARP request
1268 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001269 p = (
1270 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1271 / IP(src=self.pg0.remote_ip4, dst="10.0.0.1")
1272 / UDP(sport=1234, dport=1234)
1273 / Raw(b"\xa5" * 100)
1274 )
Neale Ranns37be7362017-02-21 17:30:26 -08001275
1276 self.pg0.add_stream(p)
1277 self.pg_enable_capture(self.pg_interfaces)
1278 self.pg_start()
1279
1280 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001281 self.verify_arp_req(
1282 rx[0], self.pg2.local_mac, self.pg2.local_ip4, self.pg2._remote_hosts[1].ip4
1283 )
Neale Ranns37be7362017-02-21 17:30:26 -08001284
1285 #
1286 # now resolve the neighbours
1287 #
1288 self.pg2.configure_ipv4_neighbors()
1289
1290 #
1291 # Now packet should be properly MPLS encapped.
1292 # This verifies that MPLS link-type adjacencies are completed
1293 # when the ARP entry resolves
1294 #
1295 self.pg0.add_stream(p)
1296 self.pg_enable_capture(self.pg_interfaces)
1297 self.pg_start()
1298
1299 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001300 self.verify_ip_o_mpls(
1301 rx[0],
1302 self.pg2.local_mac,
1303 self.pg2.remote_hosts[1].mac,
1304 55,
1305 self.pg0.remote_ip4,
1306 "10.0.0.1",
1307 )
Neale Ranns4b919a52017-03-11 05:55:21 -08001308 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001309
Matthew Smithcb9ab472017-05-16 21:35:56 -05001310 def test_arp_vrrp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001311 """ARP reply with VRRP virtual src hw addr"""
Matthew Smithcb9ab472017-05-16 21:35:56 -05001312
1313 #
1314 # IP packet destined for pg1 remote host arrives on pg0 resulting
1315 # in an ARP request for the address of the remote host on pg1
1316 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001317 p0 = (
1318 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1319 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1320 / UDP(sport=1234, dport=1234)
1321 / Raw()
1322 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001323
Neale Ranns37029302018-08-10 05:30:06 -07001324 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001325
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001326 self.verify_arp_req(
1327 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
1328 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001329
1330 #
1331 # ARP reply for address of pg1 remote host arrives on pg1 with
1332 # the hw src addr set to a value in the VRRP IPv4 range of
1333 # MAC addresses
1334 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001335 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
1336 op="is-at",
1337 hwdst=self.pg1.local_mac,
1338 hwsrc="00:00:5e:00:01:09",
1339 pdst=self.pg1.local_ip4,
1340 psrc=self.pg1.remote_ip4,
1341 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001342
Neale Ranns37029302018-08-10 05:30:06 -07001343 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001344
1345 #
1346 # IP packet destined for pg1 remote host arrives on pg0 again.
1347 # VPP should have an ARP entry for that address now and the packet
1348 # should be sent out pg1.
1349 #
Neale Ranns37029302018-08-10 05:30:06 -07001350 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001351
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001352 self.verify_ip(
1353 rx1[0],
1354 self.pg1.local_mac,
1355 "00:00:5e:00:01:09",
1356 self.pg0.remote_ip4,
1357 self.pg1.remote_ip4,
1358 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001359
1360 self.pg1.admin_down()
1361 self.pg1.admin_up()
1362
Neale Rannsdcd6d622017-05-26 02:59:16 -07001363 def test_arp_duplicates(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001364 """ARP Duplicates"""
Neale Rannsdcd6d622017-05-26 02:59:16 -07001365
1366 #
1367 # Generate some hosts on the LAN
1368 #
1369 self.pg1.generate_remote_hosts(3)
1370
1371 #
1372 # Add host 1 on pg1 and pg2
1373 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001374 arp_pg1 = VppNeighbor(
1375 self,
1376 self.pg1.sw_if_index,
1377 self.pg1.remote_hosts[1].mac,
1378 self.pg1.remote_hosts[1].ip4,
1379 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001380 arp_pg1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001381 arp_pg2 = VppNeighbor(
1382 self,
1383 self.pg2.sw_if_index,
1384 self.pg2.remote_mac,
1385 self.pg1.remote_hosts[1].ip4,
1386 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001387 arp_pg2.add_vpp_config()
1388
1389 #
1390 # IP packet destined for pg1 remote host arrives on pg1 again.
1391 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001392 p = (
1393 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1394 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1395 / UDP(sport=1234, dport=1234)
1396 / Raw()
1397 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001398
1399 self.pg0.add_stream(p)
1400 self.pg_enable_capture(self.pg_interfaces)
1401 self.pg_start()
1402
1403 rx1 = self.pg1.get_capture(1)
1404
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001405 self.verify_ip(
1406 rx1[0],
1407 self.pg1.local_mac,
1408 self.pg1.remote_hosts[1].mac,
1409 self.pg0.remote_ip4,
1410 self.pg1.remote_hosts[1].ip4,
1411 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001412
1413 #
1414 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001415 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001416 #
1417 arp_pg1.remove_vpp_config()
1418
1419 self.pg0.add_stream(p)
1420 self.pg_enable_capture(self.pg_interfaces)
1421 self.pg_start()
1422
1423 rx1 = self.pg1.get_capture(1)
1424
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001425 self.verify_arp_req(
1426 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_hosts[1].ip4
1427 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001428
1429 #
1430 # Add it back
1431 #
1432 arp_pg1.add_vpp_config()
1433
1434 self.pg0.add_stream(p)
1435 self.pg_enable_capture(self.pg_interfaces)
1436 self.pg_start()
1437
1438 rx1 = self.pg1.get_capture(1)
1439
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001440 self.verify_ip(
1441 rx1[0],
1442 self.pg1.local_mac,
1443 self.pg1.remote_hosts[1].mac,
1444 self.pg0.remote_ip4,
1445 self.pg1.remote_hosts[1].ip4,
1446 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001447
Neale Ranns15002542017-09-10 04:39:11 -07001448 def test_arp_static(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001449 """ARP Static"""
Neale Ranns15002542017-09-10 04:39:11 -07001450 self.pg2.generate_remote_hosts(3)
1451
1452 #
1453 # Add a static ARP entry
1454 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001455 static_arp = VppNeighbor(
1456 self,
1457 self.pg2.sw_if_index,
1458 self.pg2.remote_hosts[1].mac,
1459 self.pg2.remote_hosts[1].ip4,
1460 is_static=1,
1461 )
Neale Ranns15002542017-09-10 04:39:11 -07001462 static_arp.add_vpp_config()
1463
1464 #
1465 # Add the connected prefix to the interface
1466 #
1467 self.pg2.config_ip4()
1468
1469 #
1470 # We should now find the adj-fib
1471 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001472 self.assertTrue(
1473 find_nbr(
1474 self, self.pg2.sw_if_index, self.pg2.remote_hosts[1].ip4, is_static=1
1475 )
1476 )
1477 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32))
Neale Ranns15002542017-09-10 04:39:11 -07001478
1479 #
1480 # remove the connected
1481 #
1482 self.pg2.unconfig_ip4()
1483
1484 #
1485 # put the interface into table 1
1486 #
1487 self.pg2.set_table_ip4(1)
1488
1489 #
1490 # configure the same connected and expect to find the
1491 # adj fib in the new table
1492 #
1493 self.pg2.config_ip4()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001494 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32, table_id=1))
Neale Ranns15002542017-09-10 04:39:11 -07001495
1496 #
1497 # clean-up
1498 #
1499 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001500 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001501 self.pg2.set_table_ip4(0)
1502
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001503 def test_arp_static_replace_dynamic_same_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001504 """ARP Static can replace Dynamic (same mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001505 self.pg2.generate_remote_hosts(1)
1506
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001507 dyn_arp = VppNeighbor(
1508 self,
1509 self.pg2.sw_if_index,
1510 self.pg2.remote_hosts[0].mac,
1511 self.pg2.remote_hosts[0].ip4,
1512 )
1513 static_arp = VppNeighbor(
1514 self,
1515 self.pg2.sw_if_index,
1516 self.pg2.remote_hosts[0].mac,
1517 self.pg2.remote_hosts[0].ip4,
1518 is_static=1,
1519 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001520
1521 #
1522 # Add a dynamic ARP entry
1523 #
1524 dyn_arp.add_vpp_config()
1525
1526 #
1527 # We should find the dynamic nbr
1528 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001529 self.assertFalse(
1530 find_nbr(
1531 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1532 )
1533 )
1534 self.assertTrue(
1535 find_nbr(
1536 self,
1537 self.pg2.sw_if_index,
1538 self.pg2.remote_hosts[0].ip4,
1539 is_static=0,
1540 mac=self.pg2.remote_hosts[0].mac,
1541 )
1542 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001543
1544 #
1545 # Add a static ARP entry with the same mac
1546 #
1547 static_arp.add_vpp_config()
1548
1549 #
1550 # We should now find the static nbr with the same mac
1551 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001552 self.assertFalse(
1553 find_nbr(
1554 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1555 )
1556 )
1557 self.assertTrue(
1558 find_nbr(
1559 self,
1560 self.pg2.sw_if_index,
1561 self.pg2.remote_hosts[0].ip4,
1562 is_static=1,
1563 mac=self.pg2.remote_hosts[0].mac,
1564 )
1565 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001566
1567 #
1568 # clean-up
1569 #
1570 static_arp.remove_vpp_config()
1571
1572 def test_arp_static_replace_dynamic_diff_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001573 """ARP Static can replace Dynamic (diff mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001574 self.pg2.generate_remote_hosts(2)
1575
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001576 dyn_arp = VppNeighbor(
1577 self,
1578 self.pg2.sw_if_index,
1579 self.pg2.remote_hosts[0].mac,
1580 self.pg2.remote_hosts[0].ip4,
1581 )
1582 static_arp = VppNeighbor(
1583 self,
1584 self.pg2.sw_if_index,
1585 self.pg2.remote_hosts[1].mac,
1586 self.pg2.remote_hosts[0].ip4,
1587 is_static=1,
1588 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001589
1590 #
1591 # Add a dynamic ARP entry
1592 #
1593 dyn_arp.add_vpp_config()
1594
1595 #
1596 # We should find the dynamic nbr
1597 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001598 self.assertFalse(
1599 find_nbr(
1600 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1601 )
1602 )
1603 self.assertTrue(
1604 find_nbr(
1605 self,
1606 self.pg2.sw_if_index,
1607 self.pg2.remote_hosts[0].ip4,
1608 is_static=0,
1609 mac=self.pg2.remote_hosts[0].mac,
1610 )
1611 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001612
1613 #
1614 # Add a static ARP entry with a changed mac
1615 #
1616 static_arp.add_vpp_config()
1617
1618 #
1619 # We should now find the static nbr with a changed mac
1620 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001621 self.assertFalse(
1622 find_nbr(
1623 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1624 )
1625 )
1626 self.assertTrue(
1627 find_nbr(
1628 self,
1629 self.pg2.sw_if_index,
1630 self.pg2.remote_hosts[0].ip4,
1631 is_static=1,
1632 mac=self.pg2.remote_hosts[1].mac,
1633 )
1634 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001635
1636 #
1637 # clean-up
1638 #
1639 static_arp.remove_vpp_config()
1640
Neale Rannsc819fc62018-02-16 02:44:05 -08001641 def test_arp_incomplete(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001642 """ARP Incomplete"""
Neale Rannsea8adf72021-08-13 08:10:59 +00001643 self.pg1.generate_remote_hosts(4)
Neale Rannsc819fc62018-02-16 02:44:05 -08001644
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001645 p0 = (
1646 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1647 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1648 / UDP(sport=1234, dport=1234)
1649 / Raw()
1650 )
1651 p1 = (
1652 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1653 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
1654 / UDP(sport=1234, dport=1234)
1655 / Raw()
1656 )
1657 p2 = (
1658 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1659 / IP(src=self.pg0.remote_ip4, dst="1.1.1.1")
1660 / UDP(sport=1234, dport=1234)
1661 / Raw()
1662 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001663
1664 #
1665 # a packet to an unresolved destination generates an ARP request
1666 #
1667 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001668 self.verify_arp_req(
1669 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
1670 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001671
1672 #
1673 # add a neighbour for remote host 1
1674 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001675 static_arp = VppNeighbor(
1676 self,
1677 self.pg1.sw_if_index,
1678 self.pg1.remote_hosts[1].mac,
1679 self.pg1.remote_hosts[1].ip4,
1680 is_static=1,
1681 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001682 static_arp.add_vpp_config()
1683
1684 #
Neale Rannsea8adf72021-08-13 08:10:59 +00001685 # add a route through remote host 3 hence we get an incomplete
1686 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001687 VppIpRoute(
1688 self,
1689 "1.1.1.1",
1690 32,
1691 [VppRoutePath(self.pg1.remote_hosts[3].ip4, self.pg1.sw_if_index)],
1692 ).add_vpp_config()
Neale Rannsea8adf72021-08-13 08:10:59 +00001693 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001694 self.verify_arp_req(
1695 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[3].ip4
1696 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001697
1698 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001699 # change the interface's MAC
1700 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001701 self.vapi.sw_interface_set_mac_address(
1702 self.pg1.sw_if_index, "00:00:00:33:33:33"
1703 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001704
1705 #
1706 # now ARP requests come from the new source mac
1707 #
1708 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001709 self.verify_arp_req(
1710 rx[0],
1711 "00:00:00:33:33:33",
1712 self.pg1.local_ip4,
1713 self.pg1._remote_hosts[2].ip4,
1714 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001715 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001716 self.verify_arp_req(
1717 rx[0],
1718 "00:00:00:33:33:33",
1719 self.pg1.local_ip4,
1720 self.pg1._remote_hosts[3].ip4,
1721 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001722
1723 #
1724 # packets to the resolved host also have the new source mac
1725 #
1726 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001727 self.verify_ip(
1728 rx[0],
1729 "00:00:00:33:33:33",
1730 self.pg1.remote_hosts[1].mac,
1731 self.pg0.remote_ip4,
1732 self.pg1.remote_hosts[1].ip4,
1733 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001734
1735 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001736 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001737 # configured subnet and thus no glean
1738 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001739 self.vapi.sw_interface_set_mac_address(
1740 self.pg2.sw_if_index, "00:00:00:33:33:33"
1741 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001742
Neale Ranns59ae61e2018-06-07 18:09:49 -07001743 def test_garp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001744 """GARP"""
Neale Ranns59ae61e2018-06-07 18:09:49 -07001745
1746 #
1747 # Generate some hosts on the LAN
1748 #
1749 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001750 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001751
1752 #
1753 # And an ARP entry
1754 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001755 arp = VppNeighbor(
1756 self,
1757 self.pg1.sw_if_index,
1758 self.pg1.remote_hosts[1].mac,
1759 self.pg1.remote_hosts[1].ip4,
1760 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001761 arp.add_vpp_config()
1762
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001763 self.assertTrue(
1764 find_nbr(
1765 self,
1766 self.pg1.sw_if_index,
1767 self.pg1.remote_hosts[1].ip4,
1768 mac=self.pg1.remote_hosts[1].mac,
1769 )
1770 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001771
1772 #
1773 # Send a GARP (request) to swap the host 1's address to that of host 2
1774 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001775 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[2].mac) / ARP(
1776 op="who-has",
1777 hwdst=self.pg1.local_mac,
1778 hwsrc=self.pg1.remote_hosts[2].mac,
1779 pdst=self.pg1.remote_hosts[1].ip4,
1780 psrc=self.pg1.remote_hosts[1].ip4,
1781 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001782
1783 self.pg1.add_stream(p1)
1784 self.pg_enable_capture(self.pg_interfaces)
1785 self.pg_start()
1786
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001787 self.assertTrue(
1788 find_nbr(
1789 self,
1790 self.pg1.sw_if_index,
1791 self.pg1.remote_hosts[1].ip4,
1792 mac=self.pg1.remote_hosts[2].mac,
1793 )
1794 )
Neale Rannsfd2417b2021-07-16 14:00:16 +00001795 self.assert_equal(self.get_arp_rx_garp(self.pg1), 1)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001796
1797 #
1798 # Send a GARP (reply) to swap the host 1's address to that of host 3
1799 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001800 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1801 op="is-at",
1802 hwdst=self.pg1.local_mac,
1803 hwsrc=self.pg1.remote_hosts[3].mac,
1804 pdst=self.pg1.remote_hosts[1].ip4,
1805 psrc=self.pg1.remote_hosts[1].ip4,
1806 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001807
1808 self.pg1.add_stream(p1)
1809 self.pg_enable_capture(self.pg_interfaces)
1810 self.pg_start()
1811
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001812 self.assertTrue(
1813 find_nbr(
1814 self,
1815 self.pg1.sw_if_index,
1816 self.pg1.remote_hosts[1].ip4,
1817 mac=self.pg1.remote_hosts[3].mac,
1818 )
1819 )
Neale Rannsfd2417b2021-07-16 14:00:16 +00001820 self.assert_equal(self.get_arp_rx_garp(self.pg1), 2)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001821
1822 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001823 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001824 # don't result in new neighbour entries
1825 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001826 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1827 op="who-has",
1828 hwdst=self.pg1.local_mac,
1829 hwsrc=self.pg1.remote_hosts[3].mac,
1830 pdst=self.pg1.remote_hosts[2].ip4,
1831 psrc=self.pg1.remote_hosts[2].ip4,
1832 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001833
1834 self.pg1.add_stream(p1)
1835 self.pg_enable_capture(self.pg_interfaces)
1836 self.pg_start()
1837
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001838 self.assertFalse(
1839 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1840 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001841
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001842 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1843 op="is-at",
1844 hwdst=self.pg1.local_mac,
1845 hwsrc=self.pg1.remote_hosts[3].mac,
1846 pdst=self.pg1.remote_hosts[2].ip4,
1847 psrc=self.pg1.remote_hosts[2].ip4,
1848 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001849
1850 self.pg1.add_stream(p1)
1851 self.pg_enable_capture(self.pg_interfaces)
1852 self.pg_start()
1853
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001854 self.assertFalse(
1855 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1856 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001857
Neale Ranns22eefd72020-09-23 11:25:21 +00001858 #
1859 # IP address in different subnets are not learnt
1860 #
1861 self.pg2.configure_ipv4_neighbors()
1862
Benoît Ganne114b1542022-09-12 17:56:16 +02001863 cntr = self.statistics.get_err_counter(
1864 "/err/arp-reply/l3_dst_address_not_local"
1865 )
1866
Neale Ranns22eefd72020-09-23 11:25:21 +00001867 for op in ["is-at", "who-has"]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001868 p1 = [
1869 (
1870 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1871 / ARP(
1872 op=op,
1873 hwdst=self.pg2.local_mac,
1874 hwsrc=self.pg2.remote_hosts[1].mac,
1875 pdst=self.pg2.remote_hosts[1].ip4,
1876 psrc=self.pg2.remote_hosts[1].ip4,
1877 )
1878 ),
1879 (
1880 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1881 / ARP(
1882 op=op,
1883 hwdst="ff:ff:ff:ff:ff:ff",
1884 hwsrc=self.pg2.remote_hosts[1].mac,
1885 pdst=self.pg2.remote_hosts[1].ip4,
1886 psrc=self.pg2.remote_hosts[1].ip4,
1887 )
1888 ),
1889 ]
Neale Ranns22eefd72020-09-23 11:25:21 +00001890
1891 self.send_and_assert_no_replies(self.pg1, p1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001892 self.assertFalse(
1893 find_nbr(self, self.pg1.sw_if_index, self.pg2.remote_hosts[1].ip4)
1894 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001895
1896 # they are all dropped because the subnet's don't match
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001897 self.assertEqual(
Benoît Ganne114b1542022-09-12 17:56:16 +02001898 cntr + 4,
Neale Ranns13a74ae2022-08-09 00:59:37 +00001899 self.statistics.get_err_counter("/err/arp-reply/l3_dst_address_not_local"),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001900 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001901
Neale Ranns77f91622020-11-23 16:25:27 +00001902 def test_arp_incomplete2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001903 """Incomplete Entries"""
Neale Rannsc8352bc2018-08-29 10:23:58 -07001904
1905 #
Neale Rannscd35e532018-08-31 02:51:45 -07001906 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001907 #
1908 self.pg0.generate_remote_hosts(2)
1909
Neale Rannscd35e532018-08-31 02:51:45 -07001910 #
1911 # IPv4/ARP
1912 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001913 ip_10_0_0_1 = VppIpRoute(
1914 self,
1915 "10.0.0.1",
1916 32,
1917 [VppRoutePath(self.pg0.remote_hosts[1].ip4, self.pg0.sw_if_index)],
1918 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001919 ip_10_0_0_1.add_vpp_config()
1920
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001921 p1 = (
1922 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1923 / IP(src=self.pg1.remote_ip4, dst="10.0.0.1")
1924 / UDP(sport=1234, dport=1234)
1925 / Raw()
1926 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001927
1928 self.pg1.add_stream(p1 * 257)
1929 self.pg_enable_capture(self.pg_interfaces)
1930 self.pg_start()
1931 rx = self.pg0._get_capture(1)
1932
1933 #
1934 # how many we get is going to be dependent on the time for packet
1935 # processing but it should be small
1936 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001937 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001938
Neale Rannscd35e532018-08-31 02:51:45 -07001939 #
1940 # IPv6/ND
1941 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001942 ip_10_1 = VppIpRoute(
1943 self,
1944 "10::1",
1945 128,
1946 [
1947 VppRoutePath(
1948 self.pg0.remote_hosts[1].ip6,
1949 self.pg0.sw_if_index,
1950 proto=DpoProto.DPO_PROTO_IP6,
1951 )
1952 ],
1953 )
Neale Rannscd35e532018-08-31 02:51:45 -07001954 ip_10_1.add_vpp_config()
1955
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001956 p1 = (
1957 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1958 / IPv6(src=self.pg1.remote_ip6, dst="10::1")
1959 / UDP(sport=1234, dport=1234)
1960 / Raw()
1961 )
Neale Rannscd35e532018-08-31 02:51:45 -07001962
1963 self.pg1.add_stream(p1 * 257)
1964 self.pg_enable_capture(self.pg_interfaces)
1965 self.pg_start()
1966 rx = self.pg0._get_capture(1)
1967
1968 #
1969 # how many we get is going to be dependent on the time for packet
1970 # processing but it should be small
1971 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001972 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001973
Neale Ranns7425f922019-01-23 00:36:16 -08001974 def test_arp_forus(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001975 """ARP for for-us"""
Neale Ranns7425f922019-01-23 00:36:16 -08001976
1977 #
1978 # Test that VPP responds with ARP requests to addresses that
1979 # are connected and local routes.
1980 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001981 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001982 # address added to an interface
1983 #
1984 self.pg0.generate_remote_hosts(2)
1985
Neale Ranns097fa662018-05-01 05:17:55 -07001986 forus = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001987 self,
1988 self.pg0.remote_hosts[1].ip4,
1989 32,
1990 [
1991 VppRoutePath(
1992 "0.0.0.0",
1993 self.pg0.sw_if_index,
1994 type=FibPathType.FIB_PATH_TYPE_LOCAL,
1995 )
1996 ],
1997 )
Neale Ranns7425f922019-01-23 00:36:16 -08001998 forus.add_vpp_config()
1999
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002000 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
2001 op="who-has",
2002 hwdst=self.pg0.local_mac,
2003 hwsrc=self.pg0.remote_mac,
2004 pdst=self.pg0.remote_hosts[1].ip4,
2005 psrc=self.pg0.remote_ip4,
2006 )
Neale Ranns7425f922019-01-23 00:36:16 -08002007
2008 rx = self.send_and_expect(self.pg0, [p], self.pg0)
2009
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002010 self.verify_arp_resp(
2011 rx[0],
2012 self.pg0.local_mac,
2013 self.pg0.remote_mac,
2014 self.pg0.remote_hosts[1].ip4,
2015 self.pg0.remote_ip4,
2016 )
Neale Ranns7425f922019-01-23 00:36:16 -08002017
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002018 def test_arp_table_swap(self):
2019 #
2020 # Generate some hosts on the LAN
2021 #
2022 N_NBRS = 4
2023 self.pg1.generate_remote_hosts(N_NBRS)
2024
2025 for n in range(N_NBRS):
2026 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002027 VppIpRoute(
2028 self,
2029 "10.0.0.%d" % n,
2030 32,
2031 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
2032 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002033
2034 # resolve each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002035 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
2036 op="is-at",
2037 hwdst=self.pg1.local_mac,
2038 hwsrc="00:00:5e:00:01:09",
2039 pdst=self.pg1.local_ip4,
2040 psrc=self.pg1.remote_hosts[n].ip4,
2041 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002042
2043 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
2044
2045 self.logger.info(self.vapi.cli("sh ip neighbors"))
2046
2047 #
2048 # swap the table pg1 is in
2049 #
2050 table = VppIpTable(self, 100).add_vpp_config()
2051
2052 self.pg1.unconfig_ip4()
2053 self.pg1.set_table_ip4(100)
2054 self.pg1.config_ip4()
2055
2056 #
2057 # all neighbours are cleared
2058 #
2059 for n in range(N_NBRS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002060 self.assertFalse(
2061 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip4)
2062 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002063
2064 #
2065 # packets to all neighbours generate ARP requests
2066 #
2067 for n in range(N_NBRS):
2068 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002069 VppIpRoute(
2070 self,
2071 "10.0.0.%d" % n,
2072 32,
2073 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
2074 table_id=100,
2075 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002076
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002077 p = (
2078 Ether(src=self.pg1.remote_hosts[n].mac, dst=self.pg1.local_mac)
2079 / IP(src=self.pg1.remote_hosts[n].ip4, dst="10.0.0.%d" % n)
2080 / Raw(b"0x5" * 100)
2081 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002082 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
2083 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002084 self.verify_arp_req(
2085 rx,
2086 self.pg1.local_mac,
2087 self.pg1.local_ip4,
2088 self.pg1.remote_hosts[n].ip4,
2089 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002090
2091 self.pg1.unconfig_ip4()
2092 self.pg1.set_table_ip4(0)
2093
Neale Rannse2fe0972020-11-26 08:37:27 +00002094 def test_glean_src_select(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002095 """Multi Connecteds"""
Neale Rannse2fe0972020-11-26 08:37:27 +00002096
2097 #
2098 # configure multiple connected subnets on an interface
2099 # and ensure that ARP requests for hosts on those subnets
2100 # pick up the correct source address
2101 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002102 conn1 = VppIpInterfaceAddress(self, self.pg1, "10.0.0.1", 24).add_vpp_config()
2103 conn2 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.1", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002104
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002105 p1 = (
2106 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2107 / IP(src=self.pg1.remote_ip4, dst="10.0.0.128")
2108 / Raw(b"0x5" * 100)
2109 )
Neale Rannse2fe0972020-11-26 08:37:27 +00002110
2111 rxs = self.send_and_expect(self.pg0, [p1], self.pg1)
2112 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002113 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.0.1", "10.0.0.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002114
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002115 p2 = (
2116 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2117 / IP(src=self.pg1.remote_ip4, dst="10.0.1.128")
2118 / Raw(b"0x5" * 100)
2119 )
Neale Rannse2fe0972020-11-26 08:37:27 +00002120
2121 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2122 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002123 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002124
2125 #
2126 # add a local address in the same subnet
Matthew Smith9e5694b2023-09-26 13:08:26 +00002127 # the source addresses are equivalent.
2128 # VPP leaves the glean address being used for a prefix
2129 # in place until that address is deleted.
2130 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002131 conn3 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.2", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002132
2133 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2134 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002135 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002136
2137 #
Matthew Smith9e5694b2023-09-26 13:08:26 +00002138 # remove first address, which is currently in use
2139 # the second address should be used now
Neale Rannse2fe0972020-11-26 08:37:27 +00002140 #
Matthew Smith9e5694b2023-09-26 13:08:26 +00002141 conn2.remove_vpp_config()
2142 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2143 for rx in rxs:
2144 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002145
Matthew Smith9e5694b2023-09-26 13:08:26 +00002146 #
2147 # add first address back. Second address should continue
2148 # being used.
2149 #
2150 conn2 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.1", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002151 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2152 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002153 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002154
2155 conn1.remove_vpp_config()
2156 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2157 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002158 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002159
Neale Ranns66edaf22021-07-09 13:03:52 +00002160 # apply a connected prefix to an interface in a different table
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002161 VppIpRoute(
2162 self,
2163 "10.0.1.0",
2164 24,
2165 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
2166 table_id=1,
2167 ).add_vpp_config()
Neale Ranns66edaf22021-07-09 13:03:52 +00002168
2169 rxs = self.send_and_expect(self.pg3, [p2], self.pg1)
2170 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002171 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Ranns66edaf22021-07-09 13:03:52 +00002172
Neale Ranns39528792023-03-08 04:53:37 +00002173 # apply an attached prefix to the interface
2174 # since there's no local address in this prefix,
2175 # any other address is used
2176 p3 = (
2177 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2178 / IP(src=self.pg1.remote_ip4, dst="10.0.2.128")
2179 / Raw(b"0x5" * 100)
2180 )
2181
2182 VppIpRoute(
2183 self,
2184 "10.0.2.0",
2185 24,
2186 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
2187 ).add_vpp_config()
2188
2189 rxs = self.send_and_expect(self.pg0, [p3], self.pg1)
2190 for rx in rxs:
2191 self.verify_arp_req(
2192 rx, self.pg1.local_mac, self.pg1.local_ip4, "10.0.2.128"
2193 )
2194
Neale Rannse2fe0972020-11-26 08:37:27 +00002195 # cleanup
2196 conn3.remove_vpp_config()
2197 conn2.remove_vpp_config()
2198
Neale Rannsdcd6d622017-05-26 02:59:16 -07002199
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002200@tag_fixme_vpp_workers
Neale Ranns14260392018-09-28 05:00:57 -07002201class NeighborStatsTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002202 """ARP/ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002203
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002204 @classmethod
2205 def setUpClass(cls):
2206 super(NeighborStatsTestCase, cls).setUpClass()
2207
2208 @classmethod
2209 def tearDownClass(cls):
2210 super(NeighborStatsTestCase, cls).tearDownClass()
2211
Neale Ranns14260392018-09-28 05:00:57 -07002212 def setUp(self):
2213 super(NeighborStatsTestCase, self).setUp()
2214
2215 self.create_pg_interfaces(range(2))
2216
2217 # pg0 configured with ip4 and 6 addresses used for input
2218 # pg1 configured with ip4 and 6 addresses used for output
2219 # pg2 is unnumbered to pg0
2220 for i in self.pg_interfaces:
2221 i.admin_up()
2222 i.config_ip4()
2223 i.config_ip6()
2224 i.resolve_arp()
2225 i.resolve_ndp()
2226
2227 def tearDown(self):
2228 super(NeighborStatsTestCase, self).tearDown()
2229
2230 for i in self.pg_interfaces:
2231 i.unconfig_ip4()
2232 i.unconfig_ip6()
2233 i.admin_down()
2234
2235 def test_arp_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002236 """ARP Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002237
2238 self.vapi.cli("adj counters enable")
2239 self.pg1.generate_remote_hosts(2)
2240
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002241 arp1 = VppNeighbor(
2242 self,
2243 self.pg1.sw_if_index,
2244 self.pg1.remote_hosts[0].mac,
2245 self.pg1.remote_hosts[0].ip4,
2246 )
Neale Ranns14260392018-09-28 05:00:57 -07002247 arp1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002248 arp2 = VppNeighbor(
2249 self,
2250 self.pg1.sw_if_index,
2251 self.pg1.remote_hosts[1].mac,
2252 self.pg1.remote_hosts[1].ip4,
2253 )
Neale Ranns14260392018-09-28 05:00:57 -07002254 arp2.add_vpp_config()
2255
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002256 p1 = (
2257 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2258 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[0].ip4)
2259 / UDP(sport=1234, dport=1234)
2260 / Raw()
2261 )
2262 p2 = (
2263 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2264 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
2265 / UDP(sport=1234, dport=1234)
2266 / Raw()
2267 )
Neale Ranns14260392018-09-28 05:00:57 -07002268
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002269 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
2270 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07002271
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002272 self.assertEqual(NUM_PKTS, arp1.get_stats()["packets"])
2273 self.assertEqual(NUM_PKTS, arp2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002274
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002275 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002276 self.assertEqual(NUM_PKTS * 2, arp1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002277
2278 def test_nd_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002279 """ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002280
2281 self.vapi.cli("adj counters enable")
2282 self.pg0.generate_remote_hosts(3)
2283
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002284 nd1 = VppNeighbor(
2285 self,
2286 self.pg0.sw_if_index,
2287 self.pg0.remote_hosts[1].mac,
2288 self.pg0.remote_hosts[1].ip6,
2289 )
Neale Ranns14260392018-09-28 05:00:57 -07002290 nd1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002291 nd2 = VppNeighbor(
2292 self,
2293 self.pg0.sw_if_index,
2294 self.pg0.remote_hosts[2].mac,
2295 self.pg0.remote_hosts[2].ip6,
2296 )
Neale Ranns14260392018-09-28 05:00:57 -07002297 nd2.add_vpp_config()
2298
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002299 p1 = (
2300 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2301 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[1].ip6)
2302 / UDP(sport=1234, dport=1234)
2303 / Raw()
2304 )
2305 p2 = (
2306 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2307 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[2].ip6)
2308 / UDP(sport=1234, dport=1234)
2309 / Raw()
2310 )
Neale Ranns14260392018-09-28 05:00:57 -07002311
2312 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
2313 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
2314
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002315 self.assertEqual(16, nd1.get_stats()["packets"])
2316 self.assertEqual(16, nd2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002317
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002318 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002319 self.assertEqual(NUM_PKTS + 16, nd1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002320
2321
Dave Wallace670724c2022-09-20 21:52:18 -04002322@tag_fixme_ubuntu2204
Neale Rannscbe25aa2019-09-30 10:53:31 +00002323class NeighborAgeTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002324 """ARP/ND Aging"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002325
2326 @classmethod
2327 def setUpClass(cls):
2328 super(NeighborAgeTestCase, cls).setUpClass()
2329
2330 @classmethod
2331 def tearDownClass(cls):
2332 super(NeighborAgeTestCase, cls).tearDownClass()
2333
2334 def setUp(self):
2335 super(NeighborAgeTestCase, self).setUp()
2336
2337 self.create_pg_interfaces(range(1))
2338
2339 # pg0 configured with ip4 and 6 addresses used for input
2340 # pg1 configured with ip4 and 6 addresses used for output
2341 # pg2 is unnumbered to pg0
2342 for i in self.pg_interfaces:
2343 i.admin_up()
2344 i.config_ip4()
2345 i.config_ip6()
2346 i.resolve_arp()
2347 i.resolve_ndp()
2348
2349 def tearDown(self):
2350 super(NeighborAgeTestCase, self).tearDown()
2351
2352 for i in self.pg_interfaces:
2353 i.unconfig_ip4()
2354 i.unconfig_ip6()
2355 i.admin_down()
2356
Neale Rannscbe25aa2019-09-30 10:53:31 +00002357 def verify_arp_req(self, rx, smac, sip, dip):
2358 ether = rx[Ether]
2359 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2360 self.assertEqual(ether.src, smac)
2361
2362 arp = rx[ARP]
2363 self.assertEqual(arp.hwtype, 1)
2364 self.assertEqual(arp.ptype, 0x800)
2365 self.assertEqual(arp.hwlen, 6)
2366 self.assertEqual(arp.plen, 4)
2367 self.assertEqual(arp.op, arp_opts["who-has"])
2368 self.assertEqual(arp.hwsrc, smac)
2369 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2370 self.assertEqual(arp.psrc, sip)
2371 self.assertEqual(arp.pdst, dip)
2372
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002373 def verify_ip_neighbor_config(self, af, max_number, max_age, recycle):
2374 config = self.vapi.ip_neighbor_config_get(af)
2375
2376 self.assertEqual(config.af, af)
2377 self.assertEqual(config.max_number, max_number)
2378 self.assertEqual(config.max_age, max_age)
2379 self.assertEqual(config.recycle, recycle)
2380
Neale Rannscbe25aa2019-09-30 10:53:31 +00002381 def test_age(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002382 """Aging/Recycle"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002383
2384 self.vapi.cli("set logging unthrottle 0")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002385 self.vapi.cli("set logging size %d" % 0xFFFF)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002386
2387 self.pg0.generate_remote_hosts(201)
2388
2389 vaf = VppEnum.vl_api_address_family_t
2390
2391 #
2392 # start listening on all interfaces
2393 #
2394 self.pg_enable_capture(self.pg_interfaces)
2395
2396 #
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002397 # Verify neighbor configuration defaults
2398 #
2399 self.verify_ip_neighbor_config(
2400 af=vaf.ADDRESS_IP4, max_number=50000, max_age=0, recycle=False
2401 )
2402
2403 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002404 # Set the neighbor configuration:
2405 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002406 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00002407 # recycle = false
2408 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002409 self.vapi.ip_neighbor_config(
2410 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2411 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002412 self.verify_ip_neighbor_config(
2413 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2414 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002415
2416 self.vapi.cli("sh ip neighbor-config")
2417
2418 # add the 198 neighbours that should pass (-1 for one created in setup)
2419 for ii in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002420 VppNeighbor(
2421 self,
2422 self.pg0.sw_if_index,
2423 self.pg0.remote_hosts[ii].mac,
2424 self.pg0.remote_hosts[ii].ip4,
2425 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002426
2427 # one more neighbor over the limit should fail
2428 with self.vapi.assert_negative_api_retval():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002429 VppNeighbor(
2430 self,
2431 self.pg0.sw_if_index,
2432 self.pg0.remote_hosts[200].mac,
2433 self.pg0.remote_hosts[200].ip4,
2434 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002435
2436 #
2437 # change the config to allow recycling the old neighbors
2438 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002439 self.vapi.ip_neighbor_config(
2440 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=True
2441 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002442 self.verify_ip_neighbor_config(
2443 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=True
2444 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002445
2446 # now new additions are allowed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002447 VppNeighbor(
2448 self,
2449 self.pg0.sw_if_index,
2450 self.pg0.remote_hosts[200].mac,
2451 self.pg0.remote_hosts[200].ip4,
2452 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002453
2454 # add the first neighbor we configured has been re-used
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002455 self.assertFalse(
2456 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2457 )
2458 self.assertTrue(
2459 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[200].ip4)
2460 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002461
2462 #
2463 # change the config to age old neighbors
2464 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002465 self.vapi.ip_neighbor_config(
2466 af=vaf.ADDRESS_IP4, max_number=200, max_age=2, recycle=True
2467 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002468 self.verify_ip_neighbor_config(
2469 af=vaf.ADDRESS_IP4, max_number=200, max_age=2, recycle=True
2470 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002471
2472 self.vapi.cli("sh ip4 neighbor-sorted")
2473
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002474 # age out neighbors
2475 self.virtual_sleep(3)
2476
Neale Rannscbe25aa2019-09-30 10:53:31 +00002477 #
2478 # expect probes from all these ARP entries as they age
2479 # 3 probes for each neighbor 3*200 = 600
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002480 rxs = self.pg0.get_capture(600, timeout=2)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002481
2482 for ii in range(3):
2483 for jj in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002484 rx = rxs[ii * 200 + jj]
Neale Rannscbe25aa2019-09-30 10:53:31 +00002485 # rx.show()
2486
2487 #
2488 # 3 probes sent then 1 more second to see if a reply comes, before
2489 # they age out
2490 #
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002491 self.virtual_sleep(1)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002492
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002493 self.assertFalse(
2494 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2495 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002496
2497 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002498 # load up some neighbours again with 2s aging enabled
2499 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002500 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002501 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002502 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2503
2504 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002505 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002506 VppNeighbor(
2507 self,
2508 self.pg0.sw_if_index,
2509 self.pg0.remote_hosts[ii].mac,
2510 self.pg0.remote_hosts[ii].ip4,
2511 ).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002512
2513 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002514 self.assertEqual(e.flags, enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2515 self.assertEqual(str(e.neighbor.ip_address), self.pg0.remote_hosts[ii].ip4)
2516 self.assertEqual(e.neighbor.mac_address, self.pg0.remote_hosts[ii].mac)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002517
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002518 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002519 self.assertFalse(
2520 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2521 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002522
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002523 evs = []
2524 for ii in range(10):
2525 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002526 self.assertEqual(e.flags, enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002527 evs.append(e)
2528
2529 # check we got the correct mac/ip pairs - done separately
2530 # because we don't care about the order the remove notifications
2531 # arrive
2532 for ii in range(10):
2533 found = False
2534 mac = self.pg0.remote_hosts[ii].mac
2535 ip = self.pg0.remote_hosts[ii].ip4
2536
2537 for e in evs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002538 if e.neighbor.mac_address == mac and str(e.neighbor.ip_address) == ip:
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002539 found = True
2540 break
2541 self.assertTrue(found)
2542
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002543 #
2544 # check if we can set age and recycle with empty neighbor list
2545 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002546 self.vapi.ip_neighbor_config(
2547 af=vaf.ADDRESS_IP4, max_number=200, max_age=1000, recycle=True
2548 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002549 self.verify_ip_neighbor_config(
2550 af=vaf.ADDRESS_IP4, max_number=200, max_age=1000, recycle=True
2551 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002552
2553 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002554 # load up some neighbours again, then disable the aging
2555 # they should still be there in 10 seconds time
2556 #
2557 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002558 VppNeighbor(
2559 self,
2560 self.pg0.sw_if_index,
2561 self.pg0.remote_hosts[ii].mac,
2562 self.pg0.remote_hosts[ii].ip4,
2563 ).add_vpp_config()
2564 self.vapi.ip_neighbor_config(
2565 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2566 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002567 self.verify_ip_neighbor_config(
2568 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2569 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002570
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002571 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002572 self.assertTrue(
2573 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2574 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002575
2576
Neale Rannsc87fbb42020-04-02 17:08:28 +00002577class NeighborReplaceTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002578 """ARP/ND Replacement"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002579
2580 @classmethod
2581 def setUpClass(cls):
2582 super(NeighborReplaceTestCase, cls).setUpClass()
2583
2584 @classmethod
2585 def tearDownClass(cls):
2586 super(NeighborReplaceTestCase, cls).tearDownClass()
2587
2588 def setUp(self):
2589 super(NeighborReplaceTestCase, self).setUp()
2590
2591 self.create_pg_interfaces(range(4))
2592
2593 # pg0 configured with ip4 and 6 addresses used for input
2594 # pg1 configured with ip4 and 6 addresses used for output
2595 # pg2 is unnumbered to pg0
2596 for i in self.pg_interfaces:
2597 i.admin_up()
2598 i.config_ip4()
2599 i.config_ip6()
2600 i.resolve_arp()
2601 i.resolve_ndp()
2602
2603 def tearDown(self):
2604 super(NeighborReplaceTestCase, self).tearDown()
2605
2606 for i in self.pg_interfaces:
2607 i.unconfig_ip4()
2608 i.unconfig_ip6()
2609 i.admin_down()
2610
2611 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002612 """replace"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002613
2614 N_HOSTS = 16
2615
2616 for i in self.pg_interfaces:
2617 i.generate_remote_hosts(N_HOSTS)
2618 i.configure_ipv4_neighbors()
2619 i.configure_ipv6_neighbors()
2620
2621 # replace them all
2622 self.vapi.ip_neighbor_replace_begin()
2623 self.vapi.ip_neighbor_replace_end()
2624
2625 for i in self.pg_interfaces:
2626 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002627 self.assertFalse(
2628 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip4)
2629 )
2630 self.assertFalse(
2631 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip6)
2632 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002633
2634 #
2635 # and them all back via the API
2636 #
2637 for i in self.pg_interfaces:
2638 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002639 VppNeighbor(
2640 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip4
2641 ).add_vpp_config()
2642 VppNeighbor(
2643 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip6
2644 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002645
2646 #
2647 # begin the replacement again, this time touch some
2648 # the neighbours on pg1 so they are not deleted
2649 #
2650 self.vapi.ip_neighbor_replace_begin()
2651
2652 # update from the API all neighbours on pg1
2653 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002654 VppNeighbor(
2655 self,
2656 self.pg1.sw_if_index,
2657 self.pg1.remote_hosts[h].mac,
2658 self.pg1.remote_hosts[h].ip4,
2659 ).add_vpp_config()
2660 VppNeighbor(
2661 self,
2662 self.pg1.sw_if_index,
2663 self.pg1.remote_hosts[h].mac,
2664 self.pg1.remote_hosts[h].ip6,
2665 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002666
2667 # update from the data-plane all neighbours on pg3
2668 self.pg3.configure_ipv4_neighbors()
2669 self.pg3.configure_ipv6_neighbors()
2670
2671 # complete the replacement
2672 self.logger.info(self.vapi.cli("sh ip neighbors"))
2673 self.vapi.ip_neighbor_replace_end()
2674
2675 for i in self.pg_interfaces:
2676 if i == self.pg1 or i == self.pg3:
2677 # neighbours on pg1 and pg3 are still present
2678 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002679 self.assertTrue(
2680 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2681 )
2682 self.assertTrue(
2683 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2684 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002685 else:
2686 # all other neighbours are toast
2687 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002688 self.assertFalse(
2689 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2690 )
2691 self.assertFalse(
2692 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2693 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002694
2695
Neale Ranns240dcb22020-04-23 09:04:59 +00002696class NeighborFlush(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002697 """Neighbor Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002698
2699 @classmethod
2700 def setUpClass(cls):
2701 super(NeighborFlush, cls).setUpClass()
2702
2703 @classmethod
2704 def tearDownClass(cls):
2705 super(NeighborFlush, cls).tearDownClass()
2706
2707 def setUp(self):
2708 super(NeighborFlush, self).setUp()
2709
2710 self.create_pg_interfaces(range(2))
2711
2712 for i in self.pg_interfaces:
2713 i.admin_up()
2714 i.config_ip4()
2715 i.config_ip6()
2716 i.resolve_arp()
2717 i.resolve_ndp()
2718
2719 def tearDown(self):
2720 super(NeighborFlush, self).tearDown()
2721
2722 for i in self.pg_interfaces:
2723 i.unconfig_ip4()
2724 i.unconfig_ip6()
2725 i.admin_down()
2726
2727 def test_flush(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002728 """Neighbour Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002729
2730 e = VppEnum
2731 nf = e.vl_api_ip_neighbor_flags_t
2732 af = e.vl_api_address_family_t
2733 N_HOSTS = 16
2734 static = [False, True]
2735 self.pg0.generate_remote_hosts(N_HOSTS)
2736 self.pg1.generate_remote_hosts(N_HOSTS)
2737
2738 for s in static:
2739 # a few v4 and v6 dynamic neoghbors
2740 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002741 VppNeighbor(
2742 self,
2743 self.pg0.sw_if_index,
2744 self.pg0.remote_hosts[n].mac,
2745 self.pg0.remote_hosts[n].ip4,
2746 is_static=s,
2747 ).add_vpp_config()
2748 VppNeighbor(
2749 self,
2750 self.pg1.sw_if_index,
2751 self.pg1.remote_hosts[n].mac,
2752 self.pg1.remote_hosts[n].ip6,
2753 is_static=s,
2754 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002755
2756 # flush the interfaces individually
2757 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2758
2759 # check we haven't flushed that which we shouldn't
2760 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002761 self.assertTrue(
2762 find_nbr(
2763 self,
2764 self.pg1.sw_if_index,
2765 self.pg1.remote_hosts[n].ip6,
2766 is_static=s,
2767 )
2768 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002769
2770 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2771
2772 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002773 self.assertFalse(
2774 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2775 )
2776 self.assertFalse(
2777 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2778 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002779
2780 # add the nieghbours back
2781 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002782 VppNeighbor(
2783 self,
2784 self.pg0.sw_if_index,
2785 self.pg0.remote_hosts[n].mac,
2786 self.pg0.remote_hosts[n].ip4,
2787 is_static=s,
2788 ).add_vpp_config()
2789 VppNeighbor(
2790 self,
2791 self.pg1.sw_if_index,
2792 self.pg1.remote_hosts[n].mac,
2793 self.pg1.remote_hosts[n].ip6,
2794 is_static=s,
2795 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002796
2797 self.logger.info(self.vapi.cli("sh ip neighbor"))
2798
2799 # flush both interfaces at the same time
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002800 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002801
2802 # check we haven't flushed that which we shouldn't
2803 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002804 self.assertTrue(
2805 find_nbr(
2806 self,
2807 self.pg0.sw_if_index,
2808 self.pg0.remote_hosts[n].ip4,
2809 is_static=s,
2810 )
2811 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002812
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002813 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002814
2815 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002816 self.assertFalse(
2817 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2818 )
2819 self.assertFalse(
2820 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2821 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002822
2823
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002824if __name__ == "__main__":
Neale Ranns37be7362017-02-21 17:30:26 -08002825 unittest.main(testRunner=VppTestRunner)