blob: 041d78245a5b3b0aa1da88cefcaadf9f12d084e3 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns39f9d8b2017-02-16 21:57:05 -08002
3import unittest
Neale Rannscbe25aa2019-09-30 10:53:31 +00004import os
Neale Ranns39f9d8b2017-02-16 21:57:05 -08005from socket import AF_INET, AF_INET6, inet_pton
6
Dave Wallace670724c2022-09-20 21:52:18 -04007from framework import tag_fixme_vpp_workers, tag_fixme_ubuntu2204, tag_fixme_debian11
Neale Ranns39f9d8b2017-02-16 21:57:05 -08008from framework import VppTestCase, VppTestRunner
9from vpp_neighbor import VppNeighbor, find_nbr
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020010from vpp_ip_route import (
11 VppIpRoute,
12 VppRoutePath,
13 find_route,
14 VppIpTable,
15 DpoProto,
16 FibPathType,
17 VppIpInterfaceAddress,
18)
Alexander Chernavin8a92b682023-05-22 14:27:24 +000019from vpp_papi import VppEnum, MACAddress
Jakub Grajciar2df2f752020-12-01 11:23:44 +010020from vpp_ip import VppIpPuntRedirect
Alexander Chernavin8a92b682023-05-22 14:27:24 +000021from vpp_sub_interface import VppDot1ADSubint
Neale Ranns39f9d8b2017-02-16 21:57:05 -080022
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070023import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080024from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070025from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000026from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070027from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080028from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070029from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080030
Paul Vinciguerra4271c972019-05-14 13:25:49 -040031
32NUM_PKTS = 67
33
Neale Ranns39f9d8b2017-02-16 21:57:05 -080034# not exported by scapy, so redefined here
35arp_opts = {"who-has": 1, "is-at": 2}
36
37
38class ARPTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020039 """ARP Test Case"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -080040
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070041 @classmethod
42 def setUpClass(cls):
43 super(ARPTestCase, cls).setUpClass()
44
45 @classmethod
46 def tearDownClass(cls):
47 super(ARPTestCase, cls).tearDownClass()
48
Neale Ranns39f9d8b2017-02-16 21:57:05 -080049 def setUp(self):
50 super(ARPTestCase, self).setUp()
51
52 # create 3 pg interfaces
53 self.create_pg_interfaces(range(4))
54
55 # pg0 configured with ip4 and 6 addresses used for input
56 # pg1 configured with ip4 and 6 addresses used for output
57 # pg2 is unnumbered to pg0
58 for i in self.pg_interfaces:
59 i.admin_up()
60
61 self.pg0.config_ip4()
62 self.pg0.config_ip6()
63 self.pg0.resolve_arp()
64
65 self.pg1.config_ip4()
66 self.pg1.config_ip6()
67
68 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070069 self.tbl = VppIpTable(self, 1)
70 self.tbl.add_vpp_config()
71
Neale Ranns39f9d8b2017-02-16 21:57:05 -080072 self.pg3.set_table_ip4(1)
73 self.pg3.config_ip4()
74
Neale Ranns4008ac92017-02-13 23:20:04 -080075 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080076 self.pg0.unconfig_ip4()
77 self.pg0.unconfig_ip6()
78
79 self.pg1.unconfig_ip4()
80 self.pg1.unconfig_ip6()
81
82 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070083 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080084
Neale Ranns4008ac92017-02-13 23:20:04 -080085 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080086 i.admin_down()
87
Neale Ranns15002542017-09-10 04:39:11 -070088 super(ARPTestCase, self).tearDown()
89
Alexander Chernavin8a92b682023-05-22 14:27:24 +000090 def verify_arp_req(self, rx, smac, sip, dip, etype=0x0806):
Neale Ranns39f9d8b2017-02-16 21:57:05 -080091 ether = rx[Ether]
92 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
93 self.assertEqual(ether.src, smac)
Alexander Chernavin8a92b682023-05-22 14:27:24 +000094 self.assertEqual(ether.type, etype)
Neale Ranns39f9d8b2017-02-16 21:57:05 -080095
96 arp = rx[ARP]
97 self.assertEqual(arp.hwtype, 1)
98 self.assertEqual(arp.ptype, 0x800)
99 self.assertEqual(arp.hwlen, 6)
100 self.assertEqual(arp.plen, 4)
101 self.assertEqual(arp.op, arp_opts["who-has"])
102 self.assertEqual(arp.hwsrc, smac)
103 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
104 self.assertEqual(arp.psrc, sip)
105 self.assertEqual(arp.pdst, dip)
106
107 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
108 ether = rx[Ether]
109 self.assertEqual(ether.dst, dmac)
110 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100111 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800112
113 arp = rx[ARP]
114 self.assertEqual(arp.hwtype, 1)
115 self.assertEqual(arp.ptype, 0x800)
116 self.assertEqual(arp.hwlen, 6)
117 self.assertEqual(arp.plen, 4)
118 self.assertEqual(arp.op, arp_opts["is-at"])
119 self.assertEqual(arp.hwsrc, smac)
120 self.assertEqual(arp.hwdst, dmac)
121 self.assertEqual(arp.psrc, sip)
122 self.assertEqual(arp.pdst, dip)
123
Matthew Smithcb9ab472017-05-16 21:35:56 -0500124 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
125 ether = rx[Ether]
126 self.assertEqual(ether.dst, dmac)
127 self.assertEqual(ether.src, smac)
128
129 arp = rx[ARP]
130 self.assertEqual(arp.hwtype, 1)
131 self.assertEqual(arp.ptype, 0x800)
132 self.assertEqual(arp.hwlen, 6)
133 self.assertEqual(arp.plen, 4)
134 self.assertEqual(arp.op, arp_opts["is-at"])
135 self.assertNotEqual(arp.hwsrc, smac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200136 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 -0500137 self.assertEqual(arp.hwdst, dmac)
138 self.assertEqual(arp.psrc, sip)
139 self.assertEqual(arp.pdst, dip)
140
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800141 def verify_ip(self, rx, smac, dmac, sip, dip):
142 ether = rx[Ether]
143 self.assertEqual(ether.dst, dmac)
144 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100145 self.assertEqual(ether.type, 0x0800)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800146
147 ip = rx[IP]
148 self.assertEqual(ip.src, sip)
149 self.assertEqual(ip.dst, dip)
150
Neale Ranns37be7362017-02-21 17:30:26 -0800151 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
152 ether = rx[Ether]
153 self.assertEqual(ether.dst, dmac)
154 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100155 self.assertEqual(ether.type, 0x8847)
Neale Ranns37be7362017-02-21 17:30:26 -0800156
157 mpls = rx[MPLS]
158 self.assertTrue(mpls.label, label)
159
160 ip = rx[IP]
161 self.assertEqual(ip.src, sip)
162 self.assertEqual(ip.dst, dip)
163
Neale Rannsfd2417b2021-07-16 14:00:16 +0000164 def get_arp_rx_requests(self, itf):
165 """Get ARP RX request stats for and interface"""
166 return self.statistics["/net/arp/rx/requests"][:, itf.sw_if_index].sum()
167
168 def get_arp_tx_requests(self, itf):
169 """Get ARP TX request stats for and interface"""
170 return self.statistics["/net/arp/tx/requests"][:, itf.sw_if_index].sum()
171
172 def get_arp_rx_replies(self, itf):
173 """Get ARP RX replies stats for and interface"""
174 return self.statistics["/net/arp/rx/replies"][:, itf.sw_if_index].sum()
175
176 def get_arp_tx_replies(self, itf):
177 """Get ARP TX replies stats for and interface"""
178 return self.statistics["/net/arp/tx/replies"][:, itf.sw_if_index].sum()
179
180 def get_arp_rx_garp(self, itf):
181 """Get ARP RX grat stats for and interface"""
182 return self.statistics["/net/arp/rx/gratuitous"][:, itf.sw_if_index].sum()
183
184 def get_arp_tx_garp(self, itf):
185 """Get ARP RX grat stats for and interface"""
186 return self.statistics["/net/arp/tx/gratuitous"][:, itf.sw_if_index].sum()
187
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800188 def test_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200189 """ARP"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800190
191 #
192 # Generate some hosts on the LAN
193 #
Neale Rannsca193612017-06-14 06:50:08 -0700194 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800195
196 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000197 # watch for:
198 # - all neighbour events
199 # - all neighbor events on pg1
200 # - neighbor events for host[1] on pg1
201 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200202 self.vapi.want_ip_neighbor_events(enable=1, pid=os.getpid())
203 self.vapi.want_ip_neighbor_events(
204 enable=1, pid=os.getpid(), sw_if_index=self.pg1.sw_if_index
205 )
206 self.vapi.want_ip_neighbor_events(
207 enable=1,
208 pid=os.getpid(),
209 sw_if_index=self.pg1.sw_if_index,
210 ip=self.pg1.remote_hosts[1].ip4,
211 )
Neale Rannscbe25aa2019-09-30 10:53:31 +0000212
213 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
214
215 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800216 # Send IP traffic to one of these unresolved hosts.
217 # expect the generation of an ARP request
218 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200219 p = (
220 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
221 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4)
222 / UDP(sport=1234, dport=1234)
223 / Raw()
224 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800225
226 self.pg0.add_stream(p)
227 self.pg_enable_capture(self.pg_interfaces)
228 self.pg_start()
229
230 rx = self.pg1.get_capture(1)
231
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200232 self.verify_arp_req(
233 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
234 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800235
Neale Rannsfd2417b2021-07-16 14:00:16 +0000236 self.logger.info(self.vapi.cli("sh ip neighbor-stats"))
237 self.logger.info(self.vapi.cli("sh ip neighbor-stats pg1"))
238 self.assert_equal(self.get_arp_tx_requests(self.pg1), 1)
239
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800240 #
241 # And a dynamic ARP entry for host 1
242 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200243 dyn_arp = VppNeighbor(
244 self,
245 self.pg1.sw_if_index,
246 self.pg1.remote_hosts[1].mac,
247 self.pg1.remote_hosts[1].ip4,
248 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800249 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000250 self.assertTrue(dyn_arp.query_vpp_config())
251
Neale Rannsdc617b82020-08-20 08:22:56 +0000252 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
253
Neale Rannscbe25aa2019-09-30 10:53:31 +0000254 # this matches all of the listnerers
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200255 es = [self.vapi.wait_for_event(1, "ip_neighbor_event") for i in range(3)]
Neale Rannscbe25aa2019-09-30 10:53:31 +0000256 for e in es:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200257 self.assertEqual(str(e.neighbor.ip_address), self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800258
259 #
260 # now we expect IP traffic forwarded
261 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200262 dyn_p = (
263 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
264 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4)
265 / UDP(sport=1234, dport=1234)
266 / Raw()
267 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800268
269 self.pg0.add_stream(dyn_p)
270 self.pg_enable_capture(self.pg_interfaces)
271 self.pg_start()
272
273 rx = self.pg1.get_capture(1)
274
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200275 self.verify_ip(
276 rx[0],
277 self.pg1.local_mac,
278 self.pg1.remote_hosts[1].mac,
279 self.pg0.remote_ip4,
280 self.pg1._remote_hosts[1].ip4,
281 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800282
283 #
284 # And a Static ARP entry for host 2
285 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200286 static_arp = VppNeighbor(
287 self,
288 self.pg1.sw_if_index,
289 self.pg1.remote_hosts[2].mac,
290 self.pg1.remote_hosts[2].ip4,
291 is_static=1,
292 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800293 static_arp.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200294 es = [self.vapi.wait_for_event(1, "ip_neighbor_event") for i in range(2)]
Neale Rannscbe25aa2019-09-30 10:53:31 +0000295 for e in es:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200296 self.assertEqual(str(e.neighbor.ip_address), self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800297
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200298 static_p = (
299 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
300 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[2].ip4)
301 / UDP(sport=1234, dport=1234)
302 / Raw()
303 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800304
305 self.pg0.add_stream(static_p)
306 self.pg_enable_capture(self.pg_interfaces)
307 self.pg_start()
308
309 rx = self.pg1.get_capture(1)
310
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200311 self.verify_ip(
312 rx[0],
313 self.pg1.local_mac,
314 self.pg1.remote_hosts[2].mac,
315 self.pg0.remote_ip4,
316 self.pg1._remote_hosts[2].ip4,
317 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800318
319 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000320 # remove all the listeners
321 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200322 self.vapi.want_ip_neighbor_events(enable=0, pid=os.getpid())
323 self.vapi.want_ip_neighbor_events(
324 enable=0, pid=os.getpid(), sw_if_index=self.pg1.sw_if_index
325 )
326 self.vapi.want_ip_neighbor_events(
327 enable=0,
328 pid=os.getpid(),
329 sw_if_index=self.pg1.sw_if_index,
330 ip=self.pg1.remote_hosts[1].ip4,
331 )
Neale Rannscbe25aa2019-09-30 10:53:31 +0000332
333 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800334 # flap the link. dynamic ARPs get flush, statics don't
335 #
336 self.pg1.admin_down()
337 self.pg1.admin_up()
338
339 self.pg0.add_stream(static_p)
340 self.pg_enable_capture(self.pg_interfaces)
341 self.pg_start()
342 rx = self.pg1.get_capture(1)
343
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200344 self.verify_ip(
345 rx[0],
346 self.pg1.local_mac,
347 self.pg1.remote_hosts[2].mac,
348 self.pg0.remote_ip4,
349 self.pg1._remote_hosts[2].ip4,
350 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800351
352 self.pg0.add_stream(dyn_p)
353 self.pg_enable_capture(self.pg_interfaces)
354 self.pg_start()
355
356 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200357 self.verify_arp_req(
358 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
359 )
Neale Rannsfd2417b2021-07-16 14:00:16 +0000360 self.assert_equal(self.get_arp_tx_requests(self.pg1), 2)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800361
Neale Rannscbe25aa2019-09-30 10:53:31 +0000362 self.assertFalse(dyn_arp.query_vpp_config())
363 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800364 #
365 # Send an ARP request from one of the so-far unlearned remote hosts
366 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200367 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[3].mac) / ARP(
368 op="who-has",
369 hwsrc=self.pg1._remote_hosts[3].mac,
370 pdst=self.pg1.local_ip4,
371 psrc=self.pg1._remote_hosts[3].ip4,
372 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800373
374 self.pg1.add_stream(p)
375 self.pg_enable_capture(self.pg_interfaces)
376 self.pg_start()
377
378 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200379 self.verify_arp_resp(
380 rx[0],
381 self.pg1.local_mac,
382 self.pg1._remote_hosts[3].mac,
383 self.pg1.local_ip4,
384 self.pg1._remote_hosts[3].ip4,
385 )
Neale Rannsfd2417b2021-07-16 14:00:16 +0000386 self.logger.info(self.vapi.cli("sh ip neighbor-stats pg1"))
387 self.assert_equal(self.get_arp_rx_requests(self.pg1), 1)
388 self.assert_equal(self.get_arp_tx_replies(self.pg1), 1)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800389
390 #
391 # VPP should have learned the mapping for the remote host
392 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200393 self.assertTrue(
394 find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[3].ip4)
395 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800396 #
397 # Fire in an ARP request before the interface becomes IP enabled
398 #
399 self.pg2.generate_remote_hosts(4)
400
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200401 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
402 op="who-has",
403 hwsrc=self.pg2.remote_mac,
404 pdst=self.pg1.local_ip4,
405 psrc=self.pg2.remote_hosts[3].ip4,
406 )
407 pt = (
408 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac)
409 / Dot1Q(vlan=0)
410 / ARP(
411 op="who-has",
412 hwsrc=self.pg2.remote_mac,
413 pdst=self.pg1.local_ip4,
414 psrc=self.pg2.remote_hosts[3].ip4,
415 )
416 )
417 self.send_and_assert_no_replies(self.pg2, p, "interface not IP enabled")
Neale Ranns4b919a52017-03-11 05:55:21 -0800418
419 #
420 # Make pg2 un-numbered to pg1
421 #
422 self.pg2.set_unnumbered(self.pg1.sw_if_index)
423
Neale Rannsac3e72c2019-10-06 01:04:26 -0700424 #
425 # test the unnumbered dump both by all interfaces and just the enabled
426 # one
427 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700428 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700429 self.assertTrue(len(unnum))
430 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
431 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
432 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
433 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700434 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
435 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
436
Neale Ranns4b919a52017-03-11 05:55:21 -0800437 #
438 # We should respond to ARP requests for the unnumbered to address
439 # once an attached route to the source is known
440 #
441 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200442 self.pg2, p, "ARP req for unnumbered address - no source"
443 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800444
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200445 attached_host = VppIpRoute(
446 self,
447 self.pg2.remote_hosts[3].ip4,
448 32,
449 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
450 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800451 attached_host.add_vpp_config()
452
453 self.pg2.add_stream(p)
454 self.pg_enable_capture(self.pg_interfaces)
455 self.pg_start()
456
457 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200458 self.verify_arp_resp(
459 rx[0],
460 self.pg2.local_mac,
461 self.pg2.remote_mac,
462 self.pg1.local_ip4,
463 self.pg2.remote_hosts[3].ip4,
464 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800465
Neale Ranns30d0fd42017-05-30 07:30:04 -0700466 self.pg2.add_stream(pt)
467 self.pg_enable_capture(self.pg_interfaces)
468 self.pg_start()
469
470 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200471 self.verify_arp_resp(
472 rx[0],
473 self.pg2.local_mac,
474 self.pg2.remote_mac,
475 self.pg1.local_ip4,
476 self.pg2.remote_hosts[3].ip4,
477 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700478
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800479 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800480 # A neighbor entry that has no associated FIB-entry
481 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200482 arp_no_fib = VppNeighbor(
483 self,
484 self.pg1.sw_if_index,
485 self.pg1.remote_hosts[4].mac,
486 self.pg1.remote_hosts[4].ip4,
487 is_no_fib_entry=1,
488 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800489 arp_no_fib.add_vpp_config()
490
491 #
492 # check we have the neighbor, but no route
493 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200494 self.assertTrue(
495 find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[4].ip4)
496 )
497 self.assertFalse(find_route(self, self.pg1._remote_hosts[4].ip4, 32))
Neale Ranns3983ac22017-03-10 11:53:27 -0800498 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800499 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
500 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800501 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200502 arp_unnum = VppNeighbor(
503 self,
504 self.pg2.sw_if_index,
505 self.pg1.remote_hosts[5].mac,
506 self.pg1.remote_hosts[5].ip4,
507 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800508 arp_unnum.add_vpp_config()
509
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200510 p = (
511 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
512 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[5].ip4)
513 / UDP(sport=1234, dport=1234)
514 / Raw()
515 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800516
517 self.pg0.add_stream(p)
518 self.pg_enable_capture(self.pg_interfaces)
519 self.pg_start()
520
521 rx = self.pg2.get_capture(1)
522
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200523 self.verify_ip(
524 rx[0],
525 self.pg2.local_mac,
526 self.pg1.remote_hosts[5].mac,
527 self.pg0.remote_ip4,
528 self.pg1._remote_hosts[5].ip4,
529 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800530
531 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800532 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
533 # with the unnumbered interface's address as the source
534 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200535 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
536 op="who-has",
537 hwsrc=self.pg2.remote_mac,
538 pdst=self.pg1.local_ip4,
539 psrc=self.pg1.remote_hosts[6].ip4,
540 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800541
542 self.pg2.add_stream(p)
543 self.pg_enable_capture(self.pg_interfaces)
544 self.pg_start()
545
546 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200547 self.verify_arp_resp(
548 rx[0],
549 self.pg2.local_mac,
550 self.pg2.remote_mac,
551 self.pg1.local_ip4,
552 self.pg1.remote_hosts[6].ip4,
553 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800554
555 #
556 # An attached host route out of pg2 for an undiscovered hosts generates
557 # an ARP request with the unnumbered address as the source
558 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200559 att_unnum = VppIpRoute(
560 self,
561 self.pg1.remote_hosts[7].ip4,
562 32,
563 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
564 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800565 att_unnum.add_vpp_config()
566
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200567 p = (
568 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
569 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[7].ip4)
570 / UDP(sport=1234, dport=1234)
571 / Raw()
572 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800573
574 self.pg0.add_stream(p)
575 self.pg_enable_capture(self.pg_interfaces)
576 self.pg_start()
577
578 rx = self.pg2.get_capture(1)
579
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200580 self.verify_arp_req(
581 rx[0], self.pg2.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[7].ip4
582 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800583
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200584 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
585 op="who-has",
586 hwsrc=self.pg2.remote_mac,
587 pdst=self.pg1.local_ip4,
588 psrc=self.pg1.remote_hosts[7].ip4,
589 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800590
591 self.pg2.add_stream(p)
592 self.pg_enable_capture(self.pg_interfaces)
593 self.pg_start()
594
595 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200596 self.verify_arp_resp(
597 rx[0],
598 self.pg2.local_mac,
599 self.pg2.remote_mac,
600 self.pg1.local_ip4,
601 self.pg1.remote_hosts[7].ip4,
602 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800603
604 #
605 # An attached host route as yet unresolved out of pg2 for an
606 # undiscovered host, an ARP requests begets a response.
607 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200608 att_unnum1 = VppIpRoute(
609 self,
610 self.pg1.remote_hosts[8].ip4,
611 32,
612 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
613 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800614 att_unnum1.add_vpp_config()
615
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200616 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
617 op="who-has",
618 hwsrc=self.pg2.remote_mac,
619 pdst=self.pg1.local_ip4,
620 psrc=self.pg1.remote_hosts[8].ip4,
621 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800622
623 self.pg2.add_stream(p)
624 self.pg_enable_capture(self.pg_interfaces)
625 self.pg_start()
626
627 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200628 self.verify_arp_resp(
629 rx[0],
630 self.pg2.local_mac,
631 self.pg2.remote_mac,
632 self.pg1.local_ip4,
633 self.pg1.remote_hosts[8].ip4,
634 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800635
636 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700637 # Send an ARP request from one of the so-far unlearned remote hosts
638 # with a VLAN0 tag
639 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200640 p = (
641 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[9].mac)
642 / Dot1Q(vlan=0)
643 / ARP(
644 op="who-has",
645 hwsrc=self.pg1._remote_hosts[9].mac,
646 pdst=self.pg1.local_ip4,
647 psrc=self.pg1._remote_hosts[9].ip4,
648 )
649 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700650
651 self.pg1.add_stream(p)
652 self.pg_enable_capture(self.pg_interfaces)
653 self.pg_start()
654
655 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200656 self.verify_arp_resp(
657 rx[0],
658 self.pg1.local_mac,
659 self.pg1._remote_hosts[9].mac,
660 self.pg1.local_ip4,
661 self.pg1._remote_hosts[9].ip4,
662 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700663
664 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700665 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700666 # Should still get an ARP resp since the cover is attached
667 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200668 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) / ARP(
669 op="who-has",
670 hwsrc=self.pg1.remote_mac,
671 pdst=self.pg1.local_ip4,
672 psrc=self.pg1.remote_hosts[10].ip4,
673 )
Neale Rannsca193612017-06-14 06:50:08 -0700674
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200675 r1 = VppIpRoute(
676 self,
677 self.pg1.remote_hosts[10].ip4,
678 30,
679 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
680 )
Neale Rannsca193612017-06-14 06:50:08 -0700681 r1.add_vpp_config()
682
683 self.pg1.add_stream(p)
684 self.pg_enable_capture(self.pg_interfaces)
685 self.pg_start()
686 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200687 self.verify_arp_resp(
688 rx[0],
689 self.pg1.local_mac,
690 self.pg1.remote_mac,
691 self.pg1.local_ip4,
692 self.pg1.remote_hosts[10].ip4,
693 )
Neale Rannsca193612017-06-14 06:50:08 -0700694
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200695 r2 = VppIpRoute(
696 self,
697 self.pg1.remote_hosts[10].ip4,
698 32,
699 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
700 )
Neale Rannsca193612017-06-14 06:50:08 -0700701 r2.add_vpp_config()
702
703 self.pg1.add_stream(p)
704 self.pg_enable_capture(self.pg_interfaces)
705 self.pg_start()
706 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200707 self.verify_arp_resp(
708 rx[0],
709 self.pg1.local_mac,
710 self.pg1.remote_mac,
711 self.pg1.local_ip4,
712 self.pg1.remote_hosts[10].ip4,
713 )
Neale Rannsca193612017-06-14 06:50:08 -0700714
715 #
716 # add an ARP entry that's not on the sub-net and so whose
717 # adj-fib fails the refinement check. then send an ARP request
718 # from that source
719 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200720 a1 = VppNeighbor(
721 self, self.pg0.sw_if_index, self.pg0.remote_mac, "100.100.100.50"
722 )
Neale Rannsca193612017-06-14 06:50:08 -0700723 a1.add_vpp_config()
724
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200725 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
726 op="who-has",
727 hwsrc=self.pg0.remote_mac,
728 psrc="100.100.100.50",
729 pdst=self.pg0.remote_ip4,
730 )
731 self.send_and_assert_no_replies(self.pg0, p, "ARP req for from failed adj-fib")
Neale Rannsca193612017-06-14 06:50:08 -0700732
733 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800734 # ERROR Cases
735 # 1 - don't respond to ARP request for address not within the
736 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700737 # 1b - nor within the unnumbered subnet
738 # 1c - nor within the subnet of a different interface
739 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200740 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
741 op="who-has",
742 hwsrc=self.pg0.remote_mac,
743 pdst="10.10.10.3",
744 psrc=self.pg0.remote_ip4,
745 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800746 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200747 self.pg0, p, "ARP req for non-local destination"
748 )
749 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, "10.10.10.3"))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800750
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200751 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
752 op="who-has",
753 hwsrc=self.pg2.remote_mac,
754 pdst="10.10.10.3",
755 psrc=self.pg1.remote_hosts[7].ip4,
756 )
757 self.send_and_assert_no_replies(
758 self.pg0, p, "ARP req for non-local destination - unnum"
759 )
760
761 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
762 op="who-has",
763 hwsrc=self.pg0.remote_mac,
764 pdst=self.pg1.local_ip4,
765 psrc=self.pg1.remote_ip4,
766 )
767 self.send_and_assert_no_replies(self.pg0, p, "ARP req diff sub-net")
768 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700769
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800770 #
771 # 2 - don't respond to ARP request from an address not within the
772 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700773 # 2b - to a proxied address
774 # 2c - not within a different interface's sub-net
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200775 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
776 op="who-has",
777 hwsrc=self.pg0.remote_mac,
778 psrc="10.10.10.3",
779 pdst=self.pg0.local_ip4,
780 )
781 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
782 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
783 op="who-has",
784 hwsrc=self.pg2.remote_mac,
785 psrc="10.10.10.3",
786 pdst=self.pg0.local_ip4,
787 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800788 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200789 self.pg0, p, "ARP req for non-local source - unnum"
790 )
791 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
792 op="who-has",
793 hwsrc=self.pg0.remote_mac,
794 psrc=self.pg1.remote_ip4,
795 pdst=self.pg0.local_ip4,
796 )
797 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800798
799 #
800 # 3 - don't respond to ARP request from an address that belongs to
801 # the router
802 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200803 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
804 op="who-has",
805 hwsrc=self.pg0.remote_mac,
806 psrc=self.pg0.local_ip4,
807 pdst=self.pg0.local_ip4,
808 )
809 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800810
811 #
812 # 4 - don't respond to ARP requests that has mac source different
813 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800814 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200815 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
816 op="who-has",
817 hwsrc="00:00:00:DE:AD:BE",
818 psrc=self.pg0.remote_ip4,
819 pdst=self.pg0.local_ip4,
820 )
821 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800822
823 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800824 # 5 - don't respond to ARP requests for address within the
825 # interface's sub-net but not the interface's address
826 #
827 self.pg0.generate_remote_hosts(2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200828 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
829 op="who-has",
830 hwsrc=self.pg0.remote_mac,
831 psrc=self.pg0.remote_hosts[0].ip4,
832 pdst=self.pg0.remote_hosts[1].ip4,
833 )
834 self.send_and_assert_no_replies(
835 self.pg0, p, "ARP req for non-local destination"
836 )
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800837
838 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800839 # cleanup
840 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800841 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800842 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800843
Neale Ranns4b919a52017-03-11 05:55:21 -0800844 # need this to flush the adj-fibs
845 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
846 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700847 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800848
Alexander Chernavin8a92b682023-05-22 14:27:24 +0000849 def test_arp_after_mac_change(self):
850 """ARP (after MAC address change)"""
851
852 #
853 # Prepare a subinterface
854 #
855 subif0 = VppDot1ADSubint(self, self.pg1, 0, 300, 400)
856 subif0.admin_up()
857 subif0.config_ip4()
858
859 #
860 # Send a packet to cause ARP generation for the parent interface's remote host
861 #
862 p1 = (
863 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
864 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
865 / UDP(sport=1234, dport=1234)
866 / Raw()
867 )
868
869 self.pg0.add_stream(p1)
870 self.pg_enable_capture(self.pg_interfaces)
871 self.pg_start()
872
873 rx = self.pg1.get_capture(1)
874
875 self.verify_arp_req(
876 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
877 )
878
879 #
880 # Send a packet to cause ARP generation for the subinterface's remote host
881 #
882 p2 = (
883 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
884 / IP(src=self.pg0.remote_ip4, dst=subif0.remote_ip4)
885 / UDP(sport=1234, dport=1234)
886 / Raw()
887 )
888
889 self.pg0.add_stream(p2)
890 self.pg_enable_capture(self.pg_interfaces)
891 self.pg_start()
892
893 rx = self.pg1.get_capture(1)
894
895 self.verify_arp_req(
896 rx[0],
897 self.pg1.local_mac,
898 subif0.local_ip4,
899 subif0.remote_ip4,
900 subif0.DOT1AD_TYPE,
901 )
902
903 #
904 # Change MAC address of the parent interface
905 #
906 pg1_mac_saved = self.pg1.local_mac
907 self.pg1.set_mac(MACAddress("00:00:00:11:22:33"))
908
909 #
910 # Send a packet to cause ARP generation for the parent interface's remote host
911 # - expect new MAC address is used as the source
912 #
913 self.pg0.add_stream(p1)
914 self.pg_enable_capture(self.pg_interfaces)
915 self.pg_start()
916
917 rx = self.pg1.get_capture(1)
918
919 self.verify_arp_req(
920 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
921 )
922
923 #
924 # Send a packet to cause ARP generation for the subinterface's remote host
925 # - expect new MAC address is used as the source
926 #
927
928 self.pg0.add_stream(p2)
929 self.pg_enable_capture(self.pg_interfaces)
930 self.pg_start()
931
932 rx = self.pg1.get_capture(1)
933
934 self.verify_arp_req(
935 rx[0],
936 self.pg1.local_mac,
937 subif0.local_ip4,
938 subif0.remote_ip4,
939 subif0.DOT1AD_TYPE,
940 )
941
942 #
943 # Cleanup
944 #
945 subif0.remove_vpp_config()
946 self.pg1.set_mac(MACAddress(pg1_mac_saved))
947
Neale Ranns24b170a2017-08-15 05:33:11 -0700948 def test_proxy_mirror_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200949 """Interface Mirror Proxy ARP"""
Neale Ranns24b170a2017-08-15 05:33:11 -0700950
951 #
952 # When VPP has an interface whose address is also applied to a TAP
953 # interface on the host, then VPP's TAP interface will be unnumbered
954 # to the 'real' interface and do proxy ARP from the host.
955 # the curious aspect of this setup is that ARP requests from the host
956 # will come from the VPP's own address.
957 #
958 self.pg0.generate_remote_hosts(2)
959
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200960 arp_req_from_me = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
961 op="who-has",
962 hwsrc=self.pg2.remote_mac,
963 pdst=self.pg0.remote_hosts[1].ip4,
964 psrc=self.pg0.local_ip4,
965 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700966
967 #
968 # Configure Proxy ARP for the subnet on PG0addresses on pg0
969 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200970 self.vapi.proxy_arp_add_del(
971 proxy={
972 "table_id": 0,
973 "low": self.pg0._local_ip4_subnet,
974 "hi": self.pg0._local_ip4_bcast,
975 },
976 is_add=1,
977 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700978
979 # Make pg2 un-numbered to pg0
980 #
981 self.pg2.set_unnumbered(self.pg0.sw_if_index)
982
983 #
984 # Enable pg2 for proxy ARP
985 #
986 self.pg2.set_proxy_arp()
987
988 #
989 # Send the ARP request with an originating address that
990 # is VPP's own address
991 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000992 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200993 self.verify_arp_resp(
994 rx[0],
995 self.pg2.local_mac,
996 self.pg2.remote_mac,
997 self.pg0.remote_hosts[1].ip4,
998 self.pg0.local_ip4,
999 )
Neale Ranns24b170a2017-08-15 05:33:11 -07001000
1001 #
1002 # validate we have not learned an ARP entry as a result of this
1003 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001004 self.assertFalse(find_nbr(self, self.pg2.sw_if_index, self.pg0.local_ip4))
Neale Ranns24b170a2017-08-15 05:33:11 -07001005
1006 #
Neale Ranns240dcb22020-04-23 09:04:59 +00001007 # setup a punt redirect so packets from the uplink go to the tap
1008 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001009 redirect = VppIpPuntRedirect(
1010 self, self.pg0.sw_if_index, self.pg2.sw_if_index, self.pg0.local_ip4
1011 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001012 redirect.add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00001013
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001014 p_tcp = (
1015 Ether(
1016 src=self.pg0.remote_mac,
1017 dst=self.pg0.local_mac,
1018 )
1019 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
1020 / TCP(sport=80, dport=80)
1021 / Raw()
1022 )
Neale Ranns240dcb22020-04-23 09:04:59 +00001023 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
1024
1025 # there's no ARP entry so this is an ARP req
1026 self.assertTrue(rx[0].haslayer(ARP))
1027
1028 # and ARP entry for VPP's pg0 address on the host interface
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001029 n1 = VppNeighbor(
1030 self,
1031 self.pg2.sw_if_index,
1032 self.pg2.remote_mac,
1033 self.pg0.local_ip4,
1034 is_no_fib_entry=True,
1035 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00001036 # now the packets shold forward
1037 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
1038 self.assertFalse(rx[0].haslayer(ARP))
1039 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
1040
1041 #
1042 # flush the neighbor cache on the uplink
1043 #
1044 af = VppEnum.vl_api_address_family_t
1045 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
1046
1047 # ensure we can still resolve the ARPs on the uplink
1048 self.pg0.resolve_arp()
1049
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001050 self.assertTrue(find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_ip4))
Neale Ranns240dcb22020-04-23 09:04:59 +00001051
1052 #
Neale Ranns24b170a2017-08-15 05:33:11 -07001053 # cleanup
1054 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001055 self.vapi.proxy_arp_add_del(
1056 proxy={
1057 "table_id": 0,
1058 "low": self.pg0._local_ip4_subnet,
1059 "hi": self.pg0._local_ip4_bcast,
1060 },
1061 is_add=0,
1062 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001063 redirect.remove_vpp_config()
Neale Ranns24b170a2017-08-15 05:33:11 -07001064
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001065 def test_proxy_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001066 """Proxy ARP"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001067
Neale Rannsd5b6aa12017-05-16 08:46:45 -07001068 self.pg1.generate_remote_hosts(2)
1069
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001070 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001071 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001072 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001073 arp_req_pg0 = Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1074 op="who-has",
1075 hwsrc=self.pg0.remote_mac,
1076 pdst="10.10.10.3",
1077 psrc=self.pg0.remote_ip4,
1078 )
1079 arp_req_pg0_tagged = (
1080 Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff")
1081 / Dot1Q(vlan=0)
1082 / ARP(
1083 op="who-has",
1084 hwsrc=self.pg0.remote_mac,
1085 pdst="10.10.10.3",
1086 psrc=self.pg0.remote_ip4,
1087 )
1088 )
1089 arp_req_pg1 = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1090 op="who-has",
1091 hwsrc=self.pg1.remote_mac,
1092 pdst="10.10.10.3",
1093 psrc=self.pg1.remote_ip4,
1094 )
1095 arp_req_pg2 = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1096 op="who-has",
1097 hwsrc=self.pg2.remote_mac,
1098 pdst="10.10.10.3",
1099 psrc=self.pg1.remote_hosts[1].ip4,
1100 )
1101 arp_req_pg3 = Ether(src=self.pg3.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1102 op="who-has",
1103 hwsrc=self.pg3.remote_mac,
1104 pdst="10.10.10.3",
1105 psrc=self.pg3.remote_ip4,
1106 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001107
1108 #
1109 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
1110 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001111 self.vapi.proxy_arp_add_del(
1112 proxy={"table_id": 0, "low": "10.10.10.2", "hi": "10.10.10.124"}, is_add=1
1113 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001114
1115 #
1116 # No responses are sent when the interfaces are not enabled for proxy
1117 # ARP
1118 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001119 self.send_and_assert_no_replies(
1120 self.pg0, arp_req_pg0, "ARP req from unconfigured interface"
1121 )
1122 self.send_and_assert_no_replies(
1123 self.pg2, arp_req_pg2, "ARP req from unconfigured interface"
1124 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001125
1126 #
1127 # Make pg2 un-numbered to pg1
1128 # still won't reply.
1129 #
1130 self.pg2.set_unnumbered(self.pg1.sw_if_index)
1131
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001132 self.send_and_assert_no_replies(
1133 self.pg2, arp_req_pg2, "ARP req from unnumbered interface"
1134 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001135
1136 #
1137 # Enable each interface to reply to proxy ARPs
1138 #
1139 for i in self.pg_interfaces:
1140 i.set_proxy_arp()
1141
1142 #
1143 # Now each of the interfaces should reply to a request to a proxied
1144 # address
1145 #
1146 self.pg0.add_stream(arp_req_pg0)
1147 self.pg_enable_capture(self.pg_interfaces)
1148 self.pg_start()
1149
1150 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001151 self.verify_arp_resp(
1152 rx[0],
1153 self.pg0.local_mac,
1154 self.pg0.remote_mac,
1155 "10.10.10.3",
1156 self.pg0.remote_ip4,
1157 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001158
Neale Ranns30d0fd42017-05-30 07:30:04 -07001159 self.pg0.add_stream(arp_req_pg0_tagged)
1160 self.pg_enable_capture(self.pg_interfaces)
1161 self.pg_start()
1162
1163 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001164 self.verify_arp_resp(
1165 rx[0],
1166 self.pg0.local_mac,
1167 self.pg0.remote_mac,
1168 "10.10.10.3",
1169 self.pg0.remote_ip4,
1170 )
Neale Ranns30d0fd42017-05-30 07:30:04 -07001171
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001172 self.pg1.add_stream(arp_req_pg1)
1173 self.pg_enable_capture(self.pg_interfaces)
1174 self.pg_start()
1175
1176 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001177 self.verify_arp_resp(
1178 rx[0],
1179 self.pg1.local_mac,
1180 self.pg1.remote_mac,
1181 "10.10.10.3",
1182 self.pg1.remote_ip4,
1183 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001184
1185 self.pg2.add_stream(arp_req_pg2)
1186 self.pg_enable_capture(self.pg_interfaces)
1187 self.pg_start()
1188
1189 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001190 self.verify_arp_resp(
1191 rx[0],
1192 self.pg2.local_mac,
1193 self.pg2.remote_mac,
1194 "10.10.10.3",
1195 self.pg1.remote_hosts[1].ip4,
1196 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001197
1198 #
1199 # A request for an address out of the configured range
1200 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001201 arp_req_pg1_hi = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1202 op="who-has",
1203 hwsrc=self.pg1.remote_mac,
1204 pdst="10.10.10.125",
1205 psrc=self.pg1.remote_ip4,
1206 )
1207 self.send_and_assert_no_replies(
1208 self.pg1, arp_req_pg1_hi, "ARP req out of range HI"
1209 )
1210 arp_req_pg1_low = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1211 op="who-has",
1212 hwsrc=self.pg1.remote_mac,
1213 pdst="10.10.10.1",
1214 psrc=self.pg1.remote_ip4,
1215 )
1216 self.send_and_assert_no_replies(
1217 self.pg1, arp_req_pg1_low, "ARP req out of range Low"
1218 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001219
1220 #
1221 # Request for an address in the proxy range but from an interface
1222 # in a different VRF
1223 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001224 self.send_and_assert_no_replies(
1225 self.pg3, arp_req_pg3, "ARP req from different VRF"
1226 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001227
1228 #
1229 # Disable Each interface for proxy ARP
1230 # - expect none to respond
1231 #
1232 for i in self.pg_interfaces:
1233 i.set_proxy_arp(0)
1234
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001235 self.send_and_assert_no_replies(self.pg0, arp_req_pg0, "ARP req from disable")
1236 self.send_and_assert_no_replies(self.pg1, arp_req_pg1, "ARP req from disable")
1237 self.send_and_assert_no_replies(self.pg2, arp_req_pg2, "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001238
1239 #
1240 # clean up on interface 2
1241 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001242 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001243
1244 def test_mpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001245 """MPLS"""
Neale Ranns37be7362017-02-21 17:30:26 -08001246
1247 #
1248 # Interface 2 does not yet have ip4 config
1249 #
1250 self.pg2.config_ip4()
1251 self.pg2.generate_remote_hosts(2)
1252
1253 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001254 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001255 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001256 ip_10_0_0_1 = VppIpRoute(
1257 self,
1258 "10.0.0.1",
1259 32,
1260 [
1261 VppRoutePath(
1262 self.pg2.remote_hosts[1].ip4, self.pg2.sw_if_index, labels=[55]
1263 )
1264 ],
1265 )
Neale Ranns37be7362017-02-21 17:30:26 -08001266 ip_10_0_0_1.add_vpp_config()
1267
1268 #
1269 # packets should generate an ARP request
1270 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001271 p = (
1272 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1273 / IP(src=self.pg0.remote_ip4, dst="10.0.0.1")
1274 / UDP(sport=1234, dport=1234)
1275 / Raw(b"\xa5" * 100)
1276 )
Neale Ranns37be7362017-02-21 17:30:26 -08001277
1278 self.pg0.add_stream(p)
1279 self.pg_enable_capture(self.pg_interfaces)
1280 self.pg_start()
1281
1282 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001283 self.verify_arp_req(
1284 rx[0], self.pg2.local_mac, self.pg2.local_ip4, self.pg2._remote_hosts[1].ip4
1285 )
Neale Ranns37be7362017-02-21 17:30:26 -08001286
1287 #
1288 # now resolve the neighbours
1289 #
1290 self.pg2.configure_ipv4_neighbors()
1291
1292 #
1293 # Now packet should be properly MPLS encapped.
1294 # This verifies that MPLS link-type adjacencies are completed
1295 # when the ARP entry resolves
1296 #
1297 self.pg0.add_stream(p)
1298 self.pg_enable_capture(self.pg_interfaces)
1299 self.pg_start()
1300
1301 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001302 self.verify_ip_o_mpls(
1303 rx[0],
1304 self.pg2.local_mac,
1305 self.pg2.remote_hosts[1].mac,
1306 55,
1307 self.pg0.remote_ip4,
1308 "10.0.0.1",
1309 )
Neale Ranns4b919a52017-03-11 05:55:21 -08001310 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001311
Matthew Smithcb9ab472017-05-16 21:35:56 -05001312 def test_arp_vrrp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001313 """ARP reply with VRRP virtual src hw addr"""
Matthew Smithcb9ab472017-05-16 21:35:56 -05001314
1315 #
1316 # IP packet destined for pg1 remote host arrives on pg0 resulting
1317 # in an ARP request for the address of the remote host on pg1
1318 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001319 p0 = (
1320 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1321 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1322 / UDP(sport=1234, dport=1234)
1323 / Raw()
1324 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001325
Neale Ranns37029302018-08-10 05:30:06 -07001326 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001327
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001328 self.verify_arp_req(
1329 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
1330 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001331
1332 #
1333 # ARP reply for address of pg1 remote host arrives on pg1 with
1334 # the hw src addr set to a value in the VRRP IPv4 range of
1335 # MAC addresses
1336 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001337 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
1338 op="is-at",
1339 hwdst=self.pg1.local_mac,
1340 hwsrc="00:00:5e:00:01:09",
1341 pdst=self.pg1.local_ip4,
1342 psrc=self.pg1.remote_ip4,
1343 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001344
Neale Ranns37029302018-08-10 05:30:06 -07001345 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001346
1347 #
1348 # IP packet destined for pg1 remote host arrives on pg0 again.
1349 # VPP should have an ARP entry for that address now and the packet
1350 # should be sent out pg1.
1351 #
Neale Ranns37029302018-08-10 05:30:06 -07001352 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001353
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001354 self.verify_ip(
1355 rx1[0],
1356 self.pg1.local_mac,
1357 "00:00:5e:00:01:09",
1358 self.pg0.remote_ip4,
1359 self.pg1.remote_ip4,
1360 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001361
1362 self.pg1.admin_down()
1363 self.pg1.admin_up()
1364
Neale Rannsdcd6d622017-05-26 02:59:16 -07001365 def test_arp_duplicates(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001366 """ARP Duplicates"""
Neale Rannsdcd6d622017-05-26 02:59:16 -07001367
1368 #
1369 # Generate some hosts on the LAN
1370 #
1371 self.pg1.generate_remote_hosts(3)
1372
1373 #
1374 # Add host 1 on pg1 and pg2
1375 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001376 arp_pg1 = VppNeighbor(
1377 self,
1378 self.pg1.sw_if_index,
1379 self.pg1.remote_hosts[1].mac,
1380 self.pg1.remote_hosts[1].ip4,
1381 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001382 arp_pg1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001383 arp_pg2 = VppNeighbor(
1384 self,
1385 self.pg2.sw_if_index,
1386 self.pg2.remote_mac,
1387 self.pg1.remote_hosts[1].ip4,
1388 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001389 arp_pg2.add_vpp_config()
1390
1391 #
1392 # IP packet destined for pg1 remote host arrives on pg1 again.
1393 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001394 p = (
1395 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1396 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1397 / UDP(sport=1234, dport=1234)
1398 / Raw()
1399 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001400
1401 self.pg0.add_stream(p)
1402 self.pg_enable_capture(self.pg_interfaces)
1403 self.pg_start()
1404
1405 rx1 = self.pg1.get_capture(1)
1406
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001407 self.verify_ip(
1408 rx1[0],
1409 self.pg1.local_mac,
1410 self.pg1.remote_hosts[1].mac,
1411 self.pg0.remote_ip4,
1412 self.pg1.remote_hosts[1].ip4,
1413 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001414
1415 #
1416 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001417 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001418 #
1419 arp_pg1.remove_vpp_config()
1420
1421 self.pg0.add_stream(p)
1422 self.pg_enable_capture(self.pg_interfaces)
1423 self.pg_start()
1424
1425 rx1 = self.pg1.get_capture(1)
1426
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001427 self.verify_arp_req(
1428 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_hosts[1].ip4
1429 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001430
1431 #
1432 # Add it back
1433 #
1434 arp_pg1.add_vpp_config()
1435
1436 self.pg0.add_stream(p)
1437 self.pg_enable_capture(self.pg_interfaces)
1438 self.pg_start()
1439
1440 rx1 = self.pg1.get_capture(1)
1441
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001442 self.verify_ip(
1443 rx1[0],
1444 self.pg1.local_mac,
1445 self.pg1.remote_hosts[1].mac,
1446 self.pg0.remote_ip4,
1447 self.pg1.remote_hosts[1].ip4,
1448 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001449
Neale Ranns15002542017-09-10 04:39:11 -07001450 def test_arp_static(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001451 """ARP Static"""
Neale Ranns15002542017-09-10 04:39:11 -07001452 self.pg2.generate_remote_hosts(3)
1453
1454 #
1455 # Add a static ARP entry
1456 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001457 static_arp = VppNeighbor(
1458 self,
1459 self.pg2.sw_if_index,
1460 self.pg2.remote_hosts[1].mac,
1461 self.pg2.remote_hosts[1].ip4,
1462 is_static=1,
1463 )
Neale Ranns15002542017-09-10 04:39:11 -07001464 static_arp.add_vpp_config()
1465
1466 #
1467 # Add the connected prefix to the interface
1468 #
1469 self.pg2.config_ip4()
1470
1471 #
1472 # We should now find the adj-fib
1473 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001474 self.assertTrue(
1475 find_nbr(
1476 self, self.pg2.sw_if_index, self.pg2.remote_hosts[1].ip4, is_static=1
1477 )
1478 )
1479 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32))
Neale Ranns15002542017-09-10 04:39:11 -07001480
1481 #
1482 # remove the connected
1483 #
1484 self.pg2.unconfig_ip4()
1485
1486 #
1487 # put the interface into table 1
1488 #
1489 self.pg2.set_table_ip4(1)
1490
1491 #
1492 # configure the same connected and expect to find the
1493 # adj fib in the new table
1494 #
1495 self.pg2.config_ip4()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001496 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32, table_id=1))
Neale Ranns15002542017-09-10 04:39:11 -07001497
1498 #
1499 # clean-up
1500 #
1501 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001502 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001503 self.pg2.set_table_ip4(0)
1504
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001505 def test_arp_static_replace_dynamic_same_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001506 """ARP Static can replace Dynamic (same mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001507 self.pg2.generate_remote_hosts(1)
1508
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001509 dyn_arp = VppNeighbor(
1510 self,
1511 self.pg2.sw_if_index,
1512 self.pg2.remote_hosts[0].mac,
1513 self.pg2.remote_hosts[0].ip4,
1514 )
1515 static_arp = VppNeighbor(
1516 self,
1517 self.pg2.sw_if_index,
1518 self.pg2.remote_hosts[0].mac,
1519 self.pg2.remote_hosts[0].ip4,
1520 is_static=1,
1521 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001522
1523 #
1524 # Add a dynamic ARP entry
1525 #
1526 dyn_arp.add_vpp_config()
1527
1528 #
1529 # We should find the dynamic nbr
1530 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001531 self.assertFalse(
1532 find_nbr(
1533 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1534 )
1535 )
1536 self.assertTrue(
1537 find_nbr(
1538 self,
1539 self.pg2.sw_if_index,
1540 self.pg2.remote_hosts[0].ip4,
1541 is_static=0,
1542 mac=self.pg2.remote_hosts[0].mac,
1543 )
1544 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001545
1546 #
1547 # Add a static ARP entry with the same mac
1548 #
1549 static_arp.add_vpp_config()
1550
1551 #
1552 # We should now find the static nbr with the same mac
1553 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001554 self.assertFalse(
1555 find_nbr(
1556 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1557 )
1558 )
1559 self.assertTrue(
1560 find_nbr(
1561 self,
1562 self.pg2.sw_if_index,
1563 self.pg2.remote_hosts[0].ip4,
1564 is_static=1,
1565 mac=self.pg2.remote_hosts[0].mac,
1566 )
1567 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001568
1569 #
1570 # clean-up
1571 #
1572 static_arp.remove_vpp_config()
1573
1574 def test_arp_static_replace_dynamic_diff_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001575 """ARP Static can replace Dynamic (diff mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001576 self.pg2.generate_remote_hosts(2)
1577
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001578 dyn_arp = VppNeighbor(
1579 self,
1580 self.pg2.sw_if_index,
1581 self.pg2.remote_hosts[0].mac,
1582 self.pg2.remote_hosts[0].ip4,
1583 )
1584 static_arp = VppNeighbor(
1585 self,
1586 self.pg2.sw_if_index,
1587 self.pg2.remote_hosts[1].mac,
1588 self.pg2.remote_hosts[0].ip4,
1589 is_static=1,
1590 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001591
1592 #
1593 # Add a dynamic ARP entry
1594 #
1595 dyn_arp.add_vpp_config()
1596
1597 #
1598 # We should find the dynamic nbr
1599 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001600 self.assertFalse(
1601 find_nbr(
1602 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1603 )
1604 )
1605 self.assertTrue(
1606 find_nbr(
1607 self,
1608 self.pg2.sw_if_index,
1609 self.pg2.remote_hosts[0].ip4,
1610 is_static=0,
1611 mac=self.pg2.remote_hosts[0].mac,
1612 )
1613 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001614
1615 #
1616 # Add a static ARP entry with a changed mac
1617 #
1618 static_arp.add_vpp_config()
1619
1620 #
1621 # We should now find the static nbr with a changed mac
1622 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001623 self.assertFalse(
1624 find_nbr(
1625 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1626 )
1627 )
1628 self.assertTrue(
1629 find_nbr(
1630 self,
1631 self.pg2.sw_if_index,
1632 self.pg2.remote_hosts[0].ip4,
1633 is_static=1,
1634 mac=self.pg2.remote_hosts[1].mac,
1635 )
1636 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001637
1638 #
1639 # clean-up
1640 #
1641 static_arp.remove_vpp_config()
1642
Neale Rannsc819fc62018-02-16 02:44:05 -08001643 def test_arp_incomplete(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001644 """ARP Incomplete"""
Neale Rannsea8adf72021-08-13 08:10:59 +00001645 self.pg1.generate_remote_hosts(4)
Neale Rannsc819fc62018-02-16 02:44:05 -08001646
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001647 p0 = (
1648 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1649 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1650 / UDP(sport=1234, dport=1234)
1651 / Raw()
1652 )
1653 p1 = (
1654 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1655 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
1656 / UDP(sport=1234, dport=1234)
1657 / Raw()
1658 )
1659 p2 = (
1660 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1661 / IP(src=self.pg0.remote_ip4, dst="1.1.1.1")
1662 / UDP(sport=1234, dport=1234)
1663 / Raw()
1664 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001665
1666 #
1667 # a packet to an unresolved destination generates an ARP request
1668 #
1669 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001670 self.verify_arp_req(
1671 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
1672 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001673
1674 #
1675 # add a neighbour for remote host 1
1676 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001677 static_arp = VppNeighbor(
1678 self,
1679 self.pg1.sw_if_index,
1680 self.pg1.remote_hosts[1].mac,
1681 self.pg1.remote_hosts[1].ip4,
1682 is_static=1,
1683 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001684 static_arp.add_vpp_config()
1685
1686 #
Neale Rannsea8adf72021-08-13 08:10:59 +00001687 # add a route through remote host 3 hence we get an incomplete
1688 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001689 VppIpRoute(
1690 self,
1691 "1.1.1.1",
1692 32,
1693 [VppRoutePath(self.pg1.remote_hosts[3].ip4, self.pg1.sw_if_index)],
1694 ).add_vpp_config()
Neale Rannsea8adf72021-08-13 08:10:59 +00001695 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001696 self.verify_arp_req(
1697 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[3].ip4
1698 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001699
1700 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001701 # change the interface's MAC
1702 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001703 self.vapi.sw_interface_set_mac_address(
1704 self.pg1.sw_if_index, "00:00:00:33:33:33"
1705 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001706
1707 #
1708 # now ARP requests come from the new source mac
1709 #
1710 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001711 self.verify_arp_req(
1712 rx[0],
1713 "00:00:00:33:33:33",
1714 self.pg1.local_ip4,
1715 self.pg1._remote_hosts[2].ip4,
1716 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001717 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001718 self.verify_arp_req(
1719 rx[0],
1720 "00:00:00:33:33:33",
1721 self.pg1.local_ip4,
1722 self.pg1._remote_hosts[3].ip4,
1723 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001724
1725 #
1726 # packets to the resolved host also have the new source mac
1727 #
1728 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001729 self.verify_ip(
1730 rx[0],
1731 "00:00:00:33:33:33",
1732 self.pg1.remote_hosts[1].mac,
1733 self.pg0.remote_ip4,
1734 self.pg1.remote_hosts[1].ip4,
1735 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001736
1737 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001738 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001739 # configured subnet and thus no glean
1740 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001741 self.vapi.sw_interface_set_mac_address(
1742 self.pg2.sw_if_index, "00:00:00:33:33:33"
1743 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001744
Neale Ranns59ae61e2018-06-07 18:09:49 -07001745 def test_garp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001746 """GARP"""
Neale Ranns59ae61e2018-06-07 18:09:49 -07001747
1748 #
1749 # Generate some hosts on the LAN
1750 #
1751 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001752 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001753
1754 #
1755 # And an ARP entry
1756 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001757 arp = VppNeighbor(
1758 self,
1759 self.pg1.sw_if_index,
1760 self.pg1.remote_hosts[1].mac,
1761 self.pg1.remote_hosts[1].ip4,
1762 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001763 arp.add_vpp_config()
1764
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001765 self.assertTrue(
1766 find_nbr(
1767 self,
1768 self.pg1.sw_if_index,
1769 self.pg1.remote_hosts[1].ip4,
1770 mac=self.pg1.remote_hosts[1].mac,
1771 )
1772 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001773
1774 #
1775 # Send a GARP (request) to swap the host 1's address to that of host 2
1776 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001777 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[2].mac) / ARP(
1778 op="who-has",
1779 hwdst=self.pg1.local_mac,
1780 hwsrc=self.pg1.remote_hosts[2].mac,
1781 pdst=self.pg1.remote_hosts[1].ip4,
1782 psrc=self.pg1.remote_hosts[1].ip4,
1783 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001784
1785 self.pg1.add_stream(p1)
1786 self.pg_enable_capture(self.pg_interfaces)
1787 self.pg_start()
1788
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001789 self.assertTrue(
1790 find_nbr(
1791 self,
1792 self.pg1.sw_if_index,
1793 self.pg1.remote_hosts[1].ip4,
1794 mac=self.pg1.remote_hosts[2].mac,
1795 )
1796 )
Neale Rannsfd2417b2021-07-16 14:00:16 +00001797 self.assert_equal(self.get_arp_rx_garp(self.pg1), 1)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001798
1799 #
1800 # Send a GARP (reply) to swap the host 1's address to that of host 3
1801 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001802 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1803 op="is-at",
1804 hwdst=self.pg1.local_mac,
1805 hwsrc=self.pg1.remote_hosts[3].mac,
1806 pdst=self.pg1.remote_hosts[1].ip4,
1807 psrc=self.pg1.remote_hosts[1].ip4,
1808 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001809
1810 self.pg1.add_stream(p1)
1811 self.pg_enable_capture(self.pg_interfaces)
1812 self.pg_start()
1813
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001814 self.assertTrue(
1815 find_nbr(
1816 self,
1817 self.pg1.sw_if_index,
1818 self.pg1.remote_hosts[1].ip4,
1819 mac=self.pg1.remote_hosts[3].mac,
1820 )
1821 )
Neale Rannsfd2417b2021-07-16 14:00:16 +00001822 self.assert_equal(self.get_arp_rx_garp(self.pg1), 2)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001823
1824 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001825 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001826 # don't result in new neighbour entries
1827 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001828 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1829 op="who-has",
1830 hwdst=self.pg1.local_mac,
1831 hwsrc=self.pg1.remote_hosts[3].mac,
1832 pdst=self.pg1.remote_hosts[2].ip4,
1833 psrc=self.pg1.remote_hosts[2].ip4,
1834 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001835
1836 self.pg1.add_stream(p1)
1837 self.pg_enable_capture(self.pg_interfaces)
1838 self.pg_start()
1839
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001840 self.assertFalse(
1841 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1842 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001843
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001844 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1845 op="is-at",
1846 hwdst=self.pg1.local_mac,
1847 hwsrc=self.pg1.remote_hosts[3].mac,
1848 pdst=self.pg1.remote_hosts[2].ip4,
1849 psrc=self.pg1.remote_hosts[2].ip4,
1850 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001851
1852 self.pg1.add_stream(p1)
1853 self.pg_enable_capture(self.pg_interfaces)
1854 self.pg_start()
1855
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001856 self.assertFalse(
1857 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1858 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001859
Neale Ranns22eefd72020-09-23 11:25:21 +00001860 #
1861 # IP address in different subnets are not learnt
1862 #
1863 self.pg2.configure_ipv4_neighbors()
1864
Benoît Ganne114b1542022-09-12 17:56:16 +02001865 cntr = self.statistics.get_err_counter(
1866 "/err/arp-reply/l3_dst_address_not_local"
1867 )
1868
Neale Ranns22eefd72020-09-23 11:25:21 +00001869 for op in ["is-at", "who-has"]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001870 p1 = [
1871 (
1872 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1873 / ARP(
1874 op=op,
1875 hwdst=self.pg2.local_mac,
1876 hwsrc=self.pg2.remote_hosts[1].mac,
1877 pdst=self.pg2.remote_hosts[1].ip4,
1878 psrc=self.pg2.remote_hosts[1].ip4,
1879 )
1880 ),
1881 (
1882 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1883 / ARP(
1884 op=op,
1885 hwdst="ff:ff:ff:ff:ff:ff",
1886 hwsrc=self.pg2.remote_hosts[1].mac,
1887 pdst=self.pg2.remote_hosts[1].ip4,
1888 psrc=self.pg2.remote_hosts[1].ip4,
1889 )
1890 ),
1891 ]
Neale Ranns22eefd72020-09-23 11:25:21 +00001892
1893 self.send_and_assert_no_replies(self.pg1, p1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001894 self.assertFalse(
1895 find_nbr(self, self.pg1.sw_if_index, self.pg2.remote_hosts[1].ip4)
1896 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001897
1898 # they are all dropped because the subnet's don't match
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001899 self.assertEqual(
Benoît Ganne114b1542022-09-12 17:56:16 +02001900 cntr + 4,
Neale Ranns13a74ae2022-08-09 00:59:37 +00001901 self.statistics.get_err_counter("/err/arp-reply/l3_dst_address_not_local"),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001902 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001903
Neale Ranns77f91622020-11-23 16:25:27 +00001904 def test_arp_incomplete2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001905 """Incomplete Entries"""
Neale Rannsc8352bc2018-08-29 10:23:58 -07001906
1907 #
Neale Rannscd35e532018-08-31 02:51:45 -07001908 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001909 #
1910 self.pg0.generate_remote_hosts(2)
1911
Neale Rannscd35e532018-08-31 02:51:45 -07001912 #
1913 # IPv4/ARP
1914 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001915 ip_10_0_0_1 = VppIpRoute(
1916 self,
1917 "10.0.0.1",
1918 32,
1919 [VppRoutePath(self.pg0.remote_hosts[1].ip4, self.pg0.sw_if_index)],
1920 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001921 ip_10_0_0_1.add_vpp_config()
1922
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001923 p1 = (
1924 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1925 / IP(src=self.pg1.remote_ip4, dst="10.0.0.1")
1926 / UDP(sport=1234, dport=1234)
1927 / Raw()
1928 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001929
1930 self.pg1.add_stream(p1 * 257)
1931 self.pg_enable_capture(self.pg_interfaces)
1932 self.pg_start()
1933 rx = self.pg0._get_capture(1)
1934
1935 #
1936 # how many we get is going to be dependent on the time for packet
1937 # processing but it should be small
1938 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001939 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001940
Neale Rannscd35e532018-08-31 02:51:45 -07001941 #
1942 # IPv6/ND
1943 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001944 ip_10_1 = VppIpRoute(
1945 self,
1946 "10::1",
1947 128,
1948 [
1949 VppRoutePath(
1950 self.pg0.remote_hosts[1].ip6,
1951 self.pg0.sw_if_index,
1952 proto=DpoProto.DPO_PROTO_IP6,
1953 )
1954 ],
1955 )
Neale Rannscd35e532018-08-31 02:51:45 -07001956 ip_10_1.add_vpp_config()
1957
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001958 p1 = (
1959 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1960 / IPv6(src=self.pg1.remote_ip6, dst="10::1")
1961 / UDP(sport=1234, dport=1234)
1962 / Raw()
1963 )
Neale Rannscd35e532018-08-31 02:51:45 -07001964
1965 self.pg1.add_stream(p1 * 257)
1966 self.pg_enable_capture(self.pg_interfaces)
1967 self.pg_start()
1968 rx = self.pg0._get_capture(1)
1969
1970 #
1971 # how many we get is going to be dependent on the time for packet
1972 # processing but it should be small
1973 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001974 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001975
Neale Ranns7425f922019-01-23 00:36:16 -08001976 def test_arp_forus(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001977 """ARP for for-us"""
Neale Ranns7425f922019-01-23 00:36:16 -08001978
1979 #
1980 # Test that VPP responds with ARP requests to addresses that
1981 # are connected and local routes.
1982 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001983 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001984 # address added to an interface
1985 #
1986 self.pg0.generate_remote_hosts(2)
1987
Neale Ranns097fa662018-05-01 05:17:55 -07001988 forus = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001989 self,
1990 self.pg0.remote_hosts[1].ip4,
1991 32,
1992 [
1993 VppRoutePath(
1994 "0.0.0.0",
1995 self.pg0.sw_if_index,
1996 type=FibPathType.FIB_PATH_TYPE_LOCAL,
1997 )
1998 ],
1999 )
Neale Ranns7425f922019-01-23 00:36:16 -08002000 forus.add_vpp_config()
2001
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002002 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
2003 op="who-has",
2004 hwdst=self.pg0.local_mac,
2005 hwsrc=self.pg0.remote_mac,
2006 pdst=self.pg0.remote_hosts[1].ip4,
2007 psrc=self.pg0.remote_ip4,
2008 )
Neale Ranns7425f922019-01-23 00:36:16 -08002009
2010 rx = self.send_and_expect(self.pg0, [p], self.pg0)
2011
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002012 self.verify_arp_resp(
2013 rx[0],
2014 self.pg0.local_mac,
2015 self.pg0.remote_mac,
2016 self.pg0.remote_hosts[1].ip4,
2017 self.pg0.remote_ip4,
2018 )
Neale Ranns7425f922019-01-23 00:36:16 -08002019
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002020 def test_arp_table_swap(self):
2021 #
2022 # Generate some hosts on the LAN
2023 #
2024 N_NBRS = 4
2025 self.pg1.generate_remote_hosts(N_NBRS)
2026
2027 for n in range(N_NBRS):
2028 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002029 VppIpRoute(
2030 self,
2031 "10.0.0.%d" % n,
2032 32,
2033 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
2034 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002035
2036 # resolve each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002037 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
2038 op="is-at",
2039 hwdst=self.pg1.local_mac,
2040 hwsrc="00:00:5e:00:01:09",
2041 pdst=self.pg1.local_ip4,
2042 psrc=self.pg1.remote_hosts[n].ip4,
2043 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002044
2045 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
2046
2047 self.logger.info(self.vapi.cli("sh ip neighbors"))
2048
2049 #
2050 # swap the table pg1 is in
2051 #
2052 table = VppIpTable(self, 100).add_vpp_config()
2053
2054 self.pg1.unconfig_ip4()
2055 self.pg1.set_table_ip4(100)
2056 self.pg1.config_ip4()
2057
2058 #
2059 # all neighbours are cleared
2060 #
2061 for n in range(N_NBRS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002062 self.assertFalse(
2063 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip4)
2064 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002065
2066 #
2067 # packets to all neighbours generate ARP requests
2068 #
2069 for n in range(N_NBRS):
2070 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002071 VppIpRoute(
2072 self,
2073 "10.0.0.%d" % n,
2074 32,
2075 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
2076 table_id=100,
2077 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002078
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002079 p = (
2080 Ether(src=self.pg1.remote_hosts[n].mac, dst=self.pg1.local_mac)
2081 / IP(src=self.pg1.remote_hosts[n].ip4, dst="10.0.0.%d" % n)
2082 / Raw(b"0x5" * 100)
2083 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002084 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
2085 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002086 self.verify_arp_req(
2087 rx,
2088 self.pg1.local_mac,
2089 self.pg1.local_ip4,
2090 self.pg1.remote_hosts[n].ip4,
2091 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00002092
2093 self.pg1.unconfig_ip4()
2094 self.pg1.set_table_ip4(0)
2095
Neale Rannse2fe0972020-11-26 08:37:27 +00002096 def test_glean_src_select(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002097 """Multi Connecteds"""
Neale Rannse2fe0972020-11-26 08:37:27 +00002098
2099 #
2100 # configure multiple connected subnets on an interface
2101 # and ensure that ARP requests for hosts on those subnets
2102 # pick up the correct source address
2103 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002104 conn1 = VppIpInterfaceAddress(self, self.pg1, "10.0.0.1", 24).add_vpp_config()
2105 conn2 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.1", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002106
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002107 p1 = (
2108 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2109 / IP(src=self.pg1.remote_ip4, dst="10.0.0.128")
2110 / Raw(b"0x5" * 100)
2111 )
Neale Rannse2fe0972020-11-26 08:37:27 +00002112
2113 rxs = self.send_and_expect(self.pg0, [p1], self.pg1)
2114 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002115 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.0.1", "10.0.0.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002116
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002117 p2 = (
2118 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2119 / IP(src=self.pg1.remote_ip4, dst="10.0.1.128")
2120 / Raw(b"0x5" * 100)
2121 )
Neale Rannse2fe0972020-11-26 08:37:27 +00002122
2123 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2124 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002125 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002126
2127 #
2128 # add a local address in the same subnet
2129 # the source addresses are equivalent. VPP happens to
2130 # choose the last one that was added
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002131 conn3 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.2", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002132
2133 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2134 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002135 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002136
2137 #
2138 # remove
2139 #
2140 conn3.remove_vpp_config()
2141 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2142 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002143 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002144
2145 #
2146 # add back, this time remove the first one
2147 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002148 conn3 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.2", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002149
2150 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2151 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002152 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002153
2154 conn1.remove_vpp_config()
2155 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2156 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002157 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002158
Neale Ranns66edaf22021-07-09 13:03:52 +00002159 # apply a connected prefix to an interface in a different table
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002160 VppIpRoute(
2161 self,
2162 "10.0.1.0",
2163 24,
2164 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
2165 table_id=1,
2166 ).add_vpp_config()
Neale Ranns66edaf22021-07-09 13:03:52 +00002167
2168 rxs = self.send_and_expect(self.pg3, [p2], self.pg1)
2169 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002170 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Ranns66edaf22021-07-09 13:03:52 +00002171
Neale Ranns39528792023-03-08 04:53:37 +00002172 # apply an attached prefix to the interface
2173 # since there's no local address in this prefix,
2174 # any other address is used
2175 p3 = (
2176 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2177 / IP(src=self.pg1.remote_ip4, dst="10.0.2.128")
2178 / Raw(b"0x5" * 100)
2179 )
2180
2181 VppIpRoute(
2182 self,
2183 "10.0.2.0",
2184 24,
2185 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
2186 ).add_vpp_config()
2187
2188 rxs = self.send_and_expect(self.pg0, [p3], self.pg1)
2189 for rx in rxs:
2190 self.verify_arp_req(
2191 rx, self.pg1.local_mac, self.pg1.local_ip4, "10.0.2.128"
2192 )
2193
Neale Rannse2fe0972020-11-26 08:37:27 +00002194 # cleanup
2195 conn3.remove_vpp_config()
2196 conn2.remove_vpp_config()
2197
Neale Rannsdcd6d622017-05-26 02:59:16 -07002198
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002199@tag_fixme_vpp_workers
Neale Ranns14260392018-09-28 05:00:57 -07002200class NeighborStatsTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002201 """ARP/ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002202
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002203 @classmethod
2204 def setUpClass(cls):
2205 super(NeighborStatsTestCase, cls).setUpClass()
2206
2207 @classmethod
2208 def tearDownClass(cls):
2209 super(NeighborStatsTestCase, cls).tearDownClass()
2210
Neale Ranns14260392018-09-28 05:00:57 -07002211 def setUp(self):
2212 super(NeighborStatsTestCase, self).setUp()
2213
2214 self.create_pg_interfaces(range(2))
2215
2216 # pg0 configured with ip4 and 6 addresses used for input
2217 # pg1 configured with ip4 and 6 addresses used for output
2218 # pg2 is unnumbered to pg0
2219 for i in self.pg_interfaces:
2220 i.admin_up()
2221 i.config_ip4()
2222 i.config_ip6()
2223 i.resolve_arp()
2224 i.resolve_ndp()
2225
2226 def tearDown(self):
2227 super(NeighborStatsTestCase, self).tearDown()
2228
2229 for i in self.pg_interfaces:
2230 i.unconfig_ip4()
2231 i.unconfig_ip6()
2232 i.admin_down()
2233
2234 def test_arp_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002235 """ARP Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002236
2237 self.vapi.cli("adj counters enable")
2238 self.pg1.generate_remote_hosts(2)
2239
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002240 arp1 = VppNeighbor(
2241 self,
2242 self.pg1.sw_if_index,
2243 self.pg1.remote_hosts[0].mac,
2244 self.pg1.remote_hosts[0].ip4,
2245 )
Neale Ranns14260392018-09-28 05:00:57 -07002246 arp1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002247 arp2 = VppNeighbor(
2248 self,
2249 self.pg1.sw_if_index,
2250 self.pg1.remote_hosts[1].mac,
2251 self.pg1.remote_hosts[1].ip4,
2252 )
Neale Ranns14260392018-09-28 05:00:57 -07002253 arp2.add_vpp_config()
2254
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002255 p1 = (
2256 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2257 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[0].ip4)
2258 / UDP(sport=1234, dport=1234)
2259 / Raw()
2260 )
2261 p2 = (
2262 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2263 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
2264 / UDP(sport=1234, dport=1234)
2265 / Raw()
2266 )
Neale Ranns14260392018-09-28 05:00:57 -07002267
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002268 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
2269 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07002270
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002271 self.assertEqual(NUM_PKTS, arp1.get_stats()["packets"])
2272 self.assertEqual(NUM_PKTS, arp2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002273
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002274 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002275 self.assertEqual(NUM_PKTS * 2, arp1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002276
2277 def test_nd_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002278 """ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002279
2280 self.vapi.cli("adj counters enable")
2281 self.pg0.generate_remote_hosts(3)
2282
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002283 nd1 = VppNeighbor(
2284 self,
2285 self.pg0.sw_if_index,
2286 self.pg0.remote_hosts[1].mac,
2287 self.pg0.remote_hosts[1].ip6,
2288 )
Neale Ranns14260392018-09-28 05:00:57 -07002289 nd1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002290 nd2 = VppNeighbor(
2291 self,
2292 self.pg0.sw_if_index,
2293 self.pg0.remote_hosts[2].mac,
2294 self.pg0.remote_hosts[2].ip6,
2295 )
Neale Ranns14260392018-09-28 05:00:57 -07002296 nd2.add_vpp_config()
2297
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002298 p1 = (
2299 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2300 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[1].ip6)
2301 / UDP(sport=1234, dport=1234)
2302 / Raw()
2303 )
2304 p2 = (
2305 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2306 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[2].ip6)
2307 / UDP(sport=1234, dport=1234)
2308 / Raw()
2309 )
Neale Ranns14260392018-09-28 05:00:57 -07002310
2311 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
2312 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
2313
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002314 self.assertEqual(16, nd1.get_stats()["packets"])
2315 self.assertEqual(16, nd2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002316
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002317 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002318 self.assertEqual(NUM_PKTS + 16, nd1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002319
2320
Dave Wallace670724c2022-09-20 21:52:18 -04002321@tag_fixme_ubuntu2204
Neale Rannscbe25aa2019-09-30 10:53:31 +00002322class NeighborAgeTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002323 """ARP/ND Aging"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002324
2325 @classmethod
2326 def setUpClass(cls):
2327 super(NeighborAgeTestCase, cls).setUpClass()
2328
2329 @classmethod
2330 def tearDownClass(cls):
2331 super(NeighborAgeTestCase, cls).tearDownClass()
2332
2333 def setUp(self):
2334 super(NeighborAgeTestCase, self).setUp()
2335
2336 self.create_pg_interfaces(range(1))
2337
2338 # pg0 configured with ip4 and 6 addresses used for input
2339 # pg1 configured with ip4 and 6 addresses used for output
2340 # pg2 is unnumbered to pg0
2341 for i in self.pg_interfaces:
2342 i.admin_up()
2343 i.config_ip4()
2344 i.config_ip6()
2345 i.resolve_arp()
2346 i.resolve_ndp()
2347
2348 def tearDown(self):
2349 super(NeighborAgeTestCase, self).tearDown()
2350
2351 for i in self.pg_interfaces:
2352 i.unconfig_ip4()
2353 i.unconfig_ip6()
2354 i.admin_down()
2355
Neale Rannscbe25aa2019-09-30 10:53:31 +00002356 def verify_arp_req(self, rx, smac, sip, dip):
2357 ether = rx[Ether]
2358 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2359 self.assertEqual(ether.src, smac)
2360
2361 arp = rx[ARP]
2362 self.assertEqual(arp.hwtype, 1)
2363 self.assertEqual(arp.ptype, 0x800)
2364 self.assertEqual(arp.hwlen, 6)
2365 self.assertEqual(arp.plen, 4)
2366 self.assertEqual(arp.op, arp_opts["who-has"])
2367 self.assertEqual(arp.hwsrc, smac)
2368 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2369 self.assertEqual(arp.psrc, sip)
2370 self.assertEqual(arp.pdst, dip)
2371
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002372 def verify_ip_neighbor_config(self, af, max_number, max_age, recycle):
2373 config = self.vapi.ip_neighbor_config_get(af)
2374
2375 self.assertEqual(config.af, af)
2376 self.assertEqual(config.max_number, max_number)
2377 self.assertEqual(config.max_age, max_age)
2378 self.assertEqual(config.recycle, recycle)
2379
Neale Rannscbe25aa2019-09-30 10:53:31 +00002380 def test_age(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002381 """Aging/Recycle"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002382
2383 self.vapi.cli("set logging unthrottle 0")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002384 self.vapi.cli("set logging size %d" % 0xFFFF)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002385
2386 self.pg0.generate_remote_hosts(201)
2387
2388 vaf = VppEnum.vl_api_address_family_t
2389
2390 #
2391 # start listening on all interfaces
2392 #
2393 self.pg_enable_capture(self.pg_interfaces)
2394
2395 #
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002396 # Verify neighbor configuration defaults
2397 #
2398 self.verify_ip_neighbor_config(
2399 af=vaf.ADDRESS_IP4, max_number=50000, max_age=0, recycle=False
2400 )
2401
2402 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002403 # Set the neighbor configuration:
2404 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002405 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00002406 # recycle = false
2407 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002408 self.vapi.ip_neighbor_config(
2409 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2410 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002411 self.verify_ip_neighbor_config(
2412 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2413 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002414
2415 self.vapi.cli("sh ip neighbor-config")
2416
2417 # add the 198 neighbours that should pass (-1 for one created in setup)
2418 for ii in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002419 VppNeighbor(
2420 self,
2421 self.pg0.sw_if_index,
2422 self.pg0.remote_hosts[ii].mac,
2423 self.pg0.remote_hosts[ii].ip4,
2424 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002425
2426 # one more neighbor over the limit should fail
2427 with self.vapi.assert_negative_api_retval():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002428 VppNeighbor(
2429 self,
2430 self.pg0.sw_if_index,
2431 self.pg0.remote_hosts[200].mac,
2432 self.pg0.remote_hosts[200].ip4,
2433 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002434
2435 #
2436 # change the config to allow recycling the old neighbors
2437 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002438 self.vapi.ip_neighbor_config(
2439 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=True
2440 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002441 self.verify_ip_neighbor_config(
2442 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=True
2443 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002444
2445 # now new additions are allowed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002446 VppNeighbor(
2447 self,
2448 self.pg0.sw_if_index,
2449 self.pg0.remote_hosts[200].mac,
2450 self.pg0.remote_hosts[200].ip4,
2451 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002452
2453 # add the first neighbor we configured has been re-used
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002454 self.assertFalse(
2455 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2456 )
2457 self.assertTrue(
2458 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[200].ip4)
2459 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002460
2461 #
2462 # change the config to age old neighbors
2463 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002464 self.vapi.ip_neighbor_config(
2465 af=vaf.ADDRESS_IP4, max_number=200, max_age=2, recycle=True
2466 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002467 self.verify_ip_neighbor_config(
2468 af=vaf.ADDRESS_IP4, max_number=200, max_age=2, recycle=True
2469 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002470
2471 self.vapi.cli("sh ip4 neighbor-sorted")
2472
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002473 # age out neighbors
2474 self.virtual_sleep(3)
2475
Neale Rannscbe25aa2019-09-30 10:53:31 +00002476 #
2477 # expect probes from all these ARP entries as they age
2478 # 3 probes for each neighbor 3*200 = 600
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002479 rxs = self.pg0.get_capture(600, timeout=2)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002480
2481 for ii in range(3):
2482 for jj in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002483 rx = rxs[ii * 200 + jj]
Neale Rannscbe25aa2019-09-30 10:53:31 +00002484 # rx.show()
2485
2486 #
2487 # 3 probes sent then 1 more second to see if a reply comes, before
2488 # they age out
2489 #
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002490 self.virtual_sleep(1)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002491
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002492 self.assertFalse(
2493 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2494 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002495
2496 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002497 # load up some neighbours again with 2s aging enabled
2498 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002499 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002500 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002501 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2502
2503 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002504 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002505 VppNeighbor(
2506 self,
2507 self.pg0.sw_if_index,
2508 self.pg0.remote_hosts[ii].mac,
2509 self.pg0.remote_hosts[ii].ip4,
2510 ).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002511
2512 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002513 self.assertEqual(e.flags, enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2514 self.assertEqual(str(e.neighbor.ip_address), self.pg0.remote_hosts[ii].ip4)
2515 self.assertEqual(e.neighbor.mac_address, self.pg0.remote_hosts[ii].mac)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002516
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002517 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002518 self.assertFalse(
2519 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2520 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002521
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002522 evs = []
2523 for ii in range(10):
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_REMOVED)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002526 evs.append(e)
2527
2528 # check we got the correct mac/ip pairs - done separately
2529 # because we don't care about the order the remove notifications
2530 # arrive
2531 for ii in range(10):
2532 found = False
2533 mac = self.pg0.remote_hosts[ii].mac
2534 ip = self.pg0.remote_hosts[ii].ip4
2535
2536 for e in evs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002537 if e.neighbor.mac_address == mac and str(e.neighbor.ip_address) == ip:
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002538 found = True
2539 break
2540 self.assertTrue(found)
2541
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002542 #
2543 # check if we can set age and recycle with empty neighbor list
2544 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002545 self.vapi.ip_neighbor_config(
2546 af=vaf.ADDRESS_IP4, max_number=200, max_age=1000, recycle=True
2547 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002548 self.verify_ip_neighbor_config(
2549 af=vaf.ADDRESS_IP4, max_number=200, max_age=1000, recycle=True
2550 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002551
2552 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002553 # load up some neighbours again, then disable the aging
2554 # they should still be there in 10 seconds time
2555 #
2556 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002557 VppNeighbor(
2558 self,
2559 self.pg0.sw_if_index,
2560 self.pg0.remote_hosts[ii].mac,
2561 self.pg0.remote_hosts[ii].ip4,
2562 ).add_vpp_config()
2563 self.vapi.ip_neighbor_config(
2564 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2565 )
Alexander Chernavine1cc8752023-06-26 15:57:57 +00002566 self.verify_ip_neighbor_config(
2567 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2568 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002569
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002570 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002571 self.assertTrue(
2572 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2573 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002574
2575
Neale Rannsc87fbb42020-04-02 17:08:28 +00002576class NeighborReplaceTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002577 """ARP/ND Replacement"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002578
2579 @classmethod
2580 def setUpClass(cls):
2581 super(NeighborReplaceTestCase, cls).setUpClass()
2582
2583 @classmethod
2584 def tearDownClass(cls):
2585 super(NeighborReplaceTestCase, cls).tearDownClass()
2586
2587 def setUp(self):
2588 super(NeighborReplaceTestCase, self).setUp()
2589
2590 self.create_pg_interfaces(range(4))
2591
2592 # pg0 configured with ip4 and 6 addresses used for input
2593 # pg1 configured with ip4 and 6 addresses used for output
2594 # pg2 is unnumbered to pg0
2595 for i in self.pg_interfaces:
2596 i.admin_up()
2597 i.config_ip4()
2598 i.config_ip6()
2599 i.resolve_arp()
2600 i.resolve_ndp()
2601
2602 def tearDown(self):
2603 super(NeighborReplaceTestCase, self).tearDown()
2604
2605 for i in self.pg_interfaces:
2606 i.unconfig_ip4()
2607 i.unconfig_ip6()
2608 i.admin_down()
2609
2610 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002611 """replace"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002612
2613 N_HOSTS = 16
2614
2615 for i in self.pg_interfaces:
2616 i.generate_remote_hosts(N_HOSTS)
2617 i.configure_ipv4_neighbors()
2618 i.configure_ipv6_neighbors()
2619
2620 # replace them all
2621 self.vapi.ip_neighbor_replace_begin()
2622 self.vapi.ip_neighbor_replace_end()
2623
2624 for i in self.pg_interfaces:
2625 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002626 self.assertFalse(
2627 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip4)
2628 )
2629 self.assertFalse(
2630 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip6)
2631 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002632
2633 #
2634 # and them all back via the API
2635 #
2636 for i in self.pg_interfaces:
2637 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002638 VppNeighbor(
2639 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip4
2640 ).add_vpp_config()
2641 VppNeighbor(
2642 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip6
2643 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002644
2645 #
2646 # begin the replacement again, this time touch some
2647 # the neighbours on pg1 so they are not deleted
2648 #
2649 self.vapi.ip_neighbor_replace_begin()
2650
2651 # update from the API all neighbours on pg1
2652 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002653 VppNeighbor(
2654 self,
2655 self.pg1.sw_if_index,
2656 self.pg1.remote_hosts[h].mac,
2657 self.pg1.remote_hosts[h].ip4,
2658 ).add_vpp_config()
2659 VppNeighbor(
2660 self,
2661 self.pg1.sw_if_index,
2662 self.pg1.remote_hosts[h].mac,
2663 self.pg1.remote_hosts[h].ip6,
2664 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002665
2666 # update from the data-plane all neighbours on pg3
2667 self.pg3.configure_ipv4_neighbors()
2668 self.pg3.configure_ipv6_neighbors()
2669
2670 # complete the replacement
2671 self.logger.info(self.vapi.cli("sh ip neighbors"))
2672 self.vapi.ip_neighbor_replace_end()
2673
2674 for i in self.pg_interfaces:
2675 if i == self.pg1 or i == self.pg3:
2676 # neighbours on pg1 and pg3 are still present
2677 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002678 self.assertTrue(
2679 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2680 )
2681 self.assertTrue(
2682 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2683 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002684 else:
2685 # all other neighbours are toast
2686 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002687 self.assertFalse(
2688 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2689 )
2690 self.assertFalse(
2691 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2692 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002693
2694
Neale Ranns240dcb22020-04-23 09:04:59 +00002695class NeighborFlush(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002696 """Neighbor Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002697
2698 @classmethod
2699 def setUpClass(cls):
2700 super(NeighborFlush, cls).setUpClass()
2701
2702 @classmethod
2703 def tearDownClass(cls):
2704 super(NeighborFlush, cls).tearDownClass()
2705
2706 def setUp(self):
2707 super(NeighborFlush, self).setUp()
2708
2709 self.create_pg_interfaces(range(2))
2710
2711 for i in self.pg_interfaces:
2712 i.admin_up()
2713 i.config_ip4()
2714 i.config_ip6()
2715 i.resolve_arp()
2716 i.resolve_ndp()
2717
2718 def tearDown(self):
2719 super(NeighborFlush, self).tearDown()
2720
2721 for i in self.pg_interfaces:
2722 i.unconfig_ip4()
2723 i.unconfig_ip6()
2724 i.admin_down()
2725
2726 def test_flush(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002727 """Neighbour Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002728
2729 e = VppEnum
2730 nf = e.vl_api_ip_neighbor_flags_t
2731 af = e.vl_api_address_family_t
2732 N_HOSTS = 16
2733 static = [False, True]
2734 self.pg0.generate_remote_hosts(N_HOSTS)
2735 self.pg1.generate_remote_hosts(N_HOSTS)
2736
2737 for s in static:
2738 # a few v4 and v6 dynamic neoghbors
2739 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002740 VppNeighbor(
2741 self,
2742 self.pg0.sw_if_index,
2743 self.pg0.remote_hosts[n].mac,
2744 self.pg0.remote_hosts[n].ip4,
2745 is_static=s,
2746 ).add_vpp_config()
2747 VppNeighbor(
2748 self,
2749 self.pg1.sw_if_index,
2750 self.pg1.remote_hosts[n].mac,
2751 self.pg1.remote_hosts[n].ip6,
2752 is_static=s,
2753 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002754
2755 # flush the interfaces individually
2756 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2757
2758 # check we haven't flushed that which we shouldn't
2759 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002760 self.assertTrue(
2761 find_nbr(
2762 self,
2763 self.pg1.sw_if_index,
2764 self.pg1.remote_hosts[n].ip6,
2765 is_static=s,
2766 )
2767 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002768
2769 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2770
2771 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002772 self.assertFalse(
2773 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2774 )
2775 self.assertFalse(
2776 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2777 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002778
2779 # add the nieghbours back
2780 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002781 VppNeighbor(
2782 self,
2783 self.pg0.sw_if_index,
2784 self.pg0.remote_hosts[n].mac,
2785 self.pg0.remote_hosts[n].ip4,
2786 is_static=s,
2787 ).add_vpp_config()
2788 VppNeighbor(
2789 self,
2790 self.pg1.sw_if_index,
2791 self.pg1.remote_hosts[n].mac,
2792 self.pg1.remote_hosts[n].ip6,
2793 is_static=s,
2794 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002795
2796 self.logger.info(self.vapi.cli("sh ip neighbor"))
2797
2798 # flush both interfaces at the same time
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002799 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002800
2801 # check we haven't flushed that which we shouldn't
2802 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002803 self.assertTrue(
2804 find_nbr(
2805 self,
2806 self.pg0.sw_if_index,
2807 self.pg0.remote_hosts[n].ip4,
2808 is_static=s,
2809 )
2810 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002811
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002812 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002813
2814 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002815 self.assertFalse(
2816 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2817 )
2818 self.assertFalse(
2819 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2820 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002821
2822
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002823if __name__ == "__main__":
Neale Ranns37be7362017-02-21 17:30:26 -08002824 unittest.main(testRunner=VppTestRunner)