blob: d11d4abac1404c9d088f0890ab1f06653b3a2ef6 [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
Pim van Pelt2a7bc812024-03-08 09:27:40 +0100435 # Allow for ARP requests from point-to-point ethernet neighbors
436 # without an attached route on pg2
437 self.pg2.add_stream(p)
438 self.pg_enable_capture(self.pg_interfaces)
439 self.pg_start()
440
441 rx = self.pg2.get_capture(1)
442 self.verify_arp_resp(
443 rx[0],
444 self.pg2.local_mac,
445 self.pg2.remote_mac,
446 self.pg1.local_ip4,
447 self.pg2.remote_hosts[3].ip4,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200448 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800449
Pim van Pelt2a7bc812024-03-08 09:27:40 +0100450 #
451 # Allow for ARP requests from neighbors on unnumbered with
452 # an attached route on pg2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200453 attached_host = VppIpRoute(
454 self,
455 self.pg2.remote_hosts[3].ip4,
456 32,
457 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
458 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800459 attached_host.add_vpp_config()
460
461 self.pg2.add_stream(p)
462 self.pg_enable_capture(self.pg_interfaces)
463 self.pg_start()
464
465 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200466 self.verify_arp_resp(
467 rx[0],
468 self.pg2.local_mac,
469 self.pg2.remote_mac,
470 self.pg1.local_ip4,
471 self.pg2.remote_hosts[3].ip4,
472 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800473
Neale Ranns30d0fd42017-05-30 07:30:04 -0700474 self.pg2.add_stream(pt)
475 self.pg_enable_capture(self.pg_interfaces)
476 self.pg_start()
477
478 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200479 self.verify_arp_resp(
480 rx[0],
481 self.pg2.local_mac,
482 self.pg2.remote_mac,
483 self.pg1.local_ip4,
484 self.pg2.remote_hosts[3].ip4,
485 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700486
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800487 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800488 # A neighbor entry that has no associated FIB-entry
489 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200490 arp_no_fib = VppNeighbor(
491 self,
492 self.pg1.sw_if_index,
493 self.pg1.remote_hosts[4].mac,
494 self.pg1.remote_hosts[4].ip4,
495 is_no_fib_entry=1,
496 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800497 arp_no_fib.add_vpp_config()
498
499 #
500 # check we have the neighbor, but no route
501 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200502 self.assertTrue(
503 find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[4].ip4)
504 )
505 self.assertFalse(find_route(self, self.pg1._remote_hosts[4].ip4, 32))
Neale Ranns3983ac22017-03-10 11:53:27 -0800506 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800507 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
508 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800509 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200510 arp_unnum = VppNeighbor(
511 self,
512 self.pg2.sw_if_index,
513 self.pg1.remote_hosts[5].mac,
514 self.pg1.remote_hosts[5].ip4,
515 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800516 arp_unnum.add_vpp_config()
517
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200518 p = (
519 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
520 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[5].ip4)
521 / UDP(sport=1234, dport=1234)
522 / Raw()
523 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800524
525 self.pg0.add_stream(p)
526 self.pg_enable_capture(self.pg_interfaces)
527 self.pg_start()
528
529 rx = self.pg2.get_capture(1)
530
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200531 self.verify_ip(
532 rx[0],
533 self.pg2.local_mac,
534 self.pg1.remote_hosts[5].mac,
535 self.pg0.remote_ip4,
536 self.pg1._remote_hosts[5].ip4,
537 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800538
539 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800540 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
541 # with the unnumbered interface's address as the source
542 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200543 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
544 op="who-has",
545 hwsrc=self.pg2.remote_mac,
546 pdst=self.pg1.local_ip4,
547 psrc=self.pg1.remote_hosts[6].ip4,
548 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800549
550 self.pg2.add_stream(p)
551 self.pg_enable_capture(self.pg_interfaces)
552 self.pg_start()
553
554 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200555 self.verify_arp_resp(
556 rx[0],
557 self.pg2.local_mac,
558 self.pg2.remote_mac,
559 self.pg1.local_ip4,
560 self.pg1.remote_hosts[6].ip4,
561 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800562
563 #
564 # An attached host route out of pg2 for an undiscovered hosts generates
565 # an ARP request with the unnumbered address as the source
566 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200567 att_unnum = VppIpRoute(
568 self,
569 self.pg1.remote_hosts[7].ip4,
570 32,
571 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
572 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800573 att_unnum.add_vpp_config()
574
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200575 p = (
576 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
577 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[7].ip4)
578 / UDP(sport=1234, dport=1234)
579 / Raw()
580 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800581
582 self.pg0.add_stream(p)
583 self.pg_enable_capture(self.pg_interfaces)
584 self.pg_start()
585
586 rx = self.pg2.get_capture(1)
587
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200588 self.verify_arp_req(
589 rx[0], self.pg2.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[7].ip4
590 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800591
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200592 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
593 op="who-has",
594 hwsrc=self.pg2.remote_mac,
595 pdst=self.pg1.local_ip4,
596 psrc=self.pg1.remote_hosts[7].ip4,
597 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800598
599 self.pg2.add_stream(p)
600 self.pg_enable_capture(self.pg_interfaces)
601 self.pg_start()
602
603 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200604 self.verify_arp_resp(
605 rx[0],
606 self.pg2.local_mac,
607 self.pg2.remote_mac,
608 self.pg1.local_ip4,
609 self.pg1.remote_hosts[7].ip4,
610 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800611
612 #
613 # An attached host route as yet unresolved out of pg2 for an
614 # undiscovered host, an ARP requests begets a response.
615 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200616 att_unnum1 = VppIpRoute(
617 self,
618 self.pg1.remote_hosts[8].ip4,
619 32,
620 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
621 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800622 att_unnum1.add_vpp_config()
623
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200624 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
625 op="who-has",
626 hwsrc=self.pg2.remote_mac,
627 pdst=self.pg1.local_ip4,
628 psrc=self.pg1.remote_hosts[8].ip4,
629 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800630
631 self.pg2.add_stream(p)
632 self.pg_enable_capture(self.pg_interfaces)
633 self.pg_start()
634
635 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200636 self.verify_arp_resp(
637 rx[0],
638 self.pg2.local_mac,
639 self.pg2.remote_mac,
640 self.pg1.local_ip4,
641 self.pg1.remote_hosts[8].ip4,
642 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800643
644 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700645 # Send an ARP request from one of the so-far unlearned remote hosts
646 # with a VLAN0 tag
647 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200648 p = (
649 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[9].mac)
650 / Dot1Q(vlan=0)
651 / ARP(
652 op="who-has",
653 hwsrc=self.pg1._remote_hosts[9].mac,
654 pdst=self.pg1.local_ip4,
655 psrc=self.pg1._remote_hosts[9].ip4,
656 )
657 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700658
659 self.pg1.add_stream(p)
660 self.pg_enable_capture(self.pg_interfaces)
661 self.pg_start()
662
663 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200664 self.verify_arp_resp(
665 rx[0],
666 self.pg1.local_mac,
667 self.pg1._remote_hosts[9].mac,
668 self.pg1.local_ip4,
669 self.pg1._remote_hosts[9].ip4,
670 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700671
672 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700673 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700674 # Should still get an ARP resp since the cover is attached
675 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200676 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) / ARP(
677 op="who-has",
678 hwsrc=self.pg1.remote_mac,
679 pdst=self.pg1.local_ip4,
680 psrc=self.pg1.remote_hosts[10].ip4,
681 )
Neale Rannsca193612017-06-14 06:50:08 -0700682
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200683 r1 = VppIpRoute(
684 self,
685 self.pg1.remote_hosts[10].ip4,
686 30,
687 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
688 )
Neale Rannsca193612017-06-14 06:50:08 -0700689 r1.add_vpp_config()
690
691 self.pg1.add_stream(p)
692 self.pg_enable_capture(self.pg_interfaces)
693 self.pg_start()
694 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200695 self.verify_arp_resp(
696 rx[0],
697 self.pg1.local_mac,
698 self.pg1.remote_mac,
699 self.pg1.local_ip4,
700 self.pg1.remote_hosts[10].ip4,
701 )
Neale Rannsca193612017-06-14 06:50:08 -0700702
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200703 r2 = VppIpRoute(
704 self,
705 self.pg1.remote_hosts[10].ip4,
706 32,
707 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
708 )
Neale Rannsca193612017-06-14 06:50:08 -0700709 r2.add_vpp_config()
710
711 self.pg1.add_stream(p)
712 self.pg_enable_capture(self.pg_interfaces)
713 self.pg_start()
714 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200715 self.verify_arp_resp(
716 rx[0],
717 self.pg1.local_mac,
718 self.pg1.remote_mac,
719 self.pg1.local_ip4,
720 self.pg1.remote_hosts[10].ip4,
721 )
Neale Rannsca193612017-06-14 06:50:08 -0700722
723 #
724 # add an ARP entry that's not on the sub-net and so whose
725 # adj-fib fails the refinement check. then send an ARP request
726 # from that source
727 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200728 a1 = VppNeighbor(
729 self, self.pg0.sw_if_index, self.pg0.remote_mac, "100.100.100.50"
730 )
Neale Rannsca193612017-06-14 06:50:08 -0700731 a1.add_vpp_config()
732
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200733 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
734 op="who-has",
735 hwsrc=self.pg0.remote_mac,
736 psrc="100.100.100.50",
737 pdst=self.pg0.remote_ip4,
738 )
739 self.send_and_assert_no_replies(self.pg0, p, "ARP req for from failed adj-fib")
Neale Rannsca193612017-06-14 06:50:08 -0700740
741 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800742 # ERROR Cases
743 # 1 - don't respond to ARP request for address not within the
744 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700745 # 1b - nor within the unnumbered subnet
746 # 1c - nor within the subnet of a different interface
747 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200748 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
749 op="who-has",
750 hwsrc=self.pg0.remote_mac,
751 pdst="10.10.10.3",
752 psrc=self.pg0.remote_ip4,
753 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800754 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200755 self.pg0, p, "ARP req for non-local destination"
756 )
757 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, "10.10.10.3"))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800758
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200759 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
760 op="who-has",
761 hwsrc=self.pg2.remote_mac,
762 pdst="10.10.10.3",
763 psrc=self.pg1.remote_hosts[7].ip4,
764 )
765 self.send_and_assert_no_replies(
766 self.pg0, p, "ARP req for non-local destination - unnum"
767 )
768
769 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
770 op="who-has",
771 hwsrc=self.pg0.remote_mac,
772 pdst=self.pg1.local_ip4,
773 psrc=self.pg1.remote_ip4,
774 )
775 self.send_and_assert_no_replies(self.pg0, p, "ARP req diff sub-net")
776 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700777
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800778 #
779 # 2 - don't respond to ARP request from an address not within the
780 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700781 # 2b - to a proxied address
782 # 2c - not within a different interface's sub-net
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200783 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
784 op="who-has",
785 hwsrc=self.pg0.remote_mac,
786 psrc="10.10.10.3",
787 pdst=self.pg0.local_ip4,
788 )
789 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
790 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
791 op="who-has",
792 hwsrc=self.pg2.remote_mac,
793 psrc="10.10.10.3",
794 pdst=self.pg0.local_ip4,
795 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800796 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200797 self.pg0, p, "ARP req for non-local source - unnum"
798 )
799 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
800 op="who-has",
801 hwsrc=self.pg0.remote_mac,
802 psrc=self.pg1.remote_ip4,
803 pdst=self.pg0.local_ip4,
804 )
805 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800806
807 #
808 # 3 - don't respond to ARP request from an address that belongs to
809 # the router
810 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200811 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
812 op="who-has",
813 hwsrc=self.pg0.remote_mac,
814 psrc=self.pg0.local_ip4,
815 pdst=self.pg0.local_ip4,
816 )
817 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800818
819 #
820 # 4 - don't respond to ARP requests that has mac source different
821 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800822 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200823 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
824 op="who-has",
825 hwsrc="00:00:00:DE:AD:BE",
826 psrc=self.pg0.remote_ip4,
827 pdst=self.pg0.local_ip4,
828 )
829 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800830
831 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800832 # 5 - don't respond to ARP requests for address within the
833 # interface's sub-net but not the interface's address
834 #
835 self.pg0.generate_remote_hosts(2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200836 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
837 op="who-has",
838 hwsrc=self.pg0.remote_mac,
839 psrc=self.pg0.remote_hosts[0].ip4,
840 pdst=self.pg0.remote_hosts[1].ip4,
841 )
842 self.send_and_assert_no_replies(
843 self.pg0, p, "ARP req for non-local destination"
844 )
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800845
846 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800847 # cleanup
848 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800849 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800850 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800851
Neale Ranns4b919a52017-03-11 05:55:21 -0800852 # need this to flush the adj-fibs
853 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
854 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700855 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800856
Alexander Chernavin8a92b682023-05-22 14:27:24 +0000857 def test_arp_after_mac_change(self):
858 """ARP (after MAC address change)"""
859
860 #
861 # Prepare a subinterface
862 #
863 subif0 = VppDot1ADSubint(self, self.pg1, 0, 300, 400)
864 subif0.admin_up()
865 subif0.config_ip4()
866
867 #
868 # Send a packet to cause ARP generation for the parent interface's remote host
869 #
870 p1 = (
871 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
872 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
873 / UDP(sport=1234, dport=1234)
874 / Raw()
875 )
876
877 self.pg0.add_stream(p1)
878 self.pg_enable_capture(self.pg_interfaces)
879 self.pg_start()
880
881 rx = self.pg1.get_capture(1)
882
883 self.verify_arp_req(
884 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
885 )
886
887 #
888 # Send a packet to cause ARP generation for the subinterface's remote host
889 #
890 p2 = (
891 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
892 / IP(src=self.pg0.remote_ip4, dst=subif0.remote_ip4)
893 / UDP(sport=1234, dport=1234)
894 / Raw()
895 )
896
897 self.pg0.add_stream(p2)
898 self.pg_enable_capture(self.pg_interfaces)
899 self.pg_start()
900
901 rx = self.pg1.get_capture(1)
902
903 self.verify_arp_req(
904 rx[0],
905 self.pg1.local_mac,
906 subif0.local_ip4,
907 subif0.remote_ip4,
908 subif0.DOT1AD_TYPE,
909 )
910
911 #
912 # Change MAC address of the parent interface
913 #
914 pg1_mac_saved = self.pg1.local_mac
915 self.pg1.set_mac(MACAddress("00:00:00:11:22:33"))
916
917 #
918 # Send a packet to cause ARP generation for the parent interface's remote host
919 # - expect new MAC address is used as the source
920 #
921 self.pg0.add_stream(p1)
922 self.pg_enable_capture(self.pg_interfaces)
923 self.pg_start()
924
925 rx = self.pg1.get_capture(1)
926
927 self.verify_arp_req(
928 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
929 )
930
931 #
932 # Send a packet to cause ARP generation for the subinterface's remote host
933 # - expect new MAC address is used as the source
934 #
935
936 self.pg0.add_stream(p2)
937 self.pg_enable_capture(self.pg_interfaces)
938 self.pg_start()
939
940 rx = self.pg1.get_capture(1)
941
942 self.verify_arp_req(
943 rx[0],
944 self.pg1.local_mac,
945 subif0.local_ip4,
946 subif0.remote_ip4,
947 subif0.DOT1AD_TYPE,
948 )
949
950 #
951 # Cleanup
952 #
953 subif0.remove_vpp_config()
954 self.pg1.set_mac(MACAddress(pg1_mac_saved))
955
Neale Ranns24b170a2017-08-15 05:33:11 -0700956 def test_proxy_mirror_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200957 """Interface Mirror Proxy ARP"""
Neale Ranns24b170a2017-08-15 05:33:11 -0700958
959 #
960 # When VPP has an interface whose address is also applied to a TAP
961 # interface on the host, then VPP's TAP interface will be unnumbered
962 # to the 'real' interface and do proxy ARP from the host.
963 # the curious aspect of this setup is that ARP requests from the host
964 # will come from the VPP's own address.
965 #
966 self.pg0.generate_remote_hosts(2)
967
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200968 arp_req_from_me = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
969 op="who-has",
970 hwsrc=self.pg2.remote_mac,
971 pdst=self.pg0.remote_hosts[1].ip4,
972 psrc=self.pg0.local_ip4,
973 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700974
975 #
976 # Configure Proxy ARP for the subnet on PG0addresses on pg0
977 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200978 self.vapi.proxy_arp_add_del(
979 proxy={
980 "table_id": 0,
981 "low": self.pg0._local_ip4_subnet,
982 "hi": self.pg0._local_ip4_bcast,
983 },
984 is_add=1,
985 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700986
987 # Make pg2 un-numbered to pg0
988 #
989 self.pg2.set_unnumbered(self.pg0.sw_if_index)
990
991 #
992 # Enable pg2 for proxy ARP
993 #
994 self.pg2.set_proxy_arp()
995
996 #
997 # Send the ARP request with an originating address that
998 # is VPP's own address
999 #
Neale Ranns240dcb22020-04-23 09:04:59 +00001000 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001001 self.verify_arp_resp(
1002 rx[0],
1003 self.pg2.local_mac,
1004 self.pg2.remote_mac,
1005 self.pg0.remote_hosts[1].ip4,
1006 self.pg0.local_ip4,
1007 )
Neale Ranns24b170a2017-08-15 05:33:11 -07001008
1009 #
1010 # validate we have not learned an ARP entry as a result of this
1011 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001012 self.assertFalse(find_nbr(self, self.pg2.sw_if_index, self.pg0.local_ip4))
Neale Ranns24b170a2017-08-15 05:33:11 -07001013
1014 #
Neale Ranns240dcb22020-04-23 09:04:59 +00001015 # setup a punt redirect so packets from the uplink go to the tap
1016 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001017 redirect = VppIpPuntRedirect(
1018 self, self.pg0.sw_if_index, self.pg2.sw_if_index, self.pg0.local_ip4
1019 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001020 redirect.add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00001021
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001022 p_tcp = (
1023 Ether(
1024 src=self.pg0.remote_mac,
1025 dst=self.pg0.local_mac,
1026 )
1027 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
1028 / TCP(sport=80, dport=80)
1029 / Raw()
1030 )
Neale Ranns240dcb22020-04-23 09:04:59 +00001031 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
1032
1033 # there's no ARP entry so this is an ARP req
1034 self.assertTrue(rx[0].haslayer(ARP))
1035
1036 # and ARP entry for VPP's pg0 address on the host interface
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001037 n1 = VppNeighbor(
1038 self,
1039 self.pg2.sw_if_index,
1040 self.pg2.remote_mac,
1041 self.pg0.local_ip4,
1042 is_no_fib_entry=True,
1043 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00001044 # now the packets shold forward
1045 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
1046 self.assertFalse(rx[0].haslayer(ARP))
1047 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
1048
1049 #
1050 # flush the neighbor cache on the uplink
1051 #
1052 af = VppEnum.vl_api_address_family_t
1053 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
1054
1055 # ensure we can still resolve the ARPs on the uplink
1056 self.pg0.resolve_arp()
1057
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001058 self.assertTrue(find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_ip4))
Neale Ranns240dcb22020-04-23 09:04:59 +00001059
1060 #
Neale Ranns24b170a2017-08-15 05:33:11 -07001061 # cleanup
1062 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001063 self.vapi.proxy_arp_add_del(
1064 proxy={
1065 "table_id": 0,
1066 "low": self.pg0._local_ip4_subnet,
1067 "hi": self.pg0._local_ip4_bcast,
1068 },
1069 is_add=0,
1070 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001071 redirect.remove_vpp_config()
Neale Ranns24b170a2017-08-15 05:33:11 -07001072
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001073 def test_proxy_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001074 """Proxy ARP"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001075
Neale Rannsd5b6aa12017-05-16 08:46:45 -07001076 self.pg1.generate_remote_hosts(2)
1077
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001078 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001079 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001080 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001081 arp_req_pg0 = Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1082 op="who-has",
1083 hwsrc=self.pg0.remote_mac,
1084 pdst="10.10.10.3",
1085 psrc=self.pg0.remote_ip4,
1086 )
1087 arp_req_pg0_tagged = (
1088 Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff")
1089 / Dot1Q(vlan=0)
1090 / ARP(
1091 op="who-has",
1092 hwsrc=self.pg0.remote_mac,
1093 pdst="10.10.10.3",
1094 psrc=self.pg0.remote_ip4,
1095 )
1096 )
1097 arp_req_pg1 = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1098 op="who-has",
1099 hwsrc=self.pg1.remote_mac,
1100 pdst="10.10.10.3",
1101 psrc=self.pg1.remote_ip4,
1102 )
1103 arp_req_pg2 = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1104 op="who-has",
1105 hwsrc=self.pg2.remote_mac,
1106 pdst="10.10.10.3",
1107 psrc=self.pg1.remote_hosts[1].ip4,
1108 )
1109 arp_req_pg3 = Ether(src=self.pg3.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1110 op="who-has",
1111 hwsrc=self.pg3.remote_mac,
1112 pdst="10.10.10.3",
1113 psrc=self.pg3.remote_ip4,
1114 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001115
1116 #
1117 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
1118 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001119 self.vapi.proxy_arp_add_del(
1120 proxy={"table_id": 0, "low": "10.10.10.2", "hi": "10.10.10.124"}, is_add=1
1121 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001122
1123 #
1124 # No responses are sent when the interfaces are not enabled for proxy
1125 # ARP
1126 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001127 self.send_and_assert_no_replies(
1128 self.pg0, arp_req_pg0, "ARP req from unconfigured interface"
1129 )
1130 self.send_and_assert_no_replies(
1131 self.pg2, arp_req_pg2, "ARP req from unconfigured interface"
1132 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001133
1134 #
1135 # Make pg2 un-numbered to pg1
1136 # still won't reply.
1137 #
1138 self.pg2.set_unnumbered(self.pg1.sw_if_index)
1139
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001140 self.send_and_assert_no_replies(
1141 self.pg2, arp_req_pg2, "ARP req from unnumbered interface"
1142 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001143
1144 #
1145 # Enable each interface to reply to proxy ARPs
1146 #
1147 for i in self.pg_interfaces:
1148 i.set_proxy_arp()
1149
1150 #
1151 # Now each of the interfaces should reply to a request to a proxied
1152 # address
1153 #
1154 self.pg0.add_stream(arp_req_pg0)
1155 self.pg_enable_capture(self.pg_interfaces)
1156 self.pg_start()
1157
1158 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001159 self.verify_arp_resp(
1160 rx[0],
1161 self.pg0.local_mac,
1162 self.pg0.remote_mac,
1163 "10.10.10.3",
1164 self.pg0.remote_ip4,
1165 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001166
Neale Ranns30d0fd42017-05-30 07:30:04 -07001167 self.pg0.add_stream(arp_req_pg0_tagged)
1168 self.pg_enable_capture(self.pg_interfaces)
1169 self.pg_start()
1170
1171 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001172 self.verify_arp_resp(
1173 rx[0],
1174 self.pg0.local_mac,
1175 self.pg0.remote_mac,
1176 "10.10.10.3",
1177 self.pg0.remote_ip4,
1178 )
Neale Ranns30d0fd42017-05-30 07:30:04 -07001179
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001180 self.pg1.add_stream(arp_req_pg1)
1181 self.pg_enable_capture(self.pg_interfaces)
1182 self.pg_start()
1183
1184 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001185 self.verify_arp_resp(
1186 rx[0],
1187 self.pg1.local_mac,
1188 self.pg1.remote_mac,
1189 "10.10.10.3",
1190 self.pg1.remote_ip4,
1191 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001192
1193 self.pg2.add_stream(arp_req_pg2)
1194 self.pg_enable_capture(self.pg_interfaces)
1195 self.pg_start()
1196
1197 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001198 self.verify_arp_resp(
1199 rx[0],
1200 self.pg2.local_mac,
1201 self.pg2.remote_mac,
1202 "10.10.10.3",
1203 self.pg1.remote_hosts[1].ip4,
1204 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001205
1206 #
1207 # A request for an address out of the configured range
1208 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001209 arp_req_pg1_hi = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1210 op="who-has",
1211 hwsrc=self.pg1.remote_mac,
1212 pdst="10.10.10.125",
1213 psrc=self.pg1.remote_ip4,
1214 )
1215 self.send_and_assert_no_replies(
1216 self.pg1, arp_req_pg1_hi, "ARP req out of range HI"
1217 )
1218 arp_req_pg1_low = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1219 op="who-has",
1220 hwsrc=self.pg1.remote_mac,
1221 pdst="10.10.10.1",
1222 psrc=self.pg1.remote_ip4,
1223 )
1224 self.send_and_assert_no_replies(
1225 self.pg1, arp_req_pg1_low, "ARP req out of range Low"
1226 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001227
1228 #
1229 # Request for an address in the proxy range but from an interface
1230 # in a different VRF
1231 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001232 self.send_and_assert_no_replies(
1233 self.pg3, arp_req_pg3, "ARP req from different VRF"
1234 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001235
1236 #
1237 # Disable Each interface for proxy ARP
1238 # - expect none to respond
1239 #
1240 for i in self.pg_interfaces:
1241 i.set_proxy_arp(0)
1242
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001243 self.send_and_assert_no_replies(self.pg0, arp_req_pg0, "ARP req from disable")
1244 self.send_and_assert_no_replies(self.pg1, arp_req_pg1, "ARP req from disable")
1245 self.send_and_assert_no_replies(self.pg2, arp_req_pg2, "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001246
1247 #
1248 # clean up on interface 2
1249 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001250 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001251
1252 def test_mpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001253 """MPLS"""
Neale Ranns37be7362017-02-21 17:30:26 -08001254
1255 #
1256 # Interface 2 does not yet have ip4 config
1257 #
1258 self.pg2.config_ip4()
1259 self.pg2.generate_remote_hosts(2)
1260
1261 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001262 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001263 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001264 ip_10_0_0_1 = VppIpRoute(
1265 self,
1266 "10.0.0.1",
1267 32,
1268 [
1269 VppRoutePath(
1270 self.pg2.remote_hosts[1].ip4, self.pg2.sw_if_index, labels=[55]
1271 )
1272 ],
1273 )
Neale Ranns37be7362017-02-21 17:30:26 -08001274 ip_10_0_0_1.add_vpp_config()
1275
1276 #
1277 # packets should generate an ARP request
1278 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001279 p = (
1280 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1281 / IP(src=self.pg0.remote_ip4, dst="10.0.0.1")
1282 / UDP(sport=1234, dport=1234)
1283 / Raw(b"\xa5" * 100)
1284 )
Neale Ranns37be7362017-02-21 17:30:26 -08001285
1286 self.pg0.add_stream(p)
1287 self.pg_enable_capture(self.pg_interfaces)
1288 self.pg_start()
1289
1290 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001291 self.verify_arp_req(
1292 rx[0], self.pg2.local_mac, self.pg2.local_ip4, self.pg2._remote_hosts[1].ip4
1293 )
Neale Ranns37be7362017-02-21 17:30:26 -08001294
1295 #
1296 # now resolve the neighbours
1297 #
1298 self.pg2.configure_ipv4_neighbors()
1299
1300 #
1301 # Now packet should be properly MPLS encapped.
1302 # This verifies that MPLS link-type adjacencies are completed
1303 # when the ARP entry resolves
1304 #
1305 self.pg0.add_stream(p)
1306 self.pg_enable_capture(self.pg_interfaces)
1307 self.pg_start()
1308
1309 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001310 self.verify_ip_o_mpls(
1311 rx[0],
1312 self.pg2.local_mac,
1313 self.pg2.remote_hosts[1].mac,
1314 55,
1315 self.pg0.remote_ip4,
1316 "10.0.0.1",
1317 )
Neale Ranns4b919a52017-03-11 05:55:21 -08001318 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001319
Matthew Smithcb9ab472017-05-16 21:35:56 -05001320 def test_arp_vrrp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001321 """ARP reply with VRRP virtual src hw addr"""
Matthew Smithcb9ab472017-05-16 21:35:56 -05001322
1323 #
1324 # IP packet destined for pg1 remote host arrives on pg0 resulting
1325 # in an ARP request for the address of the remote host on pg1
1326 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001327 p0 = (
1328 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1329 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1330 / UDP(sport=1234, dport=1234)
1331 / Raw()
1332 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001333
Neale Ranns37029302018-08-10 05:30:06 -07001334 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001335
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001336 self.verify_arp_req(
1337 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
1338 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001339
1340 #
1341 # ARP reply for address of pg1 remote host arrives on pg1 with
1342 # the hw src addr set to a value in the VRRP IPv4 range of
1343 # MAC addresses
1344 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001345 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
1346 op="is-at",
1347 hwdst=self.pg1.local_mac,
1348 hwsrc="00:00:5e:00:01:09",
1349 pdst=self.pg1.local_ip4,
1350 psrc=self.pg1.remote_ip4,
1351 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001352
Neale Ranns37029302018-08-10 05:30:06 -07001353 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001354
1355 #
1356 # IP packet destined for pg1 remote host arrives on pg0 again.
1357 # VPP should have an ARP entry for that address now and the packet
1358 # should be sent out pg1.
1359 #
Neale Ranns37029302018-08-10 05:30:06 -07001360 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001361
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001362 self.verify_ip(
1363 rx1[0],
1364 self.pg1.local_mac,
1365 "00:00:5e:00:01:09",
1366 self.pg0.remote_ip4,
1367 self.pg1.remote_ip4,
1368 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001369
1370 self.pg1.admin_down()
1371 self.pg1.admin_up()
1372
Neale Rannsdcd6d622017-05-26 02:59:16 -07001373 def test_arp_duplicates(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001374 """ARP Duplicates"""
Neale Rannsdcd6d622017-05-26 02:59:16 -07001375
1376 #
1377 # Generate some hosts on the LAN
1378 #
1379 self.pg1.generate_remote_hosts(3)
1380
1381 #
1382 # Add host 1 on pg1 and pg2
1383 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001384 arp_pg1 = VppNeighbor(
1385 self,
1386 self.pg1.sw_if_index,
1387 self.pg1.remote_hosts[1].mac,
1388 self.pg1.remote_hosts[1].ip4,
1389 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001390 arp_pg1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001391 arp_pg2 = VppNeighbor(
1392 self,
1393 self.pg2.sw_if_index,
1394 self.pg2.remote_mac,
1395 self.pg1.remote_hosts[1].ip4,
1396 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001397 arp_pg2.add_vpp_config()
1398
1399 #
1400 # IP packet destined for pg1 remote host arrives on pg1 again.
1401 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001402 p = (
1403 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1404 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1405 / UDP(sport=1234, dport=1234)
1406 / Raw()
1407 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001408
1409 self.pg0.add_stream(p)
1410 self.pg_enable_capture(self.pg_interfaces)
1411 self.pg_start()
1412
1413 rx1 = self.pg1.get_capture(1)
1414
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001415 self.verify_ip(
1416 rx1[0],
1417 self.pg1.local_mac,
1418 self.pg1.remote_hosts[1].mac,
1419 self.pg0.remote_ip4,
1420 self.pg1.remote_hosts[1].ip4,
1421 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001422
1423 #
1424 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001425 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001426 #
1427 arp_pg1.remove_vpp_config()
1428
1429 self.pg0.add_stream(p)
1430 self.pg_enable_capture(self.pg_interfaces)
1431 self.pg_start()
1432
1433 rx1 = self.pg1.get_capture(1)
1434
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001435 self.verify_arp_req(
1436 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_hosts[1].ip4
1437 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001438
1439 #
1440 # Add it back
1441 #
1442 arp_pg1.add_vpp_config()
1443
1444 self.pg0.add_stream(p)
1445 self.pg_enable_capture(self.pg_interfaces)
1446 self.pg_start()
1447
1448 rx1 = self.pg1.get_capture(1)
1449
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001450 self.verify_ip(
1451 rx1[0],
1452 self.pg1.local_mac,
1453 self.pg1.remote_hosts[1].mac,
1454 self.pg0.remote_ip4,
1455 self.pg1.remote_hosts[1].ip4,
1456 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001457
Neale Ranns15002542017-09-10 04:39:11 -07001458 def test_arp_static(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001459 """ARP Static"""
Neale Ranns15002542017-09-10 04:39:11 -07001460 self.pg2.generate_remote_hosts(3)
1461
1462 #
1463 # Add a static ARP entry
1464 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001465 static_arp = VppNeighbor(
1466 self,
1467 self.pg2.sw_if_index,
1468 self.pg2.remote_hosts[1].mac,
1469 self.pg2.remote_hosts[1].ip4,
1470 is_static=1,
1471 )
Neale Ranns15002542017-09-10 04:39:11 -07001472 static_arp.add_vpp_config()
1473
1474 #
1475 # Add the connected prefix to the interface
1476 #
1477 self.pg2.config_ip4()
1478
1479 #
1480 # We should now find the adj-fib
1481 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001482 self.assertTrue(
1483 find_nbr(
1484 self, self.pg2.sw_if_index, self.pg2.remote_hosts[1].ip4, is_static=1
1485 )
1486 )
1487 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32))
Neale Ranns15002542017-09-10 04:39:11 -07001488
1489 #
1490 # remove the connected
1491 #
1492 self.pg2.unconfig_ip4()
1493
1494 #
1495 # put the interface into table 1
1496 #
1497 self.pg2.set_table_ip4(1)
1498
1499 #
1500 # configure the same connected and expect to find the
1501 # adj fib in the new table
1502 #
1503 self.pg2.config_ip4()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001504 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32, table_id=1))
Neale Ranns15002542017-09-10 04:39:11 -07001505
1506 #
1507 # clean-up
1508 #
1509 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001510 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001511 self.pg2.set_table_ip4(0)
1512
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001513 def test_arp_static_replace_dynamic_same_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001514 """ARP Static can replace Dynamic (same mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001515 self.pg2.generate_remote_hosts(1)
1516
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001517 dyn_arp = VppNeighbor(
1518 self,
1519 self.pg2.sw_if_index,
1520 self.pg2.remote_hosts[0].mac,
1521 self.pg2.remote_hosts[0].ip4,
1522 )
1523 static_arp = VppNeighbor(
1524 self,
1525 self.pg2.sw_if_index,
1526 self.pg2.remote_hosts[0].mac,
1527 self.pg2.remote_hosts[0].ip4,
1528 is_static=1,
1529 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001530
1531 #
1532 # Add a dynamic ARP entry
1533 #
1534 dyn_arp.add_vpp_config()
1535
1536 #
1537 # We should find the dynamic nbr
1538 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001539 self.assertFalse(
1540 find_nbr(
1541 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1542 )
1543 )
1544 self.assertTrue(
1545 find_nbr(
1546 self,
1547 self.pg2.sw_if_index,
1548 self.pg2.remote_hosts[0].ip4,
1549 is_static=0,
1550 mac=self.pg2.remote_hosts[0].mac,
1551 )
1552 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001553
1554 #
1555 # Add a static ARP entry with the same mac
1556 #
1557 static_arp.add_vpp_config()
1558
1559 #
1560 # We should now find the static nbr with the same mac
1561 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001562 self.assertFalse(
1563 find_nbr(
1564 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1565 )
1566 )
1567 self.assertTrue(
1568 find_nbr(
1569 self,
1570 self.pg2.sw_if_index,
1571 self.pg2.remote_hosts[0].ip4,
1572 is_static=1,
1573 mac=self.pg2.remote_hosts[0].mac,
1574 )
1575 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001576
1577 #
1578 # clean-up
1579 #
1580 static_arp.remove_vpp_config()
1581
1582 def test_arp_static_replace_dynamic_diff_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001583 """ARP Static can replace Dynamic (diff mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001584 self.pg2.generate_remote_hosts(2)
1585
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001586 dyn_arp = VppNeighbor(
1587 self,
1588 self.pg2.sw_if_index,
1589 self.pg2.remote_hosts[0].mac,
1590 self.pg2.remote_hosts[0].ip4,
1591 )
1592 static_arp = VppNeighbor(
1593 self,
1594 self.pg2.sw_if_index,
1595 self.pg2.remote_hosts[1].mac,
1596 self.pg2.remote_hosts[0].ip4,
1597 is_static=1,
1598 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001599
1600 #
1601 # Add a dynamic ARP entry
1602 #
1603 dyn_arp.add_vpp_config()
1604
1605 #
1606 # We should find the dynamic nbr
1607 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001608 self.assertFalse(
1609 find_nbr(
1610 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1611 )
1612 )
1613 self.assertTrue(
1614 find_nbr(
1615 self,
1616 self.pg2.sw_if_index,
1617 self.pg2.remote_hosts[0].ip4,
1618 is_static=0,
1619 mac=self.pg2.remote_hosts[0].mac,
1620 )
1621 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001622
1623 #
1624 # Add a static ARP entry with a changed mac
1625 #
1626 static_arp.add_vpp_config()
1627
1628 #
1629 # We should now find the static nbr with a changed mac
1630 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001631 self.assertFalse(
1632 find_nbr(
1633 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1634 )
1635 )
1636 self.assertTrue(
1637 find_nbr(
1638 self,
1639 self.pg2.sw_if_index,
1640 self.pg2.remote_hosts[0].ip4,
1641 is_static=1,
1642 mac=self.pg2.remote_hosts[1].mac,
1643 )
1644 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001645
1646 #
1647 # clean-up
1648 #
1649 static_arp.remove_vpp_config()
1650
Neale Rannsc819fc62018-02-16 02:44:05 -08001651 def test_arp_incomplete(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001652 """ARP Incomplete"""
Neale Rannsea8adf72021-08-13 08:10:59 +00001653 self.pg1.generate_remote_hosts(4)
Neale Rannsc819fc62018-02-16 02:44:05 -08001654
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001655 p0 = (
1656 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1657 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1658 / UDP(sport=1234, dport=1234)
1659 / Raw()
1660 )
1661 p1 = (
1662 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1663 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
1664 / UDP(sport=1234, dport=1234)
1665 / Raw()
1666 )
1667 p2 = (
1668 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1669 / IP(src=self.pg0.remote_ip4, dst="1.1.1.1")
1670 / UDP(sport=1234, dport=1234)
1671 / Raw()
1672 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001673
1674 #
1675 # a packet to an unresolved destination generates an ARP request
1676 #
1677 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001678 self.verify_arp_req(
1679 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
1680 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001681
1682 #
1683 # add a neighbour for remote host 1
1684 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001685 static_arp = VppNeighbor(
1686 self,
1687 self.pg1.sw_if_index,
1688 self.pg1.remote_hosts[1].mac,
1689 self.pg1.remote_hosts[1].ip4,
1690 is_static=1,
1691 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001692 static_arp.add_vpp_config()
1693
1694 #
Neale Rannsea8adf72021-08-13 08:10:59 +00001695 # add a route through remote host 3 hence we get an incomplete
1696 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001697 VppIpRoute(
1698 self,
1699 "1.1.1.1",
1700 32,
1701 [VppRoutePath(self.pg1.remote_hosts[3].ip4, self.pg1.sw_if_index)],
1702 ).add_vpp_config()
Neale Rannsea8adf72021-08-13 08:10:59 +00001703 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001704 self.verify_arp_req(
1705 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[3].ip4
1706 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001707
1708 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001709 # change the interface's MAC
1710 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001711 self.vapi.sw_interface_set_mac_address(
1712 self.pg1.sw_if_index, "00:00:00:33:33:33"
1713 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001714
1715 #
1716 # now ARP requests come from the new source mac
1717 #
1718 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001719 self.verify_arp_req(
1720 rx[0],
1721 "00:00:00:33:33:33",
1722 self.pg1.local_ip4,
1723 self.pg1._remote_hosts[2].ip4,
1724 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001725 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001726 self.verify_arp_req(
1727 rx[0],
1728 "00:00:00:33:33:33",
1729 self.pg1.local_ip4,
1730 self.pg1._remote_hosts[3].ip4,
1731 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001732
1733 #
1734 # packets to the resolved host also have the new source mac
1735 #
1736 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001737 self.verify_ip(
1738 rx[0],
1739 "00:00:00:33:33:33",
1740 self.pg1.remote_hosts[1].mac,
1741 self.pg0.remote_ip4,
1742 self.pg1.remote_hosts[1].ip4,
1743 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001744
1745 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001746 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001747 # configured subnet and thus no glean
1748 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001749 self.vapi.sw_interface_set_mac_address(
1750 self.pg2.sw_if_index, "00:00:00:33:33:33"
1751 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001752
Neale Ranns59ae61e2018-06-07 18:09:49 -07001753 def test_garp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001754 """GARP"""
Neale Ranns59ae61e2018-06-07 18:09:49 -07001755
1756 #
1757 # Generate some hosts on the LAN
1758 #
1759 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001760 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001761
1762 #
1763 # And an ARP entry
1764 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001765 arp = VppNeighbor(
1766 self,
1767 self.pg1.sw_if_index,
1768 self.pg1.remote_hosts[1].mac,
1769 self.pg1.remote_hosts[1].ip4,
1770 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001771 arp.add_vpp_config()
1772
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001773 self.assertTrue(
1774 find_nbr(
1775 self,
1776 self.pg1.sw_if_index,
1777 self.pg1.remote_hosts[1].ip4,
1778 mac=self.pg1.remote_hosts[1].mac,
1779 )
1780 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001781
1782 #
1783 # Send a GARP (request) to swap the host 1's address to that of host 2
1784 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001785 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[2].mac) / ARP(
1786 op="who-has",
1787 hwdst=self.pg1.local_mac,
1788 hwsrc=self.pg1.remote_hosts[2].mac,
1789 pdst=self.pg1.remote_hosts[1].ip4,
1790 psrc=self.pg1.remote_hosts[1].ip4,
1791 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001792
1793 self.pg1.add_stream(p1)
1794 self.pg_enable_capture(self.pg_interfaces)
1795 self.pg_start()
1796
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001797 self.assertTrue(
1798 find_nbr(
1799 self,
1800 self.pg1.sw_if_index,
1801 self.pg1.remote_hosts[1].ip4,
1802 mac=self.pg1.remote_hosts[2].mac,
1803 )
1804 )
Neale Rannsfd2417b2021-07-16 14:00:16 +00001805 self.assert_equal(self.get_arp_rx_garp(self.pg1), 1)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001806
1807 #
1808 # Send a GARP (reply) to swap the host 1's address to that of host 3
1809 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001810 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1811 op="is-at",
1812 hwdst=self.pg1.local_mac,
1813 hwsrc=self.pg1.remote_hosts[3].mac,
1814 pdst=self.pg1.remote_hosts[1].ip4,
1815 psrc=self.pg1.remote_hosts[1].ip4,
1816 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001817
1818 self.pg1.add_stream(p1)
1819 self.pg_enable_capture(self.pg_interfaces)
1820 self.pg_start()
1821
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001822 self.assertTrue(
1823 find_nbr(
1824 self,
1825 self.pg1.sw_if_index,
1826 self.pg1.remote_hosts[1].ip4,
1827 mac=self.pg1.remote_hosts[3].mac,
1828 )
1829 )
Neale Rannsfd2417b2021-07-16 14:00:16 +00001830 self.assert_equal(self.get_arp_rx_garp(self.pg1), 2)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001831
1832 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001833 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001834 # don't result in new neighbour entries
1835 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001836 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1837 op="who-has",
1838 hwdst=self.pg1.local_mac,
1839 hwsrc=self.pg1.remote_hosts[3].mac,
1840 pdst=self.pg1.remote_hosts[2].ip4,
1841 psrc=self.pg1.remote_hosts[2].ip4,
1842 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001843
1844 self.pg1.add_stream(p1)
1845 self.pg_enable_capture(self.pg_interfaces)
1846 self.pg_start()
1847
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001848 self.assertFalse(
1849 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1850 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001851
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001852 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1853 op="is-at",
1854 hwdst=self.pg1.local_mac,
1855 hwsrc=self.pg1.remote_hosts[3].mac,
1856 pdst=self.pg1.remote_hosts[2].ip4,
1857 psrc=self.pg1.remote_hosts[2].ip4,
1858 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001859
1860 self.pg1.add_stream(p1)
1861 self.pg_enable_capture(self.pg_interfaces)
1862 self.pg_start()
1863
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001864 self.assertFalse(
1865 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1866 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001867
Neale Ranns22eefd72020-09-23 11:25:21 +00001868 #
1869 # IP address in different subnets are not learnt
1870 #
1871 self.pg2.configure_ipv4_neighbors()
1872
Benoît Ganne114b1542022-09-12 17:56:16 +02001873 cntr = self.statistics.get_err_counter(
1874 "/err/arp-reply/l3_dst_address_not_local"
1875 )
1876
Neale Ranns22eefd72020-09-23 11:25:21 +00001877 for op in ["is-at", "who-has"]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001878 p1 = [
1879 (
1880 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1881 / ARP(
1882 op=op,
1883 hwdst=self.pg2.local_mac,
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 (
1890 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1891 / ARP(
1892 op=op,
1893 hwdst="ff:ff:ff:ff:ff:ff",
1894 hwsrc=self.pg2.remote_hosts[1].mac,
1895 pdst=self.pg2.remote_hosts[1].ip4,
1896 psrc=self.pg2.remote_hosts[1].ip4,
1897 )
1898 ),
1899 ]
Neale Ranns22eefd72020-09-23 11:25:21 +00001900
1901 self.send_and_assert_no_replies(self.pg1, p1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001902 self.assertFalse(
1903 find_nbr(self, self.pg1.sw_if_index, self.pg2.remote_hosts[1].ip4)
1904 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001905
1906 # they are all dropped because the subnet's don't match
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001907 self.assertEqual(
Benoît Ganne114b1542022-09-12 17:56:16 +02001908 cntr + 4,
Neale Ranns13a74ae2022-08-09 00:59:37 +00001909 self.statistics.get_err_counter("/err/arp-reply/l3_dst_address_not_local"),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001910 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001911
Neale Ranns77f91622020-11-23 16:25:27 +00001912 def test_arp_incomplete2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001913 """Incomplete Entries"""
Neale Rannsc8352bc2018-08-29 10:23:58 -07001914
1915 #
Neale Rannscd35e532018-08-31 02:51:45 -07001916 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001917 #
1918 self.pg0.generate_remote_hosts(2)
1919
Neale Rannscd35e532018-08-31 02:51:45 -07001920 #
1921 # IPv4/ARP
1922 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001923 ip_10_0_0_1 = VppIpRoute(
1924 self,
1925 "10.0.0.1",
1926 32,
1927 [VppRoutePath(self.pg0.remote_hosts[1].ip4, self.pg0.sw_if_index)],
1928 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001929 ip_10_0_0_1.add_vpp_config()
1930
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001931 p1 = (
1932 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1933 / IP(src=self.pg1.remote_ip4, dst="10.0.0.1")
1934 / UDP(sport=1234, dport=1234)
1935 / Raw()
1936 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001937
1938 self.pg1.add_stream(p1 * 257)
1939 self.pg_enable_capture(self.pg_interfaces)
1940 self.pg_start()
1941 rx = self.pg0._get_capture(1)
1942
1943 #
1944 # how many we get is going to be dependent on the time for packet
1945 # processing but it should be small
1946 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001947 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001948
Neale Rannscd35e532018-08-31 02:51:45 -07001949 #
1950 # IPv6/ND
1951 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001952 ip_10_1 = VppIpRoute(
1953 self,
1954 "10::1",
1955 128,
1956 [
1957 VppRoutePath(
1958 self.pg0.remote_hosts[1].ip6,
1959 self.pg0.sw_if_index,
1960 proto=DpoProto.DPO_PROTO_IP6,
1961 )
1962 ],
1963 )
Neale Rannscd35e532018-08-31 02:51:45 -07001964 ip_10_1.add_vpp_config()
1965
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001966 p1 = (
1967 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1968 / IPv6(src=self.pg1.remote_ip6, dst="10::1")
1969 / UDP(sport=1234, dport=1234)
1970 / Raw()
1971 )
Neale Rannscd35e532018-08-31 02:51:45 -07001972
1973 self.pg1.add_stream(p1 * 257)
1974 self.pg_enable_capture(self.pg_interfaces)
1975 self.pg_start()
1976 rx = self.pg0._get_capture(1)
1977
1978 #
1979 # how many we get is going to be dependent on the time for packet
1980 # processing but it should be small
1981 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001982 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001983
Neale Ranns7425f922019-01-23 00:36:16 -08001984 def test_arp_forus(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001985 """ARP for for-us"""
Neale Ranns7425f922019-01-23 00:36:16 -08001986
1987 #
1988 # Test that VPP responds with ARP requests to addresses that
1989 # are connected and local routes.
1990 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001991 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001992 # address added to an interface
1993 #
1994 self.pg0.generate_remote_hosts(2)
1995
Neale Ranns097fa662018-05-01 05:17:55 -07001996 forus = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001997 self,
1998 self.pg0.remote_hosts[1].ip4,
1999 32,
2000 [
2001 VppRoutePath(
2002 "0.0.0.0",
2003 self.pg0.sw_if_index,
2004 type=FibPathType.FIB_PATH_TYPE_LOCAL,
2005 )
2006 ],
2007 )
Neale Ranns7425f922019-01-23 00:36:16 -08002008 forus.add_vpp_config()
2009
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002010 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
2011 op="who-has",
2012 hwdst=self.pg0.local_mac,
2013 hwsrc=self.pg0.remote_mac,
2014 pdst=self.pg0.remote_hosts[1].ip4,
2015 psrc=self.pg0.remote_ip4,
2016 )
Neale Ranns7425f922019-01-23 00:36:16 -08002017
2018 rx = self.send_and_expect(self.pg0, [p], self.pg0)
2019
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002020 self.verify_arp_resp(
2021 rx[0],
2022 self.pg0.local_mac,
2023 self.pg0.remote_mac,
2024 self.pg0.remote_hosts[1].ip4,
2025 self.pg0.remote_ip4,
2026 )
Neale Ranns7425f922019-01-23 00:36:16 -08002027
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002028 def test_arp_table_swap(self):
2029 #
2030 # Generate some hosts on the LAN
2031 #
2032 N_NBRS = 4
2033 self.pg1.generate_remote_hosts(N_NBRS)
2034
2035 for n in range(N_NBRS):
2036 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002037 VppIpRoute(
2038 self,
2039 "10.0.0.%d" % n,
2040 32,
2041 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
2042 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002043
2044 # resolve each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002045 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
2046 op="is-at",
2047 hwdst=self.pg1.local_mac,
2048 hwsrc="00:00:5e:00:01:09",
2049 pdst=self.pg1.local_ip4,
2050 psrc=self.pg1.remote_hosts[n].ip4,
2051 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002052
2053 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
2054
2055 self.logger.info(self.vapi.cli("sh ip neighbors"))
2056
2057 #
2058 # swap the table pg1 is in
2059 #
2060 table = VppIpTable(self, 100).add_vpp_config()
2061
2062 self.pg1.unconfig_ip4()
2063 self.pg1.set_table_ip4(100)
2064 self.pg1.config_ip4()
2065
2066 #
2067 # all neighbours are cleared
2068 #
2069 for n in range(N_NBRS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002070 self.assertFalse(
2071 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip4)
2072 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002073
2074 #
2075 # packets to all neighbours generate ARP requests
2076 #
2077 for n in range(N_NBRS):
2078 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002079 VppIpRoute(
2080 self,
2081 "10.0.0.%d" % n,
2082 32,
2083 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
2084 table_id=100,
2085 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002086
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002087 p = (
2088 Ether(src=self.pg1.remote_hosts[n].mac, dst=self.pg1.local_mac)
2089 / IP(src=self.pg1.remote_hosts[n].ip4, dst="10.0.0.%d" % n)
2090 / Raw(b"0x5" * 100)
2091 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002092 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
2093 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002094 self.verify_arp_req(
2095 rx,
2096 self.pg1.local_mac,
2097 self.pg1.local_ip4,
2098 self.pg1.remote_hosts[n].ip4,
2099 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002100
2101 self.pg1.unconfig_ip4()
2102 self.pg1.set_table_ip4(0)
2103
Neale Rannse2fe0972020-11-26 08:37:27 +00002104 def test_glean_src_select(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002105 """Multi Connecteds"""
Neale Rannse2fe0972020-11-26 08:37:27 +00002106
2107 #
2108 # configure multiple connected subnets on an interface
2109 # and ensure that ARP requests for hosts on those subnets
2110 # pick up the correct source address
2111 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002112 conn1 = VppIpInterfaceAddress(self, self.pg1, "10.0.0.1", 24).add_vpp_config()
2113 conn2 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.1", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002114
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002115 p1 = (
2116 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2117 / IP(src=self.pg1.remote_ip4, dst="10.0.0.128")
2118 / Raw(b"0x5" * 100)
2119 )
Neale Rannse2fe0972020-11-26 08:37:27 +00002120
2121 rxs = self.send_and_expect(self.pg0, [p1], 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.0.1", "10.0.0.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002124
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002125 p2 = (
2126 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2127 / IP(src=self.pg1.remote_ip4, dst="10.0.1.128")
2128 / Raw(b"0x5" * 100)
2129 )
Neale Rannse2fe0972020-11-26 08:37:27 +00002130
2131 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2132 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002133 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002134
2135 #
2136 # add a local address in the same subnet
Matthew Smith9e5694b2023-09-26 13:08:26 +00002137 # the source addresses are equivalent.
2138 # VPP leaves the glean address being used for a prefix
2139 # in place until that address is deleted.
2140 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002141 conn3 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.2", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002142
2143 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2144 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002145 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002146
2147 #
Matthew Smith9e5694b2023-09-26 13:08:26 +00002148 # remove first address, which is currently in use
2149 # the second address should be used now
Neale Rannse2fe0972020-11-26 08:37:27 +00002150 #
Matthew Smith9e5694b2023-09-26 13:08:26 +00002151 conn2.remove_vpp_config()
2152 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2153 for rx in rxs:
2154 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002155
Matthew Smith9e5694b2023-09-26 13:08:26 +00002156 #
2157 # add first address back. Second address should continue
2158 # being used.
2159 #
2160 conn2 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.1", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002161 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2162 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002163 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002164
2165 conn1.remove_vpp_config()
2166 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2167 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002168 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002169
Neale Ranns66edaf22021-07-09 13:03:52 +00002170 # apply a connected prefix to an interface in a different table
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002171 VppIpRoute(
2172 self,
2173 "10.0.1.0",
2174 24,
2175 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
2176 table_id=1,
2177 ).add_vpp_config()
Neale Ranns66edaf22021-07-09 13:03:52 +00002178
Steven Luonge4238aa2024-04-19 09:49:20 -07002179 p2.dst = self.pg3.local_mac
Neale Ranns66edaf22021-07-09 13:03:52 +00002180 rxs = self.send_and_expect(self.pg3, [p2], self.pg1)
2181 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002182 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Ranns66edaf22021-07-09 13:03:52 +00002183
Neale Ranns39528792023-03-08 04:53:37 +00002184 # apply an attached prefix to the interface
2185 # since there's no local address in this prefix,
2186 # any other address is used
2187 p3 = (
2188 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2189 / IP(src=self.pg1.remote_ip4, dst="10.0.2.128")
2190 / Raw(b"0x5" * 100)
2191 )
2192
2193 VppIpRoute(
2194 self,
2195 "10.0.2.0",
2196 24,
2197 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
2198 ).add_vpp_config()
2199
2200 rxs = self.send_and_expect(self.pg0, [p3], self.pg1)
2201 for rx in rxs:
2202 self.verify_arp_req(
2203 rx, self.pg1.local_mac, self.pg1.local_ip4, "10.0.2.128"
2204 )
2205
Neale Rannse2fe0972020-11-26 08:37:27 +00002206 # cleanup
2207 conn3.remove_vpp_config()
2208 conn2.remove_vpp_config()
2209
Neale Rannsdcd6d622017-05-26 02:59:16 -07002210
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002211@tag_fixme_vpp_workers
Neale Ranns14260392018-09-28 05:00:57 -07002212class NeighborStatsTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002213 """ARP/ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002214
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002215 @classmethod
2216 def setUpClass(cls):
2217 super(NeighborStatsTestCase, cls).setUpClass()
2218
2219 @classmethod
2220 def tearDownClass(cls):
2221 super(NeighborStatsTestCase, cls).tearDownClass()
2222
Neale Ranns14260392018-09-28 05:00:57 -07002223 def setUp(self):
2224 super(NeighborStatsTestCase, self).setUp()
2225
2226 self.create_pg_interfaces(range(2))
2227
2228 # pg0 configured with ip4 and 6 addresses used for input
2229 # pg1 configured with ip4 and 6 addresses used for output
2230 # pg2 is unnumbered to pg0
2231 for i in self.pg_interfaces:
2232 i.admin_up()
2233 i.config_ip4()
2234 i.config_ip6()
2235 i.resolve_arp()
2236 i.resolve_ndp()
2237
2238 def tearDown(self):
2239 super(NeighborStatsTestCase, self).tearDown()
2240
2241 for i in self.pg_interfaces:
2242 i.unconfig_ip4()
2243 i.unconfig_ip6()
2244 i.admin_down()
2245
2246 def test_arp_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002247 """ARP Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002248
2249 self.vapi.cli("adj counters enable")
2250 self.pg1.generate_remote_hosts(2)
2251
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002252 arp1 = VppNeighbor(
2253 self,
2254 self.pg1.sw_if_index,
2255 self.pg1.remote_hosts[0].mac,
2256 self.pg1.remote_hosts[0].ip4,
2257 )
Neale Ranns14260392018-09-28 05:00:57 -07002258 arp1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002259 arp2 = VppNeighbor(
2260 self,
2261 self.pg1.sw_if_index,
2262 self.pg1.remote_hosts[1].mac,
2263 self.pg1.remote_hosts[1].ip4,
2264 )
Neale Ranns14260392018-09-28 05:00:57 -07002265 arp2.add_vpp_config()
2266
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002267 p1 = (
2268 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2269 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[0].ip4)
2270 / UDP(sport=1234, dport=1234)
2271 / Raw()
2272 )
2273 p2 = (
2274 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2275 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
2276 / UDP(sport=1234, dport=1234)
2277 / Raw()
2278 )
Neale Ranns14260392018-09-28 05:00:57 -07002279
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002280 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
2281 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07002282
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002283 self.assertEqual(NUM_PKTS, arp1.get_stats()["packets"])
2284 self.assertEqual(NUM_PKTS, arp2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002285
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002286 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002287 self.assertEqual(NUM_PKTS * 2, arp1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002288
2289 def test_nd_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002290 """ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002291
2292 self.vapi.cli("adj counters enable")
2293 self.pg0.generate_remote_hosts(3)
2294
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002295 nd1 = VppNeighbor(
2296 self,
2297 self.pg0.sw_if_index,
2298 self.pg0.remote_hosts[1].mac,
2299 self.pg0.remote_hosts[1].ip6,
2300 )
Neale Ranns14260392018-09-28 05:00:57 -07002301 nd1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002302 nd2 = VppNeighbor(
2303 self,
2304 self.pg0.sw_if_index,
2305 self.pg0.remote_hosts[2].mac,
2306 self.pg0.remote_hosts[2].ip6,
2307 )
Neale Ranns14260392018-09-28 05:00:57 -07002308 nd2.add_vpp_config()
2309
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002310 p1 = (
2311 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2312 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[1].ip6)
2313 / UDP(sport=1234, dport=1234)
2314 / Raw()
2315 )
2316 p2 = (
2317 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2318 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[2].ip6)
2319 / UDP(sport=1234, dport=1234)
2320 / Raw()
2321 )
Neale Ranns14260392018-09-28 05:00:57 -07002322
2323 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
2324 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
2325
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002326 self.assertEqual(16, nd1.get_stats()["packets"])
2327 self.assertEqual(16, nd2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002328
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002329 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002330 self.assertEqual(NUM_PKTS + 16, nd1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002331
2332
Dave Wallace670724c2022-09-20 21:52:18 -04002333@tag_fixme_ubuntu2204
Neale Rannscbe25aa2019-09-30 10:53:31 +00002334class NeighborAgeTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002335 """ARP/ND Aging"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002336
2337 @classmethod
2338 def setUpClass(cls):
2339 super(NeighborAgeTestCase, cls).setUpClass()
2340
2341 @classmethod
2342 def tearDownClass(cls):
2343 super(NeighborAgeTestCase, cls).tearDownClass()
2344
2345 def setUp(self):
2346 super(NeighborAgeTestCase, self).setUp()
2347
2348 self.create_pg_interfaces(range(1))
2349
2350 # pg0 configured with ip4 and 6 addresses used for input
2351 # pg1 configured with ip4 and 6 addresses used for output
2352 # pg2 is unnumbered to pg0
2353 for i in self.pg_interfaces:
2354 i.admin_up()
2355 i.config_ip4()
2356 i.config_ip6()
2357 i.resolve_arp()
2358 i.resolve_ndp()
2359
2360 def tearDown(self):
2361 super(NeighborAgeTestCase, self).tearDown()
2362
2363 for i in self.pg_interfaces:
2364 i.unconfig_ip4()
2365 i.unconfig_ip6()
2366 i.admin_down()
2367
Neale Rannscbe25aa2019-09-30 10:53:31 +00002368 def verify_arp_req(self, rx, smac, sip, dip):
2369 ether = rx[Ether]
2370 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2371 self.assertEqual(ether.src, smac)
2372
2373 arp = rx[ARP]
2374 self.assertEqual(arp.hwtype, 1)
2375 self.assertEqual(arp.ptype, 0x800)
2376 self.assertEqual(arp.hwlen, 6)
2377 self.assertEqual(arp.plen, 4)
2378 self.assertEqual(arp.op, arp_opts["who-has"])
2379 self.assertEqual(arp.hwsrc, smac)
2380 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2381 self.assertEqual(arp.psrc, sip)
2382 self.assertEqual(arp.pdst, dip)
2383
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002384 def verify_ip_neighbor_config(self, af, max_number, max_age, recycle):
2385 config = self.vapi.ip_neighbor_config_get(af)
2386
2387 self.assertEqual(config.af, af)
2388 self.assertEqual(config.max_number, max_number)
2389 self.assertEqual(config.max_age, max_age)
2390 self.assertEqual(config.recycle, recycle)
2391
Neale Rannscbe25aa2019-09-30 10:53:31 +00002392 def test_age(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002393 """Aging/Recycle"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002394
2395 self.vapi.cli("set logging unthrottle 0")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002396 self.vapi.cli("set logging size %d" % 0xFFFF)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002397
2398 self.pg0.generate_remote_hosts(201)
2399
2400 vaf = VppEnum.vl_api_address_family_t
2401
2402 #
2403 # start listening on all interfaces
2404 #
2405 self.pg_enable_capture(self.pg_interfaces)
2406
2407 #
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002408 # Verify neighbor configuration defaults
2409 #
2410 self.verify_ip_neighbor_config(
2411 af=vaf.ADDRESS_IP4, max_number=50000, max_age=0, recycle=False
2412 )
2413
2414 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002415 # Set the neighbor configuration:
2416 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002417 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00002418 # recycle = false
2419 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002420 self.vapi.ip_neighbor_config(
2421 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2422 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002423 self.verify_ip_neighbor_config(
2424 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2425 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002426
2427 self.vapi.cli("sh ip neighbor-config")
2428
2429 # add the 198 neighbours that should pass (-1 for one created in setup)
2430 for ii in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002431 VppNeighbor(
2432 self,
2433 self.pg0.sw_if_index,
2434 self.pg0.remote_hosts[ii].mac,
2435 self.pg0.remote_hosts[ii].ip4,
2436 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002437
2438 # one more neighbor over the limit should fail
2439 with self.vapi.assert_negative_api_retval():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002440 VppNeighbor(
2441 self,
2442 self.pg0.sw_if_index,
2443 self.pg0.remote_hosts[200].mac,
2444 self.pg0.remote_hosts[200].ip4,
2445 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002446
2447 #
2448 # change the config to allow recycling the old neighbors
2449 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002450 self.vapi.ip_neighbor_config(
2451 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=True
2452 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002453 self.verify_ip_neighbor_config(
2454 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=True
2455 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002456
2457 # now new additions are allowed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002458 VppNeighbor(
2459 self,
2460 self.pg0.sw_if_index,
2461 self.pg0.remote_hosts[200].mac,
2462 self.pg0.remote_hosts[200].ip4,
2463 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002464
2465 # add the first neighbor we configured has been re-used
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002466 self.assertFalse(
2467 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2468 )
2469 self.assertTrue(
2470 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[200].ip4)
2471 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002472
2473 #
2474 # change the config to age old neighbors
2475 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002476 self.vapi.ip_neighbor_config(
2477 af=vaf.ADDRESS_IP4, max_number=200, max_age=2, recycle=True
2478 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002479 self.verify_ip_neighbor_config(
2480 af=vaf.ADDRESS_IP4, max_number=200, max_age=2, recycle=True
2481 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002482
2483 self.vapi.cli("sh ip4 neighbor-sorted")
2484
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002485 # age out neighbors
2486 self.virtual_sleep(3)
2487
Neale Rannscbe25aa2019-09-30 10:53:31 +00002488 #
2489 # expect probes from all these ARP entries as they age
2490 # 3 probes for each neighbor 3*200 = 600
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002491 rxs = self.pg0.get_capture(600, timeout=2)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002492
2493 for ii in range(3):
2494 for jj in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002495 rx = rxs[ii * 200 + jj]
Neale Rannscbe25aa2019-09-30 10:53:31 +00002496 # rx.show()
2497
2498 #
2499 # 3 probes sent then 1 more second to see if a reply comes, before
2500 # they age out
2501 #
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002502 self.virtual_sleep(1)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002503
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002504 self.assertFalse(
2505 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2506 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002507
2508 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002509 # load up some neighbours again with 2s aging enabled
2510 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002511 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002512 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002513 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2514
2515 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002516 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002517 VppNeighbor(
2518 self,
2519 self.pg0.sw_if_index,
2520 self.pg0.remote_hosts[ii].mac,
2521 self.pg0.remote_hosts[ii].ip4,
2522 ).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002523
2524 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002525 self.assertEqual(e.flags, enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2526 self.assertEqual(str(e.neighbor.ip_address), self.pg0.remote_hosts[ii].ip4)
2527 self.assertEqual(e.neighbor.mac_address, self.pg0.remote_hosts[ii].mac)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002528
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002529 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002530 self.assertFalse(
2531 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2532 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002533
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002534 evs = []
2535 for ii in range(10):
2536 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002537 self.assertEqual(e.flags, enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002538 evs.append(e)
2539
2540 # check we got the correct mac/ip pairs - done separately
2541 # because we don't care about the order the remove notifications
2542 # arrive
2543 for ii in range(10):
2544 found = False
2545 mac = self.pg0.remote_hosts[ii].mac
2546 ip = self.pg0.remote_hosts[ii].ip4
2547
2548 for e in evs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002549 if e.neighbor.mac_address == mac and str(e.neighbor.ip_address) == ip:
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002550 found = True
2551 break
2552 self.assertTrue(found)
2553
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002554 #
2555 # check if we can set age and recycle with empty neighbor list
2556 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002557 self.vapi.ip_neighbor_config(
2558 af=vaf.ADDRESS_IP4, max_number=200, max_age=1000, recycle=True
2559 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002560 self.verify_ip_neighbor_config(
2561 af=vaf.ADDRESS_IP4, max_number=200, max_age=1000, recycle=True
2562 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002563
2564 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002565 # load up some neighbours again, then disable the aging
2566 # they should still be there in 10 seconds time
2567 #
2568 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002569 VppNeighbor(
2570 self,
2571 self.pg0.sw_if_index,
2572 self.pg0.remote_hosts[ii].mac,
2573 self.pg0.remote_hosts[ii].ip4,
2574 ).add_vpp_config()
2575 self.vapi.ip_neighbor_config(
2576 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2577 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002578 self.verify_ip_neighbor_config(
2579 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2580 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002581
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002582 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002583 self.assertTrue(
2584 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2585 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002586
2587
Neale Rannsc87fbb42020-04-02 17:08:28 +00002588class NeighborReplaceTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002589 """ARP/ND Replacement"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002590
2591 @classmethod
2592 def setUpClass(cls):
2593 super(NeighborReplaceTestCase, cls).setUpClass()
2594
2595 @classmethod
2596 def tearDownClass(cls):
2597 super(NeighborReplaceTestCase, cls).tearDownClass()
2598
2599 def setUp(self):
2600 super(NeighborReplaceTestCase, self).setUp()
2601
2602 self.create_pg_interfaces(range(4))
2603
2604 # pg0 configured with ip4 and 6 addresses used for input
2605 # pg1 configured with ip4 and 6 addresses used for output
2606 # pg2 is unnumbered to pg0
2607 for i in self.pg_interfaces:
2608 i.admin_up()
2609 i.config_ip4()
2610 i.config_ip6()
2611 i.resolve_arp()
2612 i.resolve_ndp()
2613
2614 def tearDown(self):
2615 super(NeighborReplaceTestCase, self).tearDown()
2616
2617 for i in self.pg_interfaces:
2618 i.unconfig_ip4()
2619 i.unconfig_ip6()
2620 i.admin_down()
2621
2622 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002623 """replace"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002624
2625 N_HOSTS = 16
2626
2627 for i in self.pg_interfaces:
2628 i.generate_remote_hosts(N_HOSTS)
2629 i.configure_ipv4_neighbors()
2630 i.configure_ipv6_neighbors()
2631
2632 # replace them all
2633 self.vapi.ip_neighbor_replace_begin()
2634 self.vapi.ip_neighbor_replace_end()
2635
2636 for i in self.pg_interfaces:
2637 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002638 self.assertFalse(
2639 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip4)
2640 )
2641 self.assertFalse(
2642 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip6)
2643 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002644
2645 #
2646 # and them all back via the API
2647 #
2648 for i in self.pg_interfaces:
2649 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002650 VppNeighbor(
2651 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip4
2652 ).add_vpp_config()
2653 VppNeighbor(
2654 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip6
2655 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002656
2657 #
2658 # begin the replacement again, this time touch some
2659 # the neighbours on pg1 so they are not deleted
2660 #
2661 self.vapi.ip_neighbor_replace_begin()
2662
2663 # update from the API all neighbours on pg1
2664 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002665 VppNeighbor(
2666 self,
2667 self.pg1.sw_if_index,
2668 self.pg1.remote_hosts[h].mac,
2669 self.pg1.remote_hosts[h].ip4,
2670 ).add_vpp_config()
2671 VppNeighbor(
2672 self,
2673 self.pg1.sw_if_index,
2674 self.pg1.remote_hosts[h].mac,
2675 self.pg1.remote_hosts[h].ip6,
2676 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002677
2678 # update from the data-plane all neighbours on pg3
2679 self.pg3.configure_ipv4_neighbors()
2680 self.pg3.configure_ipv6_neighbors()
2681
2682 # complete the replacement
2683 self.logger.info(self.vapi.cli("sh ip neighbors"))
2684 self.vapi.ip_neighbor_replace_end()
2685
2686 for i in self.pg_interfaces:
2687 if i == self.pg1 or i == self.pg3:
2688 # neighbours on pg1 and pg3 are still present
2689 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002690 self.assertTrue(
2691 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2692 )
2693 self.assertTrue(
2694 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2695 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002696 else:
2697 # all other neighbours are toast
2698 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002699 self.assertFalse(
2700 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2701 )
2702 self.assertFalse(
2703 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2704 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002705
2706
Neale Ranns240dcb22020-04-23 09:04:59 +00002707class NeighborFlush(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002708 """Neighbor Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002709
2710 @classmethod
2711 def setUpClass(cls):
2712 super(NeighborFlush, cls).setUpClass()
2713
2714 @classmethod
2715 def tearDownClass(cls):
2716 super(NeighborFlush, cls).tearDownClass()
2717
2718 def setUp(self):
2719 super(NeighborFlush, self).setUp()
2720
2721 self.create_pg_interfaces(range(2))
2722
2723 for i in self.pg_interfaces:
2724 i.admin_up()
2725 i.config_ip4()
2726 i.config_ip6()
2727 i.resolve_arp()
2728 i.resolve_ndp()
2729
2730 def tearDown(self):
2731 super(NeighborFlush, self).tearDown()
2732
2733 for i in self.pg_interfaces:
2734 i.unconfig_ip4()
2735 i.unconfig_ip6()
2736 i.admin_down()
2737
2738 def test_flush(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002739 """Neighbour Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002740
2741 e = VppEnum
2742 nf = e.vl_api_ip_neighbor_flags_t
2743 af = e.vl_api_address_family_t
2744 N_HOSTS = 16
2745 static = [False, True]
2746 self.pg0.generate_remote_hosts(N_HOSTS)
2747 self.pg1.generate_remote_hosts(N_HOSTS)
2748
2749 for s in static:
2750 # a few v4 and v6 dynamic neoghbors
2751 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002752 VppNeighbor(
2753 self,
2754 self.pg0.sw_if_index,
2755 self.pg0.remote_hosts[n].mac,
2756 self.pg0.remote_hosts[n].ip4,
2757 is_static=s,
2758 ).add_vpp_config()
2759 VppNeighbor(
2760 self,
2761 self.pg1.sw_if_index,
2762 self.pg1.remote_hosts[n].mac,
2763 self.pg1.remote_hosts[n].ip6,
2764 is_static=s,
2765 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002766
2767 # flush the interfaces individually
2768 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2769
2770 # check we haven't flushed that which we shouldn't
2771 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002772 self.assertTrue(
2773 find_nbr(
2774 self,
2775 self.pg1.sw_if_index,
2776 self.pg1.remote_hosts[n].ip6,
2777 is_static=s,
2778 )
2779 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002780
2781 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2782
2783 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002784 self.assertFalse(
2785 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2786 )
2787 self.assertFalse(
2788 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2789 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002790
2791 # add the nieghbours back
2792 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002793 VppNeighbor(
2794 self,
2795 self.pg0.sw_if_index,
2796 self.pg0.remote_hosts[n].mac,
2797 self.pg0.remote_hosts[n].ip4,
2798 is_static=s,
2799 ).add_vpp_config()
2800 VppNeighbor(
2801 self,
2802 self.pg1.sw_if_index,
2803 self.pg1.remote_hosts[n].mac,
2804 self.pg1.remote_hosts[n].ip6,
2805 is_static=s,
2806 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002807
2808 self.logger.info(self.vapi.cli("sh ip neighbor"))
2809
2810 # flush both interfaces at the same time
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002811 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002812
2813 # check we haven't flushed that which we shouldn't
2814 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002815 self.assertTrue(
2816 find_nbr(
2817 self,
2818 self.pg0.sw_if_index,
2819 self.pg0.remote_hosts[n].ip4,
2820 is_static=s,
2821 )
2822 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002823
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002824 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002825
2826 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002827 self.assertFalse(
2828 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2829 )
2830 self.assertFalse(
2831 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2832 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002833
2834
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002835if __name__ == "__main__":
Neale Ranns37be7362017-02-21 17:30:26 -08002836 unittest.main(testRunner=VppTestRunner)