blob: 503b1f11456a8a21736623ee0cf5551487c167a9 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns39f9d8b2017-02-16 21:57:05 -08002
3import unittest
Neale Rannscbe25aa2019-09-30 10:53:31 +00004import os
Neale Ranns39f9d8b2017-02-16 21:57:05 -08005from socket import AF_INET, AF_INET6, inet_pton
6
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00007from framework import tag_fixme_vpp_workers
Neale Ranns39f9d8b2017-02-16 21:57:05 -08008from framework import VppTestCase, VppTestRunner
9from vpp_neighbor import VppNeighbor, find_nbr
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020010from vpp_ip_route import (
11 VppIpRoute,
12 VppRoutePath,
13 find_route,
14 VppIpTable,
15 DpoProto,
16 FibPathType,
17 VppIpInterfaceAddress,
18)
Neale Ranns37029302018-08-10 05:30:06 -070019from vpp_papi import VppEnum
Jakub Grajciar2df2f752020-12-01 11:23:44 +010020from vpp_ip import VppIpPuntRedirect
Neale Ranns39f9d8b2017-02-16 21:57:05 -080021
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070022import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080023from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070024from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000025from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070026from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080027from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070028from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080029
Paul Vinciguerra4271c972019-05-14 13:25:49 -040030
31NUM_PKTS = 67
32
Neale Ranns39f9d8b2017-02-16 21:57:05 -080033# not exported by scapy, so redefined here
34arp_opts = {"who-has": 1, "is-at": 2}
35
36
37class ARPTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020038 """ARP Test Case"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -080039
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070040 @classmethod
41 def setUpClass(cls):
42 super(ARPTestCase, cls).setUpClass()
43
44 @classmethod
45 def tearDownClass(cls):
46 super(ARPTestCase, cls).tearDownClass()
47
Neale Ranns39f9d8b2017-02-16 21:57:05 -080048 def setUp(self):
49 super(ARPTestCase, self).setUp()
50
51 # create 3 pg interfaces
52 self.create_pg_interfaces(range(4))
53
54 # pg0 configured with ip4 and 6 addresses used for input
55 # pg1 configured with ip4 and 6 addresses used for output
56 # pg2 is unnumbered to pg0
57 for i in self.pg_interfaces:
58 i.admin_up()
59
60 self.pg0.config_ip4()
61 self.pg0.config_ip6()
62 self.pg0.resolve_arp()
63
64 self.pg1.config_ip4()
65 self.pg1.config_ip6()
66
67 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070068 self.tbl = VppIpTable(self, 1)
69 self.tbl.add_vpp_config()
70
Neale Ranns39f9d8b2017-02-16 21:57:05 -080071 self.pg3.set_table_ip4(1)
72 self.pg3.config_ip4()
73
Neale Ranns4008ac92017-02-13 23:20:04 -080074 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080075 self.pg0.unconfig_ip4()
76 self.pg0.unconfig_ip6()
77
78 self.pg1.unconfig_ip4()
79 self.pg1.unconfig_ip6()
80
81 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070082 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080083
Neale Ranns4008ac92017-02-13 23:20:04 -080084 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080085 i.admin_down()
86
Neale Ranns15002542017-09-10 04:39:11 -070087 super(ARPTestCase, self).tearDown()
88
Neale Ranns39f9d8b2017-02-16 21:57:05 -080089 def verify_arp_req(self, rx, smac, sip, dip):
90 ether = rx[Ether]
91 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
92 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +010093 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -080094
95 arp = rx[ARP]
96 self.assertEqual(arp.hwtype, 1)
97 self.assertEqual(arp.ptype, 0x800)
98 self.assertEqual(arp.hwlen, 6)
99 self.assertEqual(arp.plen, 4)
100 self.assertEqual(arp.op, arp_opts["who-has"])
101 self.assertEqual(arp.hwsrc, smac)
102 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
103 self.assertEqual(arp.psrc, sip)
104 self.assertEqual(arp.pdst, dip)
105
106 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
107 ether = rx[Ether]
108 self.assertEqual(ether.dst, dmac)
109 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100110 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800111
112 arp = rx[ARP]
113 self.assertEqual(arp.hwtype, 1)
114 self.assertEqual(arp.ptype, 0x800)
115 self.assertEqual(arp.hwlen, 6)
116 self.assertEqual(arp.plen, 4)
117 self.assertEqual(arp.op, arp_opts["is-at"])
118 self.assertEqual(arp.hwsrc, smac)
119 self.assertEqual(arp.hwdst, dmac)
120 self.assertEqual(arp.psrc, sip)
121 self.assertEqual(arp.pdst, dip)
122
Matthew Smithcb9ab472017-05-16 21:35:56 -0500123 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
124 ether = rx[Ether]
125 self.assertEqual(ether.dst, dmac)
126 self.assertEqual(ether.src, smac)
127
128 arp = rx[ARP]
129 self.assertEqual(arp.hwtype, 1)
130 self.assertEqual(arp.ptype, 0x800)
131 self.assertEqual(arp.hwlen, 6)
132 self.assertEqual(arp.plen, 4)
133 self.assertEqual(arp.op, arp_opts["is-at"])
134 self.assertNotEqual(arp.hwsrc, smac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200135 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or "00:00:5E:00:01" in arp.hwsrc)
Matthew Smithcb9ab472017-05-16 21:35:56 -0500136 self.assertEqual(arp.hwdst, dmac)
137 self.assertEqual(arp.psrc, sip)
138 self.assertEqual(arp.pdst, dip)
139
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800140 def verify_ip(self, rx, smac, dmac, sip, dip):
141 ether = rx[Ether]
142 self.assertEqual(ether.dst, dmac)
143 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100144 self.assertEqual(ether.type, 0x0800)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800145
146 ip = rx[IP]
147 self.assertEqual(ip.src, sip)
148 self.assertEqual(ip.dst, dip)
149
Neale Ranns37be7362017-02-21 17:30:26 -0800150 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
151 ether = rx[Ether]
152 self.assertEqual(ether.dst, dmac)
153 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100154 self.assertEqual(ether.type, 0x8847)
Neale Ranns37be7362017-02-21 17:30:26 -0800155
156 mpls = rx[MPLS]
157 self.assertTrue(mpls.label, label)
158
159 ip = rx[IP]
160 self.assertEqual(ip.src, sip)
161 self.assertEqual(ip.dst, dip)
162
Neale Rannsfd2417b2021-07-16 14:00:16 +0000163 def get_arp_rx_requests(self, itf):
164 """Get ARP RX request stats for and interface"""
165 return self.statistics["/net/arp/rx/requests"][:, itf.sw_if_index].sum()
166
167 def get_arp_tx_requests(self, itf):
168 """Get ARP TX request stats for and interface"""
169 return self.statistics["/net/arp/tx/requests"][:, itf.sw_if_index].sum()
170
171 def get_arp_rx_replies(self, itf):
172 """Get ARP RX replies stats for and interface"""
173 return self.statistics["/net/arp/rx/replies"][:, itf.sw_if_index].sum()
174
175 def get_arp_tx_replies(self, itf):
176 """Get ARP TX replies stats for and interface"""
177 return self.statistics["/net/arp/tx/replies"][:, itf.sw_if_index].sum()
178
179 def get_arp_rx_garp(self, itf):
180 """Get ARP RX grat stats for and interface"""
181 return self.statistics["/net/arp/rx/gratuitous"][:, itf.sw_if_index].sum()
182
183 def get_arp_tx_garp(self, itf):
184 """Get ARP RX grat stats for and interface"""
185 return self.statistics["/net/arp/tx/gratuitous"][:, itf.sw_if_index].sum()
186
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800187 def test_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200188 """ARP"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800189
190 #
191 # Generate some hosts on the LAN
192 #
Neale Rannsca193612017-06-14 06:50:08 -0700193 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800194
195 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000196 # watch for:
197 # - all neighbour events
198 # - all neighbor events on pg1
199 # - neighbor events for host[1] on pg1
200 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200201 self.vapi.want_ip_neighbor_events(enable=1, pid=os.getpid())
202 self.vapi.want_ip_neighbor_events(
203 enable=1, pid=os.getpid(), sw_if_index=self.pg1.sw_if_index
204 )
205 self.vapi.want_ip_neighbor_events(
206 enable=1,
207 pid=os.getpid(),
208 sw_if_index=self.pg1.sw_if_index,
209 ip=self.pg1.remote_hosts[1].ip4,
210 )
Neale Rannscbe25aa2019-09-30 10:53:31 +0000211
212 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
213
214 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800215 # Send IP traffic to one of these unresolved hosts.
216 # expect the generation of an ARP request
217 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200218 p = (
219 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
220 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4)
221 / UDP(sport=1234, dport=1234)
222 / Raw()
223 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800224
225 self.pg0.add_stream(p)
226 self.pg_enable_capture(self.pg_interfaces)
227 self.pg_start()
228
229 rx = self.pg1.get_capture(1)
230
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200231 self.verify_arp_req(
232 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
233 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800234
Neale Rannsfd2417b2021-07-16 14:00:16 +0000235 self.logger.info(self.vapi.cli("sh ip neighbor-stats"))
236 self.logger.info(self.vapi.cli("sh ip neighbor-stats pg1"))
237 self.assert_equal(self.get_arp_tx_requests(self.pg1), 1)
238
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800239 #
240 # And a dynamic ARP entry for host 1
241 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200242 dyn_arp = VppNeighbor(
243 self,
244 self.pg1.sw_if_index,
245 self.pg1.remote_hosts[1].mac,
246 self.pg1.remote_hosts[1].ip4,
247 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800248 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000249 self.assertTrue(dyn_arp.query_vpp_config())
250
Neale Rannsdc617b82020-08-20 08:22:56 +0000251 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
252
Neale Rannscbe25aa2019-09-30 10:53:31 +0000253 # this matches all of the listnerers
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200254 es = [self.vapi.wait_for_event(1, "ip_neighbor_event") for i in range(3)]
Neale Rannscbe25aa2019-09-30 10:53:31 +0000255 for e in es:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200256 self.assertEqual(str(e.neighbor.ip_address), self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800257
258 #
259 # now we expect IP traffic forwarded
260 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200261 dyn_p = (
262 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
263 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4)
264 / UDP(sport=1234, dport=1234)
265 / Raw()
266 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800267
268 self.pg0.add_stream(dyn_p)
269 self.pg_enable_capture(self.pg_interfaces)
270 self.pg_start()
271
272 rx = self.pg1.get_capture(1)
273
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200274 self.verify_ip(
275 rx[0],
276 self.pg1.local_mac,
277 self.pg1.remote_hosts[1].mac,
278 self.pg0.remote_ip4,
279 self.pg1._remote_hosts[1].ip4,
280 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800281
282 #
283 # And a Static ARP entry for host 2
284 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200285 static_arp = VppNeighbor(
286 self,
287 self.pg1.sw_if_index,
288 self.pg1.remote_hosts[2].mac,
289 self.pg1.remote_hosts[2].ip4,
290 is_static=1,
291 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800292 static_arp.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200293 es = [self.vapi.wait_for_event(1, "ip_neighbor_event") for i in range(2)]
Neale Rannscbe25aa2019-09-30 10:53:31 +0000294 for e in es:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200295 self.assertEqual(str(e.neighbor.ip_address), self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800296
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200297 static_p = (
298 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
299 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[2].ip4)
300 / UDP(sport=1234, dport=1234)
301 / Raw()
302 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800303
304 self.pg0.add_stream(static_p)
305 self.pg_enable_capture(self.pg_interfaces)
306 self.pg_start()
307
308 rx = self.pg1.get_capture(1)
309
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200310 self.verify_ip(
311 rx[0],
312 self.pg1.local_mac,
313 self.pg1.remote_hosts[2].mac,
314 self.pg0.remote_ip4,
315 self.pg1._remote_hosts[2].ip4,
316 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800317
318 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000319 # remove all the listeners
320 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200321 self.vapi.want_ip_neighbor_events(enable=0, pid=os.getpid())
322 self.vapi.want_ip_neighbor_events(
323 enable=0, pid=os.getpid(), sw_if_index=self.pg1.sw_if_index
324 )
325 self.vapi.want_ip_neighbor_events(
326 enable=0,
327 pid=os.getpid(),
328 sw_if_index=self.pg1.sw_if_index,
329 ip=self.pg1.remote_hosts[1].ip4,
330 )
Neale Rannscbe25aa2019-09-30 10:53:31 +0000331
332 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800333 # flap the link. dynamic ARPs get flush, statics don't
334 #
335 self.pg1.admin_down()
336 self.pg1.admin_up()
337
338 self.pg0.add_stream(static_p)
339 self.pg_enable_capture(self.pg_interfaces)
340 self.pg_start()
341 rx = self.pg1.get_capture(1)
342
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200343 self.verify_ip(
344 rx[0],
345 self.pg1.local_mac,
346 self.pg1.remote_hosts[2].mac,
347 self.pg0.remote_ip4,
348 self.pg1._remote_hosts[2].ip4,
349 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800350
351 self.pg0.add_stream(dyn_p)
352 self.pg_enable_capture(self.pg_interfaces)
353 self.pg_start()
354
355 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200356 self.verify_arp_req(
357 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
358 )
Neale Rannsfd2417b2021-07-16 14:00:16 +0000359 self.assert_equal(self.get_arp_tx_requests(self.pg1), 2)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800360
Neale Rannscbe25aa2019-09-30 10:53:31 +0000361 self.assertFalse(dyn_arp.query_vpp_config())
362 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800363 #
364 # Send an ARP request from one of the so-far unlearned remote hosts
365 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200366 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[3].mac) / ARP(
367 op="who-has",
368 hwsrc=self.pg1._remote_hosts[3].mac,
369 pdst=self.pg1.local_ip4,
370 psrc=self.pg1._remote_hosts[3].ip4,
371 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800372
373 self.pg1.add_stream(p)
374 self.pg_enable_capture(self.pg_interfaces)
375 self.pg_start()
376
377 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200378 self.verify_arp_resp(
379 rx[0],
380 self.pg1.local_mac,
381 self.pg1._remote_hosts[3].mac,
382 self.pg1.local_ip4,
383 self.pg1._remote_hosts[3].ip4,
384 )
Neale Rannsfd2417b2021-07-16 14:00:16 +0000385 self.logger.info(self.vapi.cli("sh ip neighbor-stats pg1"))
386 self.assert_equal(self.get_arp_rx_requests(self.pg1), 1)
387 self.assert_equal(self.get_arp_tx_replies(self.pg1), 1)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800388
389 #
390 # VPP should have learned the mapping for the remote host
391 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200392 self.assertTrue(
393 find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[3].ip4)
394 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800395 #
396 # Fire in an ARP request before the interface becomes IP enabled
397 #
398 self.pg2.generate_remote_hosts(4)
399
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200400 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
401 op="who-has",
402 hwsrc=self.pg2.remote_mac,
403 pdst=self.pg1.local_ip4,
404 psrc=self.pg2.remote_hosts[3].ip4,
405 )
406 pt = (
407 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac)
408 / Dot1Q(vlan=0)
409 / ARP(
410 op="who-has",
411 hwsrc=self.pg2.remote_mac,
412 pdst=self.pg1.local_ip4,
413 psrc=self.pg2.remote_hosts[3].ip4,
414 )
415 )
416 self.send_and_assert_no_replies(self.pg2, p, "interface not IP enabled")
Neale Ranns4b919a52017-03-11 05:55:21 -0800417
418 #
419 # Make pg2 un-numbered to pg1
420 #
421 self.pg2.set_unnumbered(self.pg1.sw_if_index)
422
Neale Rannsac3e72c2019-10-06 01:04:26 -0700423 #
424 # test the unnumbered dump both by all interfaces and just the enabled
425 # one
426 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700427 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700428 self.assertTrue(len(unnum))
429 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
430 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
431 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
432 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700433 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
434 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
435
Neale Ranns4b919a52017-03-11 05:55:21 -0800436 #
437 # We should respond to ARP requests for the unnumbered to address
438 # once an attached route to the source is known
439 #
440 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200441 self.pg2, p, "ARP req for unnumbered address - no source"
442 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800443
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200444 attached_host = VppIpRoute(
445 self,
446 self.pg2.remote_hosts[3].ip4,
447 32,
448 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
449 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800450 attached_host.add_vpp_config()
451
452 self.pg2.add_stream(p)
453 self.pg_enable_capture(self.pg_interfaces)
454 self.pg_start()
455
456 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200457 self.verify_arp_resp(
458 rx[0],
459 self.pg2.local_mac,
460 self.pg2.remote_mac,
461 self.pg1.local_ip4,
462 self.pg2.remote_hosts[3].ip4,
463 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800464
Neale Ranns30d0fd42017-05-30 07:30:04 -0700465 self.pg2.add_stream(pt)
466 self.pg_enable_capture(self.pg_interfaces)
467 self.pg_start()
468
469 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200470 self.verify_arp_resp(
471 rx[0],
472 self.pg2.local_mac,
473 self.pg2.remote_mac,
474 self.pg1.local_ip4,
475 self.pg2.remote_hosts[3].ip4,
476 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700477
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800478 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800479 # A neighbor entry that has no associated FIB-entry
480 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200481 arp_no_fib = VppNeighbor(
482 self,
483 self.pg1.sw_if_index,
484 self.pg1.remote_hosts[4].mac,
485 self.pg1.remote_hosts[4].ip4,
486 is_no_fib_entry=1,
487 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800488 arp_no_fib.add_vpp_config()
489
490 #
491 # check we have the neighbor, but no route
492 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200493 self.assertTrue(
494 find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[4].ip4)
495 )
496 self.assertFalse(find_route(self, self.pg1._remote_hosts[4].ip4, 32))
Neale Ranns3983ac22017-03-10 11:53:27 -0800497 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800498 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
499 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800500 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200501 arp_unnum = VppNeighbor(
502 self,
503 self.pg2.sw_if_index,
504 self.pg1.remote_hosts[5].mac,
505 self.pg1.remote_hosts[5].ip4,
506 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800507 arp_unnum.add_vpp_config()
508
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200509 p = (
510 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
511 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[5].ip4)
512 / UDP(sport=1234, dport=1234)
513 / Raw()
514 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800515
516 self.pg0.add_stream(p)
517 self.pg_enable_capture(self.pg_interfaces)
518 self.pg_start()
519
520 rx = self.pg2.get_capture(1)
521
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200522 self.verify_ip(
523 rx[0],
524 self.pg2.local_mac,
525 self.pg1.remote_hosts[5].mac,
526 self.pg0.remote_ip4,
527 self.pg1._remote_hosts[5].ip4,
528 )
Neale Ranns3983ac22017-03-10 11:53:27 -0800529
530 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800531 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
532 # with the unnumbered interface's address as the source
533 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200534 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
535 op="who-has",
536 hwsrc=self.pg2.remote_mac,
537 pdst=self.pg1.local_ip4,
538 psrc=self.pg1.remote_hosts[6].ip4,
539 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800540
541 self.pg2.add_stream(p)
542 self.pg_enable_capture(self.pg_interfaces)
543 self.pg_start()
544
545 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200546 self.verify_arp_resp(
547 rx[0],
548 self.pg2.local_mac,
549 self.pg2.remote_mac,
550 self.pg1.local_ip4,
551 self.pg1.remote_hosts[6].ip4,
552 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800553
554 #
555 # An attached host route out of pg2 for an undiscovered hosts generates
556 # an ARP request with the unnumbered address as the source
557 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200558 att_unnum = VppIpRoute(
559 self,
560 self.pg1.remote_hosts[7].ip4,
561 32,
562 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
563 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800564 att_unnum.add_vpp_config()
565
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200566 p = (
567 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
568 / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[7].ip4)
569 / UDP(sport=1234, dport=1234)
570 / Raw()
571 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800572
573 self.pg0.add_stream(p)
574 self.pg_enable_capture(self.pg_interfaces)
575 self.pg_start()
576
577 rx = self.pg2.get_capture(1)
578
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200579 self.verify_arp_req(
580 rx[0], self.pg2.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[7].ip4
581 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800582
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200583 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
584 op="who-has",
585 hwsrc=self.pg2.remote_mac,
586 pdst=self.pg1.local_ip4,
587 psrc=self.pg1.remote_hosts[7].ip4,
588 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800589
590 self.pg2.add_stream(p)
591 self.pg_enable_capture(self.pg_interfaces)
592 self.pg_start()
593
594 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200595 self.verify_arp_resp(
596 rx[0],
597 self.pg2.local_mac,
598 self.pg2.remote_mac,
599 self.pg1.local_ip4,
600 self.pg1.remote_hosts[7].ip4,
601 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800602
603 #
604 # An attached host route as yet unresolved out of pg2 for an
605 # undiscovered host, an ARP requests begets a response.
606 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200607 att_unnum1 = VppIpRoute(
608 self,
609 self.pg1.remote_hosts[8].ip4,
610 32,
611 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
612 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800613 att_unnum1.add_vpp_config()
614
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200615 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
616 op="who-has",
617 hwsrc=self.pg2.remote_mac,
618 pdst=self.pg1.local_ip4,
619 psrc=self.pg1.remote_hosts[8].ip4,
620 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800621
622 self.pg2.add_stream(p)
623 self.pg_enable_capture(self.pg_interfaces)
624 self.pg_start()
625
626 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200627 self.verify_arp_resp(
628 rx[0],
629 self.pg2.local_mac,
630 self.pg2.remote_mac,
631 self.pg1.local_ip4,
632 self.pg1.remote_hosts[8].ip4,
633 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800634
635 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700636 # Send an ARP request from one of the so-far unlearned remote hosts
637 # with a VLAN0 tag
638 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200639 p = (
640 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[9].mac)
641 / Dot1Q(vlan=0)
642 / ARP(
643 op="who-has",
644 hwsrc=self.pg1._remote_hosts[9].mac,
645 pdst=self.pg1.local_ip4,
646 psrc=self.pg1._remote_hosts[9].ip4,
647 )
648 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700649
650 self.pg1.add_stream(p)
651 self.pg_enable_capture(self.pg_interfaces)
652 self.pg_start()
653
654 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200655 self.verify_arp_resp(
656 rx[0],
657 self.pg1.local_mac,
658 self.pg1._remote_hosts[9].mac,
659 self.pg1.local_ip4,
660 self.pg1._remote_hosts[9].ip4,
661 )
Neale Ranns30d0fd42017-05-30 07:30:04 -0700662
663 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700664 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700665 # Should still get an ARP resp since the cover is attached
666 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200667 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) / ARP(
668 op="who-has",
669 hwsrc=self.pg1.remote_mac,
670 pdst=self.pg1.local_ip4,
671 psrc=self.pg1.remote_hosts[10].ip4,
672 )
Neale Rannsca193612017-06-14 06:50:08 -0700673
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200674 r1 = VppIpRoute(
675 self,
676 self.pg1.remote_hosts[10].ip4,
677 30,
678 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
679 )
Neale Rannsca193612017-06-14 06:50:08 -0700680 r1.add_vpp_config()
681
682 self.pg1.add_stream(p)
683 self.pg_enable_capture(self.pg_interfaces)
684 self.pg_start()
685 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200686 self.verify_arp_resp(
687 rx[0],
688 self.pg1.local_mac,
689 self.pg1.remote_mac,
690 self.pg1.local_ip4,
691 self.pg1.remote_hosts[10].ip4,
692 )
Neale Rannsca193612017-06-14 06:50:08 -0700693
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200694 r2 = VppIpRoute(
695 self,
696 self.pg1.remote_hosts[10].ip4,
697 32,
698 [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)],
699 )
Neale Rannsca193612017-06-14 06:50:08 -0700700 r2.add_vpp_config()
701
702 self.pg1.add_stream(p)
703 self.pg_enable_capture(self.pg_interfaces)
704 self.pg_start()
705 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200706 self.verify_arp_resp(
707 rx[0],
708 self.pg1.local_mac,
709 self.pg1.remote_mac,
710 self.pg1.local_ip4,
711 self.pg1.remote_hosts[10].ip4,
712 )
Neale Rannsca193612017-06-14 06:50:08 -0700713
714 #
715 # add an ARP entry that's not on the sub-net and so whose
716 # adj-fib fails the refinement check. then send an ARP request
717 # from that source
718 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200719 a1 = VppNeighbor(
720 self, self.pg0.sw_if_index, self.pg0.remote_mac, "100.100.100.50"
721 )
Neale Rannsca193612017-06-14 06:50:08 -0700722 a1.add_vpp_config()
723
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200724 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
725 op="who-has",
726 hwsrc=self.pg0.remote_mac,
727 psrc="100.100.100.50",
728 pdst=self.pg0.remote_ip4,
729 )
730 self.send_and_assert_no_replies(self.pg0, p, "ARP req for from failed adj-fib")
Neale Rannsca193612017-06-14 06:50:08 -0700731
732 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800733 # ERROR Cases
734 # 1 - don't respond to ARP request for address not within the
735 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700736 # 1b - nor within the unnumbered subnet
737 # 1c - nor within the subnet of a different interface
738 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200739 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
740 op="who-has",
741 hwsrc=self.pg0.remote_mac,
742 pdst="10.10.10.3",
743 psrc=self.pg0.remote_ip4,
744 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800745 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200746 self.pg0, p, "ARP req for non-local destination"
747 )
748 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, "10.10.10.3"))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800749
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200750 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
751 op="who-has",
752 hwsrc=self.pg2.remote_mac,
753 pdst="10.10.10.3",
754 psrc=self.pg1.remote_hosts[7].ip4,
755 )
756 self.send_and_assert_no_replies(
757 self.pg0, p, "ARP req for non-local destination - unnum"
758 )
759
760 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
761 op="who-has",
762 hwsrc=self.pg0.remote_mac,
763 pdst=self.pg1.local_ip4,
764 psrc=self.pg1.remote_ip4,
765 )
766 self.send_and_assert_no_replies(self.pg0, p, "ARP req diff sub-net")
767 self.assertFalse(find_nbr(self, self.pg0.sw_if_index, self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700768
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800769 #
770 # 2 - don't respond to ARP request from an address not within the
771 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700772 # 2b - to a proxied address
773 # 2c - not within a different interface's sub-net
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200774 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
775 op="who-has",
776 hwsrc=self.pg0.remote_mac,
777 psrc="10.10.10.3",
778 pdst=self.pg0.local_ip4,
779 )
780 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
781 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(
782 op="who-has",
783 hwsrc=self.pg2.remote_mac,
784 psrc="10.10.10.3",
785 pdst=self.pg0.local_ip4,
786 )
Neale Ranns4b919a52017-03-11 05:55:21 -0800787 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200788 self.pg0, p, "ARP req for non-local source - unnum"
789 )
790 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
791 op="who-has",
792 hwsrc=self.pg0.remote_mac,
793 psrc=self.pg1.remote_ip4,
794 pdst=self.pg0.local_ip4,
795 )
796 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800797
798 #
799 # 3 - don't respond to ARP request from an address that belongs to
800 # the router
801 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200802 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
803 op="who-has",
804 hwsrc=self.pg0.remote_mac,
805 psrc=self.pg0.local_ip4,
806 pdst=self.pg0.local_ip4,
807 )
808 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800809
810 #
811 # 4 - don't respond to ARP requests that has mac source different
812 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800813 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200814 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
815 op="who-has",
816 hwsrc="00:00:00:DE:AD:BE",
817 psrc=self.pg0.remote_ip4,
818 pdst=self.pg0.local_ip4,
819 )
820 self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800821
822 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800823 # 5 - don't respond to ARP requests for address within the
824 # interface's sub-net but not the interface's address
825 #
826 self.pg0.generate_remote_hosts(2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200827 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
828 op="who-has",
829 hwsrc=self.pg0.remote_mac,
830 psrc=self.pg0.remote_hosts[0].ip4,
831 pdst=self.pg0.remote_hosts[1].ip4,
832 )
833 self.send_and_assert_no_replies(
834 self.pg0, p, "ARP req for non-local destination"
835 )
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800836
837 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800838 # cleanup
839 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800840 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800841 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800842
Neale Ranns4b919a52017-03-11 05:55:21 -0800843 # need this to flush the adj-fibs
844 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
845 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700846 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800847
Neale Ranns24b170a2017-08-15 05:33:11 -0700848 def test_proxy_mirror_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200849 """Interface Mirror Proxy ARP"""
Neale Ranns24b170a2017-08-15 05:33:11 -0700850
851 #
852 # When VPP has an interface whose address is also applied to a TAP
853 # interface on the host, then VPP's TAP interface will be unnumbered
854 # to the 'real' interface and do proxy ARP from the host.
855 # the curious aspect of this setup is that ARP requests from the host
856 # will come from the VPP's own address.
857 #
858 self.pg0.generate_remote_hosts(2)
859
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200860 arp_req_from_me = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
861 op="who-has",
862 hwsrc=self.pg2.remote_mac,
863 pdst=self.pg0.remote_hosts[1].ip4,
864 psrc=self.pg0.local_ip4,
865 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700866
867 #
868 # Configure Proxy ARP for the subnet on PG0addresses on pg0
869 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200870 self.vapi.proxy_arp_add_del(
871 proxy={
872 "table_id": 0,
873 "low": self.pg0._local_ip4_subnet,
874 "hi": self.pg0._local_ip4_bcast,
875 },
876 is_add=1,
877 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700878
879 # Make pg2 un-numbered to pg0
880 #
881 self.pg2.set_unnumbered(self.pg0.sw_if_index)
882
883 #
884 # Enable pg2 for proxy ARP
885 #
886 self.pg2.set_proxy_arp()
887
888 #
889 # Send the ARP request with an originating address that
890 # is VPP's own address
891 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000892 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200893 self.verify_arp_resp(
894 rx[0],
895 self.pg2.local_mac,
896 self.pg2.remote_mac,
897 self.pg0.remote_hosts[1].ip4,
898 self.pg0.local_ip4,
899 )
Neale Ranns24b170a2017-08-15 05:33:11 -0700900
901 #
902 # validate we have not learned an ARP entry as a result of this
903 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200904 self.assertFalse(find_nbr(self, self.pg2.sw_if_index, self.pg0.local_ip4))
Neale Ranns24b170a2017-08-15 05:33:11 -0700905
906 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000907 # setup a punt redirect so packets from the uplink go to the tap
908 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200909 redirect = VppIpPuntRedirect(
910 self, self.pg0.sw_if_index, self.pg2.sw_if_index, self.pg0.local_ip4
911 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100912 redirect.add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +0000913
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200914 p_tcp = (
915 Ether(
916 src=self.pg0.remote_mac,
917 dst=self.pg0.local_mac,
918 )
919 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
920 / TCP(sport=80, dport=80)
921 / Raw()
922 )
Neale Ranns240dcb22020-04-23 09:04:59 +0000923 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
924
925 # there's no ARP entry so this is an ARP req
926 self.assertTrue(rx[0].haslayer(ARP))
927
928 # and ARP entry for VPP's pg0 address on the host interface
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200929 n1 = VppNeighbor(
930 self,
931 self.pg2.sw_if_index,
932 self.pg2.remote_mac,
933 self.pg0.local_ip4,
934 is_no_fib_entry=True,
935 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +0000936 # now the packets shold forward
937 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
938 self.assertFalse(rx[0].haslayer(ARP))
939 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
940
941 #
942 # flush the neighbor cache on the uplink
943 #
944 af = VppEnum.vl_api_address_family_t
945 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
946
947 # ensure we can still resolve the ARPs on the uplink
948 self.pg0.resolve_arp()
949
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200950 self.assertTrue(find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_ip4))
Neale Ranns240dcb22020-04-23 09:04:59 +0000951
952 #
Neale Ranns24b170a2017-08-15 05:33:11 -0700953 # cleanup
954 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200955 self.vapi.proxy_arp_add_del(
956 proxy={
957 "table_id": 0,
958 "low": self.pg0._local_ip4_subnet,
959 "hi": self.pg0._local_ip4_bcast,
960 },
961 is_add=0,
962 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100963 redirect.remove_vpp_config()
Neale Ranns24b170a2017-08-15 05:33:11 -0700964
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800965 def test_proxy_arp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200966 """Proxy ARP"""
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800967
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700968 self.pg1.generate_remote_hosts(2)
969
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800970 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700971 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800972 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200973 arp_req_pg0 = Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
974 op="who-has",
975 hwsrc=self.pg0.remote_mac,
976 pdst="10.10.10.3",
977 psrc=self.pg0.remote_ip4,
978 )
979 arp_req_pg0_tagged = (
980 Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff")
981 / Dot1Q(vlan=0)
982 / ARP(
983 op="who-has",
984 hwsrc=self.pg0.remote_mac,
985 pdst="10.10.10.3",
986 psrc=self.pg0.remote_ip4,
987 )
988 )
989 arp_req_pg1 = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
990 op="who-has",
991 hwsrc=self.pg1.remote_mac,
992 pdst="10.10.10.3",
993 psrc=self.pg1.remote_ip4,
994 )
995 arp_req_pg2 = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
996 op="who-has",
997 hwsrc=self.pg2.remote_mac,
998 pdst="10.10.10.3",
999 psrc=self.pg1.remote_hosts[1].ip4,
1000 )
1001 arp_req_pg3 = Ether(src=self.pg3.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1002 op="who-has",
1003 hwsrc=self.pg3.remote_mac,
1004 pdst="10.10.10.3",
1005 psrc=self.pg3.remote_ip4,
1006 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001007
1008 #
1009 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
1010 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001011 self.vapi.proxy_arp_add_del(
1012 proxy={"table_id": 0, "low": "10.10.10.2", "hi": "10.10.10.124"}, is_add=1
1013 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001014
1015 #
1016 # No responses are sent when the interfaces are not enabled for proxy
1017 # ARP
1018 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001019 self.send_and_assert_no_replies(
1020 self.pg0, arp_req_pg0, "ARP req from unconfigured interface"
1021 )
1022 self.send_and_assert_no_replies(
1023 self.pg2, arp_req_pg2, "ARP req from unconfigured interface"
1024 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001025
1026 #
1027 # Make pg2 un-numbered to pg1
1028 # still won't reply.
1029 #
1030 self.pg2.set_unnumbered(self.pg1.sw_if_index)
1031
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001032 self.send_and_assert_no_replies(
1033 self.pg2, arp_req_pg2, "ARP req from unnumbered interface"
1034 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001035
1036 #
1037 # Enable each interface to reply to proxy ARPs
1038 #
1039 for i in self.pg_interfaces:
1040 i.set_proxy_arp()
1041
1042 #
1043 # Now each of the interfaces should reply to a request to a proxied
1044 # address
1045 #
1046 self.pg0.add_stream(arp_req_pg0)
1047 self.pg_enable_capture(self.pg_interfaces)
1048 self.pg_start()
1049
1050 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001051 self.verify_arp_resp(
1052 rx[0],
1053 self.pg0.local_mac,
1054 self.pg0.remote_mac,
1055 "10.10.10.3",
1056 self.pg0.remote_ip4,
1057 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001058
Neale Ranns30d0fd42017-05-30 07:30:04 -07001059 self.pg0.add_stream(arp_req_pg0_tagged)
1060 self.pg_enable_capture(self.pg_interfaces)
1061 self.pg_start()
1062
1063 rx = self.pg0.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001064 self.verify_arp_resp(
1065 rx[0],
1066 self.pg0.local_mac,
1067 self.pg0.remote_mac,
1068 "10.10.10.3",
1069 self.pg0.remote_ip4,
1070 )
Neale Ranns30d0fd42017-05-30 07:30:04 -07001071
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001072 self.pg1.add_stream(arp_req_pg1)
1073 self.pg_enable_capture(self.pg_interfaces)
1074 self.pg_start()
1075
1076 rx = self.pg1.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001077 self.verify_arp_resp(
1078 rx[0],
1079 self.pg1.local_mac,
1080 self.pg1.remote_mac,
1081 "10.10.10.3",
1082 self.pg1.remote_ip4,
1083 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001084
1085 self.pg2.add_stream(arp_req_pg2)
1086 self.pg_enable_capture(self.pg_interfaces)
1087 self.pg_start()
1088
1089 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001090 self.verify_arp_resp(
1091 rx[0],
1092 self.pg2.local_mac,
1093 self.pg2.remote_mac,
1094 "10.10.10.3",
1095 self.pg1.remote_hosts[1].ip4,
1096 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001097
1098 #
1099 # A request for an address out of the configured range
1100 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001101 arp_req_pg1_hi = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1102 op="who-has",
1103 hwsrc=self.pg1.remote_mac,
1104 pdst="10.10.10.125",
1105 psrc=self.pg1.remote_ip4,
1106 )
1107 self.send_and_assert_no_replies(
1108 self.pg1, arp_req_pg1_hi, "ARP req out of range HI"
1109 )
1110 arp_req_pg1_low = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
1111 op="who-has",
1112 hwsrc=self.pg1.remote_mac,
1113 pdst="10.10.10.1",
1114 psrc=self.pg1.remote_ip4,
1115 )
1116 self.send_and_assert_no_replies(
1117 self.pg1, arp_req_pg1_low, "ARP req out of range Low"
1118 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001119
1120 #
1121 # Request for an address in the proxy range but from an interface
1122 # in a different VRF
1123 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001124 self.send_and_assert_no_replies(
1125 self.pg3, arp_req_pg3, "ARP req from different VRF"
1126 )
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001127
1128 #
1129 # Disable Each interface for proxy ARP
1130 # - expect none to respond
1131 #
1132 for i in self.pg_interfaces:
1133 i.set_proxy_arp(0)
1134
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001135 self.send_and_assert_no_replies(self.pg0, arp_req_pg0, "ARP req from disable")
1136 self.send_and_assert_no_replies(self.pg1, arp_req_pg1, "ARP req from disable")
1137 self.send_and_assert_no_replies(self.pg2, arp_req_pg2, "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001138
1139 #
1140 # clean up on interface 2
1141 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001142 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001143
1144 def test_mpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001145 """MPLS"""
Neale Ranns37be7362017-02-21 17:30:26 -08001146
1147 #
1148 # Interface 2 does not yet have ip4 config
1149 #
1150 self.pg2.config_ip4()
1151 self.pg2.generate_remote_hosts(2)
1152
1153 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001154 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001155 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001156 ip_10_0_0_1 = VppIpRoute(
1157 self,
1158 "10.0.0.1",
1159 32,
1160 [
1161 VppRoutePath(
1162 self.pg2.remote_hosts[1].ip4, self.pg2.sw_if_index, labels=[55]
1163 )
1164 ],
1165 )
Neale Ranns37be7362017-02-21 17:30:26 -08001166 ip_10_0_0_1.add_vpp_config()
1167
1168 #
1169 # packets should generate an ARP request
1170 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001171 p = (
1172 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1173 / IP(src=self.pg0.remote_ip4, dst="10.0.0.1")
1174 / UDP(sport=1234, dport=1234)
1175 / Raw(b"\xa5" * 100)
1176 )
Neale Ranns37be7362017-02-21 17:30:26 -08001177
1178 self.pg0.add_stream(p)
1179 self.pg_enable_capture(self.pg_interfaces)
1180 self.pg_start()
1181
1182 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001183 self.verify_arp_req(
1184 rx[0], self.pg2.local_mac, self.pg2.local_ip4, self.pg2._remote_hosts[1].ip4
1185 )
Neale Ranns37be7362017-02-21 17:30:26 -08001186
1187 #
1188 # now resolve the neighbours
1189 #
1190 self.pg2.configure_ipv4_neighbors()
1191
1192 #
1193 # Now packet should be properly MPLS encapped.
1194 # This verifies that MPLS link-type adjacencies are completed
1195 # when the ARP entry resolves
1196 #
1197 self.pg0.add_stream(p)
1198 self.pg_enable_capture(self.pg_interfaces)
1199 self.pg_start()
1200
1201 rx = self.pg2.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001202 self.verify_ip_o_mpls(
1203 rx[0],
1204 self.pg2.local_mac,
1205 self.pg2.remote_hosts[1].mac,
1206 55,
1207 self.pg0.remote_ip4,
1208 "10.0.0.1",
1209 )
Neale Ranns4b919a52017-03-11 05:55:21 -08001210 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001211
Matthew Smithcb9ab472017-05-16 21:35:56 -05001212 def test_arp_vrrp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001213 """ARP reply with VRRP virtual src hw addr"""
Matthew Smithcb9ab472017-05-16 21:35:56 -05001214
1215 #
1216 # IP packet destined for pg1 remote host arrives on pg0 resulting
1217 # in an ARP request for the address of the remote host on pg1
1218 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001219 p0 = (
1220 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1221 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1222 / UDP(sport=1234, dport=1234)
1223 / Raw()
1224 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001225
Neale Ranns37029302018-08-10 05:30:06 -07001226 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001227
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001228 self.verify_arp_req(
1229 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_ip4
1230 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001231
1232 #
1233 # ARP reply for address of pg1 remote host arrives on pg1 with
1234 # the hw src addr set to a value in the VRRP IPv4 range of
1235 # MAC addresses
1236 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001237 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
1238 op="is-at",
1239 hwdst=self.pg1.local_mac,
1240 hwsrc="00:00:5e:00:01:09",
1241 pdst=self.pg1.local_ip4,
1242 psrc=self.pg1.remote_ip4,
1243 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001244
Neale Ranns37029302018-08-10 05:30:06 -07001245 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001246
1247 #
1248 # IP packet destined for pg1 remote host arrives on pg0 again.
1249 # VPP should have an ARP entry for that address now and the packet
1250 # should be sent out pg1.
1251 #
Neale Ranns37029302018-08-10 05:30:06 -07001252 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001253
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001254 self.verify_ip(
1255 rx1[0],
1256 self.pg1.local_mac,
1257 "00:00:5e:00:01:09",
1258 self.pg0.remote_ip4,
1259 self.pg1.remote_ip4,
1260 )
Matthew Smithcb9ab472017-05-16 21:35:56 -05001261
1262 self.pg1.admin_down()
1263 self.pg1.admin_up()
1264
Neale Rannsdcd6d622017-05-26 02:59:16 -07001265 def test_arp_duplicates(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001266 """ARP Duplicates"""
Neale Rannsdcd6d622017-05-26 02:59:16 -07001267
1268 #
1269 # Generate some hosts on the LAN
1270 #
1271 self.pg1.generate_remote_hosts(3)
1272
1273 #
1274 # Add host 1 on pg1 and pg2
1275 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001276 arp_pg1 = VppNeighbor(
1277 self,
1278 self.pg1.sw_if_index,
1279 self.pg1.remote_hosts[1].mac,
1280 self.pg1.remote_hosts[1].ip4,
1281 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001282 arp_pg1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001283 arp_pg2 = VppNeighbor(
1284 self,
1285 self.pg2.sw_if_index,
1286 self.pg2.remote_mac,
1287 self.pg1.remote_hosts[1].ip4,
1288 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001289 arp_pg2.add_vpp_config()
1290
1291 #
1292 # IP packet destined for pg1 remote host arrives on pg1 again.
1293 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001294 p = (
1295 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1296 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1297 / UDP(sport=1234, dport=1234)
1298 / Raw()
1299 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001300
1301 self.pg0.add_stream(p)
1302 self.pg_enable_capture(self.pg_interfaces)
1303 self.pg_start()
1304
1305 rx1 = self.pg1.get_capture(1)
1306
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001307 self.verify_ip(
1308 rx1[0],
1309 self.pg1.local_mac,
1310 self.pg1.remote_hosts[1].mac,
1311 self.pg0.remote_ip4,
1312 self.pg1.remote_hosts[1].ip4,
1313 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001314
1315 #
1316 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001317 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001318 #
1319 arp_pg1.remove_vpp_config()
1320
1321 self.pg0.add_stream(p)
1322 self.pg_enable_capture(self.pg_interfaces)
1323 self.pg_start()
1324
1325 rx1 = self.pg1.get_capture(1)
1326
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001327 self.verify_arp_req(
1328 rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_hosts[1].ip4
1329 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001330
1331 #
1332 # Add it back
1333 #
1334 arp_pg1.add_vpp_config()
1335
1336 self.pg0.add_stream(p)
1337 self.pg_enable_capture(self.pg_interfaces)
1338 self.pg_start()
1339
1340 rx1 = self.pg1.get_capture(1)
1341
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001342 self.verify_ip(
1343 rx1[0],
1344 self.pg1.local_mac,
1345 self.pg1.remote_hosts[1].mac,
1346 self.pg0.remote_ip4,
1347 self.pg1.remote_hosts[1].ip4,
1348 )
Neale Rannsdcd6d622017-05-26 02:59:16 -07001349
Neale Ranns15002542017-09-10 04:39:11 -07001350 def test_arp_static(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001351 """ARP Static"""
Neale Ranns15002542017-09-10 04:39:11 -07001352 self.pg2.generate_remote_hosts(3)
1353
1354 #
1355 # Add a static ARP entry
1356 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001357 static_arp = VppNeighbor(
1358 self,
1359 self.pg2.sw_if_index,
1360 self.pg2.remote_hosts[1].mac,
1361 self.pg2.remote_hosts[1].ip4,
1362 is_static=1,
1363 )
Neale Ranns15002542017-09-10 04:39:11 -07001364 static_arp.add_vpp_config()
1365
1366 #
1367 # Add the connected prefix to the interface
1368 #
1369 self.pg2.config_ip4()
1370
1371 #
1372 # We should now find the adj-fib
1373 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001374 self.assertTrue(
1375 find_nbr(
1376 self, self.pg2.sw_if_index, self.pg2.remote_hosts[1].ip4, is_static=1
1377 )
1378 )
1379 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32))
Neale Ranns15002542017-09-10 04:39:11 -07001380
1381 #
1382 # remove the connected
1383 #
1384 self.pg2.unconfig_ip4()
1385
1386 #
1387 # put the interface into table 1
1388 #
1389 self.pg2.set_table_ip4(1)
1390
1391 #
1392 # configure the same connected and expect to find the
1393 # adj fib in the new table
1394 #
1395 self.pg2.config_ip4()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001396 self.assertTrue(find_route(self, self.pg2.remote_hosts[1].ip4, 32, table_id=1))
Neale Ranns15002542017-09-10 04:39:11 -07001397
1398 #
1399 # clean-up
1400 #
1401 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001402 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001403 self.pg2.set_table_ip4(0)
1404
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001405 def test_arp_static_replace_dynamic_same_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001406 """ARP Static can replace Dynamic (same mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001407 self.pg2.generate_remote_hosts(1)
1408
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001409 dyn_arp = VppNeighbor(
1410 self,
1411 self.pg2.sw_if_index,
1412 self.pg2.remote_hosts[0].mac,
1413 self.pg2.remote_hosts[0].ip4,
1414 )
1415 static_arp = VppNeighbor(
1416 self,
1417 self.pg2.sw_if_index,
1418 self.pg2.remote_hosts[0].mac,
1419 self.pg2.remote_hosts[0].ip4,
1420 is_static=1,
1421 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001422
1423 #
1424 # Add a dynamic ARP entry
1425 #
1426 dyn_arp.add_vpp_config()
1427
1428 #
1429 # We should find the dynamic nbr
1430 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001431 self.assertFalse(
1432 find_nbr(
1433 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1434 )
1435 )
1436 self.assertTrue(
1437 find_nbr(
1438 self,
1439 self.pg2.sw_if_index,
1440 self.pg2.remote_hosts[0].ip4,
1441 is_static=0,
1442 mac=self.pg2.remote_hosts[0].mac,
1443 )
1444 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001445
1446 #
1447 # Add a static ARP entry with the same mac
1448 #
1449 static_arp.add_vpp_config()
1450
1451 #
1452 # We should now find the static nbr with the same mac
1453 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001454 self.assertFalse(
1455 find_nbr(
1456 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1457 )
1458 )
1459 self.assertTrue(
1460 find_nbr(
1461 self,
1462 self.pg2.sw_if_index,
1463 self.pg2.remote_hosts[0].ip4,
1464 is_static=1,
1465 mac=self.pg2.remote_hosts[0].mac,
1466 )
1467 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001468
1469 #
1470 # clean-up
1471 #
1472 static_arp.remove_vpp_config()
1473
1474 def test_arp_static_replace_dynamic_diff_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001475 """ARP Static can replace Dynamic (diff mac)"""
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001476 self.pg2.generate_remote_hosts(2)
1477
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001478 dyn_arp = VppNeighbor(
1479 self,
1480 self.pg2.sw_if_index,
1481 self.pg2.remote_hosts[0].mac,
1482 self.pg2.remote_hosts[0].ip4,
1483 )
1484 static_arp = VppNeighbor(
1485 self,
1486 self.pg2.sw_if_index,
1487 self.pg2.remote_hosts[1].mac,
1488 self.pg2.remote_hosts[0].ip4,
1489 is_static=1,
1490 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001491
1492 #
1493 # Add a dynamic ARP entry
1494 #
1495 dyn_arp.add_vpp_config()
1496
1497 #
1498 # We should find the dynamic nbr
1499 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001500 self.assertFalse(
1501 find_nbr(
1502 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=1
1503 )
1504 )
1505 self.assertTrue(
1506 find_nbr(
1507 self,
1508 self.pg2.sw_if_index,
1509 self.pg2.remote_hosts[0].ip4,
1510 is_static=0,
1511 mac=self.pg2.remote_hosts[0].mac,
1512 )
1513 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001514
1515 #
1516 # Add a static ARP entry with a changed mac
1517 #
1518 static_arp.add_vpp_config()
1519
1520 #
1521 # We should now find the static nbr with a changed mac
1522 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001523 self.assertFalse(
1524 find_nbr(
1525 self, self.pg2.sw_if_index, self.pg2.remote_hosts[0].ip4, is_static=0
1526 )
1527 )
1528 self.assertTrue(
1529 find_nbr(
1530 self,
1531 self.pg2.sw_if_index,
1532 self.pg2.remote_hosts[0].ip4,
1533 is_static=1,
1534 mac=self.pg2.remote_hosts[1].mac,
1535 )
1536 )
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001537
1538 #
1539 # clean-up
1540 #
1541 static_arp.remove_vpp_config()
1542
Neale Rannsc819fc62018-02-16 02:44:05 -08001543 def test_arp_incomplete(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001544 """ARP Incomplete"""
Neale Rannsea8adf72021-08-13 08:10:59 +00001545 self.pg1.generate_remote_hosts(4)
Neale Rannsc819fc62018-02-16 02:44:05 -08001546
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001547 p0 = (
1548 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1549 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
1550 / UDP(sport=1234, dport=1234)
1551 / Raw()
1552 )
1553 p1 = (
1554 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1555 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
1556 / UDP(sport=1234, dport=1234)
1557 / Raw()
1558 )
1559 p2 = (
1560 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1561 / IP(src=self.pg0.remote_ip4, dst="1.1.1.1")
1562 / UDP(sport=1234, dport=1234)
1563 / Raw()
1564 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001565
1566 #
1567 # a packet to an unresolved destination generates an ARP request
1568 #
1569 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001570 self.verify_arp_req(
1571 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4
1572 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001573
1574 #
1575 # add a neighbour for remote host 1
1576 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001577 static_arp = VppNeighbor(
1578 self,
1579 self.pg1.sw_if_index,
1580 self.pg1.remote_hosts[1].mac,
1581 self.pg1.remote_hosts[1].ip4,
1582 is_static=1,
1583 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001584 static_arp.add_vpp_config()
1585
1586 #
Neale Rannsea8adf72021-08-13 08:10:59 +00001587 # add a route through remote host 3 hence we get an incomplete
1588 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001589 VppIpRoute(
1590 self,
1591 "1.1.1.1",
1592 32,
1593 [VppRoutePath(self.pg1.remote_hosts[3].ip4, self.pg1.sw_if_index)],
1594 ).add_vpp_config()
Neale Rannsea8adf72021-08-13 08:10:59 +00001595 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001596 self.verify_arp_req(
1597 rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[3].ip4
1598 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001599
1600 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001601 # change the interface's MAC
1602 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001603 self.vapi.sw_interface_set_mac_address(
1604 self.pg1.sw_if_index, "00:00:00:33:33:33"
1605 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001606
1607 #
1608 # now ARP requests come from the new source mac
1609 #
1610 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001611 self.verify_arp_req(
1612 rx[0],
1613 "00:00:00:33:33:33",
1614 self.pg1.local_ip4,
1615 self.pg1._remote_hosts[2].ip4,
1616 )
Neale Rannsea8adf72021-08-13 08:10:59 +00001617 rx = self.send_and_expect(self.pg0, [p2], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001618 self.verify_arp_req(
1619 rx[0],
1620 "00:00:00:33:33:33",
1621 self.pg1.local_ip4,
1622 self.pg1._remote_hosts[3].ip4,
1623 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001624
1625 #
1626 # packets to the resolved host also have the new source mac
1627 #
1628 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001629 self.verify_ip(
1630 rx[0],
1631 "00:00:00:33:33:33",
1632 self.pg1.remote_hosts[1].mac,
1633 self.pg0.remote_ip4,
1634 self.pg1.remote_hosts[1].ip4,
1635 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001636
1637 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001638 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001639 # configured subnet and thus no glean
1640 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001641 self.vapi.sw_interface_set_mac_address(
1642 self.pg2.sw_if_index, "00:00:00:33:33:33"
1643 )
Neale Rannsc819fc62018-02-16 02:44:05 -08001644
Neale Ranns59ae61e2018-06-07 18:09:49 -07001645 def test_garp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001646 """GARP"""
Neale Ranns59ae61e2018-06-07 18:09:49 -07001647
1648 #
1649 # Generate some hosts on the LAN
1650 #
1651 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001652 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001653
1654 #
1655 # And an ARP entry
1656 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001657 arp = VppNeighbor(
1658 self,
1659 self.pg1.sw_if_index,
1660 self.pg1.remote_hosts[1].mac,
1661 self.pg1.remote_hosts[1].ip4,
1662 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001663 arp.add_vpp_config()
1664
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001665 self.assertTrue(
1666 find_nbr(
1667 self,
1668 self.pg1.sw_if_index,
1669 self.pg1.remote_hosts[1].ip4,
1670 mac=self.pg1.remote_hosts[1].mac,
1671 )
1672 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001673
1674 #
1675 # Send a GARP (request) to swap the host 1's address to that of host 2
1676 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001677 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[2].mac) / ARP(
1678 op="who-has",
1679 hwdst=self.pg1.local_mac,
1680 hwsrc=self.pg1.remote_hosts[2].mac,
1681 pdst=self.pg1.remote_hosts[1].ip4,
1682 psrc=self.pg1.remote_hosts[1].ip4,
1683 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001684
1685 self.pg1.add_stream(p1)
1686 self.pg_enable_capture(self.pg_interfaces)
1687 self.pg_start()
1688
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001689 self.assertTrue(
1690 find_nbr(
1691 self,
1692 self.pg1.sw_if_index,
1693 self.pg1.remote_hosts[1].ip4,
1694 mac=self.pg1.remote_hosts[2].mac,
1695 )
1696 )
Neale Rannsfd2417b2021-07-16 14:00:16 +00001697 self.assert_equal(self.get_arp_rx_garp(self.pg1), 1)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001698
1699 #
1700 # Send a GARP (reply) to swap the host 1's address to that of host 3
1701 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001702 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1703 op="is-at",
1704 hwdst=self.pg1.local_mac,
1705 hwsrc=self.pg1.remote_hosts[3].mac,
1706 pdst=self.pg1.remote_hosts[1].ip4,
1707 psrc=self.pg1.remote_hosts[1].ip4,
1708 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001709
1710 self.pg1.add_stream(p1)
1711 self.pg_enable_capture(self.pg_interfaces)
1712 self.pg_start()
1713
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001714 self.assertTrue(
1715 find_nbr(
1716 self,
1717 self.pg1.sw_if_index,
1718 self.pg1.remote_hosts[1].ip4,
1719 mac=self.pg1.remote_hosts[3].mac,
1720 )
1721 )
Neale Rannsfd2417b2021-07-16 14:00:16 +00001722 self.assert_equal(self.get_arp_rx_garp(self.pg1), 2)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001723
1724 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001725 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001726 # don't result in new neighbour entries
1727 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001728 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1729 op="who-has",
1730 hwdst=self.pg1.local_mac,
1731 hwsrc=self.pg1.remote_hosts[3].mac,
1732 pdst=self.pg1.remote_hosts[2].ip4,
1733 psrc=self.pg1.remote_hosts[2].ip4,
1734 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001735
1736 self.pg1.add_stream(p1)
1737 self.pg_enable_capture(self.pg_interfaces)
1738 self.pg_start()
1739
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001740 self.assertFalse(
1741 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1742 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001743
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001744 p1 = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_hosts[3].mac) / ARP(
1745 op="is-at",
1746 hwdst=self.pg1.local_mac,
1747 hwsrc=self.pg1.remote_hosts[3].mac,
1748 pdst=self.pg1.remote_hosts[2].ip4,
1749 psrc=self.pg1.remote_hosts[2].ip4,
1750 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001751
1752 self.pg1.add_stream(p1)
1753 self.pg_enable_capture(self.pg_interfaces)
1754 self.pg_start()
1755
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001756 self.assertFalse(
1757 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].ip4)
1758 )
Neale Ranns59ae61e2018-06-07 18:09:49 -07001759
Neale Ranns22eefd72020-09-23 11:25:21 +00001760 #
1761 # IP address in different subnets are not learnt
1762 #
1763 self.pg2.configure_ipv4_neighbors()
1764
1765 for op in ["is-at", "who-has"]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001766 p1 = [
1767 (
1768 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1769 / ARP(
1770 op=op,
1771 hwdst=self.pg2.local_mac,
1772 hwsrc=self.pg2.remote_hosts[1].mac,
1773 pdst=self.pg2.remote_hosts[1].ip4,
1774 psrc=self.pg2.remote_hosts[1].ip4,
1775 )
1776 ),
1777 (
1778 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_hosts[1].mac)
1779 / ARP(
1780 op=op,
1781 hwdst="ff:ff:ff:ff:ff:ff",
1782 hwsrc=self.pg2.remote_hosts[1].mac,
1783 pdst=self.pg2.remote_hosts[1].ip4,
1784 psrc=self.pg2.remote_hosts[1].ip4,
1785 )
1786 ),
1787 ]
Neale Ranns22eefd72020-09-23 11:25:21 +00001788
1789 self.send_and_assert_no_replies(self.pg1, p1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001790 self.assertFalse(
1791 find_nbr(self, self.pg1.sw_if_index, self.pg2.remote_hosts[1].ip4)
1792 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001793
1794 # they are all dropped because the subnet's don't match
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001795 self.assertEqual(
1796 4,
Neale Ranns13a74ae2022-08-09 00:59:37 +00001797 self.statistics.get_err_counter("/err/arp-reply/l3_dst_address_not_local"),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001798 )
Neale Ranns22eefd72020-09-23 11:25:21 +00001799
Neale Ranns77f91622020-11-23 16:25:27 +00001800 def test_arp_incomplete2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001801 """Incomplete Entries"""
Neale Rannsc8352bc2018-08-29 10:23:58 -07001802
1803 #
Neale Rannscd35e532018-08-31 02:51:45 -07001804 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001805 #
1806 self.pg0.generate_remote_hosts(2)
1807
Neale Rannscd35e532018-08-31 02:51:45 -07001808 #
1809 # IPv4/ARP
1810 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001811 ip_10_0_0_1 = VppIpRoute(
1812 self,
1813 "10.0.0.1",
1814 32,
1815 [VppRoutePath(self.pg0.remote_hosts[1].ip4, self.pg0.sw_if_index)],
1816 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001817 ip_10_0_0_1.add_vpp_config()
1818
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001819 p1 = (
1820 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1821 / IP(src=self.pg1.remote_ip4, dst="10.0.0.1")
1822 / UDP(sport=1234, dport=1234)
1823 / Raw()
1824 )
Neale Rannsc8352bc2018-08-29 10:23:58 -07001825
1826 self.pg1.add_stream(p1 * 257)
1827 self.pg_enable_capture(self.pg_interfaces)
1828 self.pg_start()
1829 rx = self.pg0._get_capture(1)
1830
1831 #
1832 # how many we get is going to be dependent on the time for packet
1833 # processing but it should be small
1834 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001835 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001836
Neale Rannscd35e532018-08-31 02:51:45 -07001837 #
1838 # IPv6/ND
1839 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001840 ip_10_1 = VppIpRoute(
1841 self,
1842 "10::1",
1843 128,
1844 [
1845 VppRoutePath(
1846 self.pg0.remote_hosts[1].ip6,
1847 self.pg0.sw_if_index,
1848 proto=DpoProto.DPO_PROTO_IP6,
1849 )
1850 ],
1851 )
Neale Rannscd35e532018-08-31 02:51:45 -07001852 ip_10_1.add_vpp_config()
1853
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001854 p1 = (
1855 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1856 / IPv6(src=self.pg1.remote_ip6, dst="10::1")
1857 / UDP(sport=1234, dport=1234)
1858 / Raw()
1859 )
Neale Rannscd35e532018-08-31 02:51:45 -07001860
1861 self.pg1.add_stream(p1 * 257)
1862 self.pg_enable_capture(self.pg_interfaces)
1863 self.pg_start()
1864 rx = self.pg0._get_capture(1)
1865
1866 #
1867 # how many we get is going to be dependent on the time for packet
1868 # processing but it should be small
1869 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001870 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001871
Neale Ranns7425f922019-01-23 00:36:16 -08001872 def test_arp_forus(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001873 """ARP for for-us"""
Neale Ranns7425f922019-01-23 00:36:16 -08001874
1875 #
1876 # Test that VPP responds with ARP requests to addresses that
1877 # are connected and local routes.
1878 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001879 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001880 # address added to an interface
1881 #
1882 self.pg0.generate_remote_hosts(2)
1883
Neale Ranns097fa662018-05-01 05:17:55 -07001884 forus = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001885 self,
1886 self.pg0.remote_hosts[1].ip4,
1887 32,
1888 [
1889 VppRoutePath(
1890 "0.0.0.0",
1891 self.pg0.sw_if_index,
1892 type=FibPathType.FIB_PATH_TYPE_LOCAL,
1893 )
1894 ],
1895 )
Neale Ranns7425f922019-01-23 00:36:16 -08001896 forus.add_vpp_config()
1897
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001898 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
1899 op="who-has",
1900 hwdst=self.pg0.local_mac,
1901 hwsrc=self.pg0.remote_mac,
1902 pdst=self.pg0.remote_hosts[1].ip4,
1903 psrc=self.pg0.remote_ip4,
1904 )
Neale Ranns7425f922019-01-23 00:36:16 -08001905
1906 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1907
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001908 self.verify_arp_resp(
1909 rx[0],
1910 self.pg0.local_mac,
1911 self.pg0.remote_mac,
1912 self.pg0.remote_hosts[1].ip4,
1913 self.pg0.remote_ip4,
1914 )
Neale Ranns7425f922019-01-23 00:36:16 -08001915
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001916 def test_arp_table_swap(self):
1917 #
1918 # Generate some hosts on the LAN
1919 #
1920 N_NBRS = 4
1921 self.pg1.generate_remote_hosts(N_NBRS)
1922
1923 for n in range(N_NBRS):
1924 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001925 VppIpRoute(
1926 self,
1927 "10.0.0.%d" % n,
1928 32,
1929 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
1930 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001931
1932 # resolve each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001933 p1 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / ARP(
1934 op="is-at",
1935 hwdst=self.pg1.local_mac,
1936 hwsrc="00:00:5e:00:01:09",
1937 pdst=self.pg1.local_ip4,
1938 psrc=self.pg1.remote_hosts[n].ip4,
1939 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001940
1941 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1942
1943 self.logger.info(self.vapi.cli("sh ip neighbors"))
1944
1945 #
1946 # swap the table pg1 is in
1947 #
1948 table = VppIpTable(self, 100).add_vpp_config()
1949
1950 self.pg1.unconfig_ip4()
1951 self.pg1.set_table_ip4(100)
1952 self.pg1.config_ip4()
1953
1954 #
1955 # all neighbours are cleared
1956 #
1957 for n in range(N_NBRS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001958 self.assertFalse(
1959 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip4)
1960 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001961
1962 #
1963 # packets to all neighbours generate ARP requests
1964 #
1965 for n in range(N_NBRS):
1966 # a route thru each neighbour
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001967 VppIpRoute(
1968 self,
1969 "10.0.0.%d" % n,
1970 32,
1971 [VppRoutePath(self.pg1.remote_hosts[n].ip4, self.pg1.sw_if_index)],
1972 table_id=100,
1973 ).add_vpp_config()
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001974
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001975 p = (
1976 Ether(src=self.pg1.remote_hosts[n].mac, dst=self.pg1.local_mac)
1977 / IP(src=self.pg1.remote_hosts[n].ip4, dst="10.0.0.%d" % n)
1978 / Raw(b"0x5" * 100)
1979 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001980 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1981 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001982 self.verify_arp_req(
1983 rx,
1984 self.pg1.local_mac,
1985 self.pg1.local_ip4,
1986 self.pg1.remote_hosts[n].ip4,
1987 )
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001988
1989 self.pg1.unconfig_ip4()
1990 self.pg1.set_table_ip4(0)
1991
Neale Rannse2fe0972020-11-26 08:37:27 +00001992 def test_glean_src_select(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001993 """Multi Connecteds"""
Neale Rannse2fe0972020-11-26 08:37:27 +00001994
1995 #
1996 # configure multiple connected subnets on an interface
1997 # and ensure that ARP requests for hosts on those subnets
1998 # pick up the correct source address
1999 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002000 conn1 = VppIpInterfaceAddress(self, self.pg1, "10.0.0.1", 24).add_vpp_config()
2001 conn2 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.1", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002002
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002003 p1 = (
2004 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2005 / IP(src=self.pg1.remote_ip4, dst="10.0.0.128")
2006 / Raw(b"0x5" * 100)
2007 )
Neale Rannse2fe0972020-11-26 08:37:27 +00002008
2009 rxs = self.send_and_expect(self.pg0, [p1], self.pg1)
2010 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002011 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.0.1", "10.0.0.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002012
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002013 p2 = (
2014 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2015 / IP(src=self.pg1.remote_ip4, dst="10.0.1.128")
2016 / Raw(b"0x5" * 100)
2017 )
Neale Rannse2fe0972020-11-26 08:37:27 +00002018
2019 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2020 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002021 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002022
2023 #
2024 # add a local address in the same subnet
2025 # the source addresses are equivalent. VPP happens to
2026 # choose the last one that was added
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002027 conn3 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.2", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002028
2029 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2030 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002031 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002032
2033 #
2034 # remove
2035 #
2036 conn3.remove_vpp_config()
2037 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2038 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002039 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.1", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002040
2041 #
2042 # add back, this time remove the first one
2043 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002044 conn3 = VppIpInterfaceAddress(self, self.pg1, "10.0.1.2", 24).add_vpp_config()
Neale Rannse2fe0972020-11-26 08:37:27 +00002045
2046 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2047 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002048 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002049
2050 conn1.remove_vpp_config()
2051 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
2052 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002053 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Rannse2fe0972020-11-26 08:37:27 +00002054
Neale Ranns66edaf22021-07-09 13:03:52 +00002055 # apply a connected prefix to an interface in a different table
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002056 VppIpRoute(
2057 self,
2058 "10.0.1.0",
2059 24,
2060 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
2061 table_id=1,
2062 ).add_vpp_config()
Neale Ranns66edaf22021-07-09 13:03:52 +00002063
2064 rxs = self.send_and_expect(self.pg3, [p2], self.pg1)
2065 for rx in rxs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002066 self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
Neale Ranns66edaf22021-07-09 13:03:52 +00002067
Neale Rannse2fe0972020-11-26 08:37:27 +00002068 # cleanup
2069 conn3.remove_vpp_config()
2070 conn2.remove_vpp_config()
2071
Neale Rannsdcd6d622017-05-26 02:59:16 -07002072
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002073@tag_fixme_vpp_workers
Neale Ranns14260392018-09-28 05:00:57 -07002074class NeighborStatsTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002075 """ARP/ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002076
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002077 @classmethod
2078 def setUpClass(cls):
2079 super(NeighborStatsTestCase, cls).setUpClass()
2080
2081 @classmethod
2082 def tearDownClass(cls):
2083 super(NeighborStatsTestCase, cls).tearDownClass()
2084
Neale Ranns14260392018-09-28 05:00:57 -07002085 def setUp(self):
2086 super(NeighborStatsTestCase, self).setUp()
2087
2088 self.create_pg_interfaces(range(2))
2089
2090 # pg0 configured with ip4 and 6 addresses used for input
2091 # pg1 configured with ip4 and 6 addresses used for output
2092 # pg2 is unnumbered to pg0
2093 for i in self.pg_interfaces:
2094 i.admin_up()
2095 i.config_ip4()
2096 i.config_ip6()
2097 i.resolve_arp()
2098 i.resolve_ndp()
2099
2100 def tearDown(self):
2101 super(NeighborStatsTestCase, self).tearDown()
2102
2103 for i in self.pg_interfaces:
2104 i.unconfig_ip4()
2105 i.unconfig_ip6()
2106 i.admin_down()
2107
2108 def test_arp_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002109 """ARP Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002110
2111 self.vapi.cli("adj counters enable")
2112 self.pg1.generate_remote_hosts(2)
2113
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002114 arp1 = VppNeighbor(
2115 self,
2116 self.pg1.sw_if_index,
2117 self.pg1.remote_hosts[0].mac,
2118 self.pg1.remote_hosts[0].ip4,
2119 )
Neale Ranns14260392018-09-28 05:00:57 -07002120 arp1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002121 arp2 = VppNeighbor(
2122 self,
2123 self.pg1.sw_if_index,
2124 self.pg1.remote_hosts[1].mac,
2125 self.pg1.remote_hosts[1].ip4,
2126 )
Neale Ranns14260392018-09-28 05:00:57 -07002127 arp2.add_vpp_config()
2128
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002129 p1 = (
2130 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2131 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[0].ip4)
2132 / UDP(sport=1234, dport=1234)
2133 / Raw()
2134 )
2135 p2 = (
2136 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2137 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4)
2138 / UDP(sport=1234, dport=1234)
2139 / Raw()
2140 )
Neale Ranns14260392018-09-28 05:00:57 -07002141
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002142 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
2143 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07002144
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002145 self.assertEqual(NUM_PKTS, arp1.get_stats()["packets"])
2146 self.assertEqual(NUM_PKTS, arp2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002147
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002148 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002149 self.assertEqual(NUM_PKTS * 2, arp1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002150
2151 def test_nd_stats(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002152 """ND Counters"""
Neale Ranns14260392018-09-28 05:00:57 -07002153
2154 self.vapi.cli("adj counters enable")
2155 self.pg0.generate_remote_hosts(3)
2156
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002157 nd1 = VppNeighbor(
2158 self,
2159 self.pg0.sw_if_index,
2160 self.pg0.remote_hosts[1].mac,
2161 self.pg0.remote_hosts[1].ip6,
2162 )
Neale Ranns14260392018-09-28 05:00:57 -07002163 nd1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002164 nd2 = VppNeighbor(
2165 self,
2166 self.pg0.sw_if_index,
2167 self.pg0.remote_hosts[2].mac,
2168 self.pg0.remote_hosts[2].ip6,
2169 )
Neale Ranns14260392018-09-28 05:00:57 -07002170 nd2.add_vpp_config()
2171
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002172 p1 = (
2173 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2174 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[1].ip6)
2175 / UDP(sport=1234, dport=1234)
2176 / Raw()
2177 )
2178 p2 = (
2179 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2180 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.remote_hosts[2].ip6)
2181 / UDP(sport=1234, dport=1234)
2182 / Raw()
2183 )
Neale Ranns14260392018-09-28 05:00:57 -07002184
2185 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
2186 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
2187
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002188 self.assertEqual(16, nd1.get_stats()["packets"])
2189 self.assertEqual(16, nd2.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002190
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002191 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002192 self.assertEqual(NUM_PKTS + 16, nd1.get_stats()["packets"])
Neale Ranns14260392018-09-28 05:00:57 -07002193
2194
Neale Rannscbe25aa2019-09-30 10:53:31 +00002195class NeighborAgeTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002196 """ARP/ND Aging"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002197
2198 @classmethod
2199 def setUpClass(cls):
2200 super(NeighborAgeTestCase, cls).setUpClass()
2201
2202 @classmethod
2203 def tearDownClass(cls):
2204 super(NeighborAgeTestCase, cls).tearDownClass()
2205
2206 def setUp(self):
2207 super(NeighborAgeTestCase, self).setUp()
2208
2209 self.create_pg_interfaces(range(1))
2210
2211 # pg0 configured with ip4 and 6 addresses used for input
2212 # pg1 configured with ip4 and 6 addresses used for output
2213 # pg2 is unnumbered to pg0
2214 for i in self.pg_interfaces:
2215 i.admin_up()
2216 i.config_ip4()
2217 i.config_ip6()
2218 i.resolve_arp()
2219 i.resolve_ndp()
2220
2221 def tearDown(self):
2222 super(NeighborAgeTestCase, self).tearDown()
2223
2224 for i in self.pg_interfaces:
2225 i.unconfig_ip4()
2226 i.unconfig_ip6()
2227 i.admin_down()
2228
Neale Rannscbe25aa2019-09-30 10:53:31 +00002229 def verify_arp_req(self, rx, smac, sip, dip):
2230 ether = rx[Ether]
2231 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2232 self.assertEqual(ether.src, smac)
2233
2234 arp = rx[ARP]
2235 self.assertEqual(arp.hwtype, 1)
2236 self.assertEqual(arp.ptype, 0x800)
2237 self.assertEqual(arp.hwlen, 6)
2238 self.assertEqual(arp.plen, 4)
2239 self.assertEqual(arp.op, arp_opts["who-has"])
2240 self.assertEqual(arp.hwsrc, smac)
2241 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2242 self.assertEqual(arp.psrc, sip)
2243 self.assertEqual(arp.pdst, dip)
2244
2245 def test_age(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002246 """Aging/Recycle"""
Neale Rannscbe25aa2019-09-30 10:53:31 +00002247
2248 self.vapi.cli("set logging unthrottle 0")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002249 self.vapi.cli("set logging size %d" % 0xFFFF)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002250
2251 self.pg0.generate_remote_hosts(201)
2252
2253 vaf = VppEnum.vl_api_address_family_t
2254
2255 #
2256 # start listening on all interfaces
2257 #
2258 self.pg_enable_capture(self.pg_interfaces)
2259
2260 #
2261 # Set the neighbor configuration:
2262 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002263 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00002264 # recycle = false
2265 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002266 self.vapi.ip_neighbor_config(
2267 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2268 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002269
2270 self.vapi.cli("sh ip neighbor-config")
2271
2272 # add the 198 neighbours that should pass (-1 for one created in setup)
2273 for ii in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002274 VppNeighbor(
2275 self,
2276 self.pg0.sw_if_index,
2277 self.pg0.remote_hosts[ii].mac,
2278 self.pg0.remote_hosts[ii].ip4,
2279 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002280
2281 # one more neighbor over the limit should fail
2282 with self.vapi.assert_negative_api_retval():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002283 VppNeighbor(
2284 self,
2285 self.pg0.sw_if_index,
2286 self.pg0.remote_hosts[200].mac,
2287 self.pg0.remote_hosts[200].ip4,
2288 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002289
2290 #
2291 # change the config to allow recycling the old neighbors
2292 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002293 self.vapi.ip_neighbor_config(
2294 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=True
2295 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002296
2297 # now new additions are allowed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002298 VppNeighbor(
2299 self,
2300 self.pg0.sw_if_index,
2301 self.pg0.remote_hosts[200].mac,
2302 self.pg0.remote_hosts[200].ip4,
2303 ).add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +00002304
2305 # add the first neighbor we configured has been re-used
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002306 self.assertFalse(
2307 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2308 )
2309 self.assertTrue(
2310 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[200].ip4)
2311 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002312
2313 #
2314 # change the config to age old neighbors
2315 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002316 self.vapi.ip_neighbor_config(
2317 af=vaf.ADDRESS_IP4, max_number=200, max_age=2, recycle=True
2318 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002319
2320 self.vapi.cli("sh ip4 neighbor-sorted")
2321
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002322 # age out neighbors
2323 self.virtual_sleep(3)
2324
Neale Rannscbe25aa2019-09-30 10:53:31 +00002325 #
2326 # expect probes from all these ARP entries as they age
2327 # 3 probes for each neighbor 3*200 = 600
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002328 rxs = self.pg0.get_capture(600, timeout=2)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002329
2330 for ii in range(3):
2331 for jj in range(200):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002332 rx = rxs[ii * 200 + jj]
Neale Rannscbe25aa2019-09-30 10:53:31 +00002333 # rx.show()
2334
2335 #
2336 # 3 probes sent then 1 more second to see if a reply comes, before
2337 # they age out
2338 #
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002339 self.virtual_sleep(1)
Neale Rannscbe25aa2019-09-30 10:53:31 +00002340
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002341 self.assertFalse(
2342 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2343 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002344
2345 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002346 # load up some neighbours again with 2s aging enabled
2347 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002348 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002349 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002350 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2351
2352 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002353 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002354 VppNeighbor(
2355 self,
2356 self.pg0.sw_if_index,
2357 self.pg0.remote_hosts[ii].mac,
2358 self.pg0.remote_hosts[ii].ip4,
2359 ).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002360
2361 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002362 self.assertEqual(e.flags, enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2363 self.assertEqual(str(e.neighbor.ip_address), self.pg0.remote_hosts[ii].ip4)
2364 self.assertEqual(e.neighbor.mac_address, self.pg0.remote_hosts[ii].mac)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002365
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002366 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002367 self.assertFalse(
2368 self.vapi.ip_neighbor_dump(sw_if_index=0xFFFFFFFF, af=vaf.ADDRESS_IP4)
2369 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002370
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002371 evs = []
2372 for ii in range(10):
2373 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002374 self.assertEqual(e.flags, enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002375 evs.append(e)
2376
2377 # check we got the correct mac/ip pairs - done separately
2378 # because we don't care about the order the remove notifications
2379 # arrive
2380 for ii in range(10):
2381 found = False
2382 mac = self.pg0.remote_hosts[ii].mac
2383 ip = self.pg0.remote_hosts[ii].ip4
2384
2385 for e in evs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002386 if e.neighbor.mac_address == mac and str(e.neighbor.ip_address) == ip:
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002387 found = True
2388 break
2389 self.assertTrue(found)
2390
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002391 #
2392 # check if we can set age and recycle with empty neighbor list
2393 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002394 self.vapi.ip_neighbor_config(
2395 af=vaf.ADDRESS_IP4, max_number=200, max_age=1000, recycle=True
2396 )
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002397
2398 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002399 # load up some neighbours again, then disable the aging
2400 # they should still be there in 10 seconds time
2401 #
2402 for ii in range(10):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002403 VppNeighbor(
2404 self,
2405 self.pg0.sw_if_index,
2406 self.pg0.remote_hosts[ii].mac,
2407 self.pg0.remote_hosts[ii].ip4,
2408 ).add_vpp_config()
2409 self.vapi.ip_neighbor_config(
2410 af=vaf.ADDRESS_IP4, max_number=200, max_age=0, recycle=False
2411 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002412
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002413 self.virtual_sleep(10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002414 self.assertTrue(
2415 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[0].ip4)
2416 )
Neale Rannscbe25aa2019-09-30 10:53:31 +00002417
2418
Neale Rannsc87fbb42020-04-02 17:08:28 +00002419class NeighborReplaceTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002420 """ARP/ND Replacement"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002421
2422 @classmethod
2423 def setUpClass(cls):
2424 super(NeighborReplaceTestCase, cls).setUpClass()
2425
2426 @classmethod
2427 def tearDownClass(cls):
2428 super(NeighborReplaceTestCase, cls).tearDownClass()
2429
2430 def setUp(self):
2431 super(NeighborReplaceTestCase, self).setUp()
2432
2433 self.create_pg_interfaces(range(4))
2434
2435 # pg0 configured with ip4 and 6 addresses used for input
2436 # pg1 configured with ip4 and 6 addresses used for output
2437 # pg2 is unnumbered to pg0
2438 for i in self.pg_interfaces:
2439 i.admin_up()
2440 i.config_ip4()
2441 i.config_ip6()
2442 i.resolve_arp()
2443 i.resolve_ndp()
2444
2445 def tearDown(self):
2446 super(NeighborReplaceTestCase, self).tearDown()
2447
2448 for i in self.pg_interfaces:
2449 i.unconfig_ip4()
2450 i.unconfig_ip6()
2451 i.admin_down()
2452
2453 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002454 """replace"""
Neale Rannsc87fbb42020-04-02 17:08:28 +00002455
2456 N_HOSTS = 16
2457
2458 for i in self.pg_interfaces:
2459 i.generate_remote_hosts(N_HOSTS)
2460 i.configure_ipv4_neighbors()
2461 i.configure_ipv6_neighbors()
2462
2463 # replace them all
2464 self.vapi.ip_neighbor_replace_begin()
2465 self.vapi.ip_neighbor_replace_end()
2466
2467 for i in self.pg_interfaces:
2468 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002469 self.assertFalse(
2470 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip4)
2471 )
2472 self.assertFalse(
2473 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[h].ip6)
2474 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002475
2476 #
2477 # and them all back via the API
2478 #
2479 for i in self.pg_interfaces:
2480 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002481 VppNeighbor(
2482 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip4
2483 ).add_vpp_config()
2484 VppNeighbor(
2485 self, i.sw_if_index, i.remote_hosts[h].mac, i.remote_hosts[h].ip6
2486 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002487
2488 #
2489 # begin the replacement again, this time touch some
2490 # the neighbours on pg1 so they are not deleted
2491 #
2492 self.vapi.ip_neighbor_replace_begin()
2493
2494 # update from the API all neighbours on pg1
2495 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002496 VppNeighbor(
2497 self,
2498 self.pg1.sw_if_index,
2499 self.pg1.remote_hosts[h].mac,
2500 self.pg1.remote_hosts[h].ip4,
2501 ).add_vpp_config()
2502 VppNeighbor(
2503 self,
2504 self.pg1.sw_if_index,
2505 self.pg1.remote_hosts[h].mac,
2506 self.pg1.remote_hosts[h].ip6,
2507 ).add_vpp_config()
Neale Rannsc87fbb42020-04-02 17:08:28 +00002508
2509 # update from the data-plane all neighbours on pg3
2510 self.pg3.configure_ipv4_neighbors()
2511 self.pg3.configure_ipv6_neighbors()
2512
2513 # complete the replacement
2514 self.logger.info(self.vapi.cli("sh ip neighbors"))
2515 self.vapi.ip_neighbor_replace_end()
2516
2517 for i in self.pg_interfaces:
2518 if i == self.pg1 or i == self.pg3:
2519 # neighbours on pg1 and pg3 are still present
2520 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002521 self.assertTrue(
2522 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2523 )
2524 self.assertTrue(
2525 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2526 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002527 else:
2528 # all other neighbours are toast
2529 for h in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002530 self.assertFalse(
2531 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip4)
2532 )
2533 self.assertFalse(
2534 find_nbr(self, i.sw_if_index, i.remote_hosts[h].ip6)
2535 )
Neale Rannsc87fbb42020-04-02 17:08:28 +00002536
2537
Neale Ranns240dcb22020-04-23 09:04:59 +00002538class NeighborFlush(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002539 """Neighbor Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002540
2541 @classmethod
2542 def setUpClass(cls):
2543 super(NeighborFlush, cls).setUpClass()
2544
2545 @classmethod
2546 def tearDownClass(cls):
2547 super(NeighborFlush, cls).tearDownClass()
2548
2549 def setUp(self):
2550 super(NeighborFlush, self).setUp()
2551
2552 self.create_pg_interfaces(range(2))
2553
2554 for i in self.pg_interfaces:
2555 i.admin_up()
2556 i.config_ip4()
2557 i.config_ip6()
2558 i.resolve_arp()
2559 i.resolve_ndp()
2560
2561 def tearDown(self):
2562 super(NeighborFlush, self).tearDown()
2563
2564 for i in self.pg_interfaces:
2565 i.unconfig_ip4()
2566 i.unconfig_ip6()
2567 i.admin_down()
2568
2569 def test_flush(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002570 """Neighbour Flush"""
Neale Ranns240dcb22020-04-23 09:04:59 +00002571
2572 e = VppEnum
2573 nf = e.vl_api_ip_neighbor_flags_t
2574 af = e.vl_api_address_family_t
2575 N_HOSTS = 16
2576 static = [False, True]
2577 self.pg0.generate_remote_hosts(N_HOSTS)
2578 self.pg1.generate_remote_hosts(N_HOSTS)
2579
2580 for s in static:
2581 # a few v4 and v6 dynamic neoghbors
2582 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002583 VppNeighbor(
2584 self,
2585 self.pg0.sw_if_index,
2586 self.pg0.remote_hosts[n].mac,
2587 self.pg0.remote_hosts[n].ip4,
2588 is_static=s,
2589 ).add_vpp_config()
2590 VppNeighbor(
2591 self,
2592 self.pg1.sw_if_index,
2593 self.pg1.remote_hosts[n].mac,
2594 self.pg1.remote_hosts[n].ip6,
2595 is_static=s,
2596 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002597
2598 # flush the interfaces individually
2599 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2600
2601 # check we haven't flushed that which we shouldn't
2602 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002603 self.assertTrue(
2604 find_nbr(
2605 self,
2606 self.pg1.sw_if_index,
2607 self.pg1.remote_hosts[n].ip6,
2608 is_static=s,
2609 )
2610 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002611
2612 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2613
2614 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002615 self.assertFalse(
2616 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2617 )
2618 self.assertFalse(
2619 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2620 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002621
2622 # add the nieghbours back
2623 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002624 VppNeighbor(
2625 self,
2626 self.pg0.sw_if_index,
2627 self.pg0.remote_hosts[n].mac,
2628 self.pg0.remote_hosts[n].ip4,
2629 is_static=s,
2630 ).add_vpp_config()
2631 VppNeighbor(
2632 self,
2633 self.pg1.sw_if_index,
2634 self.pg1.remote_hosts[n].mac,
2635 self.pg1.remote_hosts[n].ip6,
2636 is_static=s,
2637 ).add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +00002638
2639 self.logger.info(self.vapi.cli("sh ip neighbor"))
2640
2641 # flush both interfaces at the same time
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002642 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002643
2644 # check we haven't flushed that which we shouldn't
2645 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002646 self.assertTrue(
2647 find_nbr(
2648 self,
2649 self.pg0.sw_if_index,
2650 self.pg0.remote_hosts[n].ip4,
2651 is_static=s,
2652 )
2653 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002654
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002655 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xFFFFFFFF)
Neale Ranns240dcb22020-04-23 09:04:59 +00002656
2657 for n in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002658 self.assertFalse(
2659 find_nbr(self, self.pg0.sw_if_index, self.pg0.remote_hosts[n].ip4)
2660 )
2661 self.assertFalse(
2662 find_nbr(self, self.pg1.sw_if_index, self.pg1.remote_hosts[n].ip6)
2663 )
Neale Ranns240dcb22020-04-23 09:04:59 +00002664
2665
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002666if __name__ == "__main__":
Neale Ranns37be7362017-02-21 17:30:26 -08002667 unittest.main(testRunner=VppTestRunner)