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 <pim@ipng.nl>
This commit is contained in:
Pim van Pelt
2024-03-08 09:27:40 +01:00
committed by Neale Ranns
parent 0bfce6b724
commit 2a7bc81ae3
2 changed files with 30 additions and 21 deletions

View File

@ -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 */

View File

@ -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,