From 2a7bc81ae302b02e8e0d4eec7db82c1ca15b7f7a Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Fri, 8 Mar 2024 09:27:40 +0100 Subject: vnet: fix ARP for unnumbered On unnumbered interfaces, ARP fails because there is no attached route. Allow replies to peer-to-peer addresses on unnumbered interfaces: eg. 192.0.2.1/32 <-> 192.0.2.2/32 Type: fix Change-Id: Ibeb8d8ebc8d58d5bfb0724739a17694e0217356e Signed-off-by: Pim van Pelt --- src/vnet/arp/arp.c | 29 ++++++++++++++--------------- test/test_neighbor.py | 22 ++++++++++++++++------ 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/vnet/arp/arp.c b/src/vnet/arp/arp.c index cacdd71e381..43b2a93a7b3 100644 --- a/src/vnet/arp/arp.c +++ b/src/vnet/arp/arp.c @@ -423,6 +423,10 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) } + dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0), + &arp0->ip4_over_ethernet[1].ip4, 32); + conn_sw_if_index0 = fib_entry_get_any_resolving_interface (dst_fei); + { /* * we're looking for FIB entries that indicate the source @@ -509,24 +513,20 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) while (!attached && !fib_entry_is_sourced (src_fei, FIB_SOURCE_DEFAULT_ROUTE)); - if (!attached) + if (!attached && + !arp_unnumbered (p0, sw_if_index0, conn_sw_if_index0)) { /* - * the matching route is a not attached, i.e. it was - * added as a result of routing, rather than interface/ARP - * configuration. If the matching route is not a host route - * (i.e. a /32) + * the matching route is a not attached and not unnumbered, + * i.e. it was added as a result of routing, rather than + * interface/ARP configuration. If the matching route is not + * a host route (i.e. a /32) */ error0 = ARP_ERROR_L3_SRC_ADDRESS_NOT_LOCAL; goto drop; } } - dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0), - &arp0->ip4_over_ethernet[1].ip4, - 32); - conn_sw_if_index0 = fib_entry_get_any_resolving_interface (dst_fei); - switch (arp_dst_fib_check (dst_fei, &dst_flags)) { case ARP_DST_FIB_ADJ: @@ -619,9 +619,9 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) sw_if_index0 != fib_entry_get_resolving_interface (src_fei)) { /* - * The interface the ARP is sent to or was received on is not the - * interface on which the covering prefix is configured. - * Maybe this is a case for unnumbered. + * The interface the ARP is sent to or was received on is + * not the interface on which the covering prefix is + * configured. Maybe this is a case for unnumbered. */ if (!arp_unnumbered (p0, sw_if_index0, conn_sw_if_index0)) { @@ -636,8 +636,7 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) goto drop; } - next0 = arp_mk_reply (vnm, p0, sw_if_index0, - if_addr0, arp0, eth_rx); + next0 = arp_mk_reply (vnm, p0, sw_if_index0, if_addr0, arp0, eth_rx); /* We are going to reply to this request, so, in the absence of errors, learn the sender */ diff --git a/test/test_neighbor.py b/test/test_neighbor.py index 7338eff86d3..6fcf13f8261 100644 --- a/test/test_neighbor.py +++ b/test/test_neighbor.py @@ -432,14 +432,24 @@ class ARPTestCase(VppTestCase): self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index) self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index) - # - # We should respond to ARP requests for the unnumbered to address - # once an attached route to the source is known - # - self.send_and_assert_no_replies( - self.pg2, p, "ARP req for unnumbered address - no source" + # Allow for ARP requests from point-to-point ethernet neighbors + # without an attached route on pg2 + self.pg2.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg2.get_capture(1) + self.verify_arp_resp( + rx[0], + self.pg2.local_mac, + self.pg2.remote_mac, + self.pg1.local_ip4, + self.pg2.remote_hosts[3].ip4, ) + # + # Allow for ARP requests from neighbors on unnumbered with + # an attached route on pg2 attached_host = VppIpRoute( self, self.pg2.remote_hosts[3].ip4, -- cgit 1.2.3-korg