From: Artem Glazychev Date: Mon, 18 Aug 2025 04:18:05 +0000 (+0700) Subject: fib: change the order of adding interface routes X-Git-Tag: v26.02-rc0~63 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F89%2F43589%2F2;p=vpp.git fib: change the order of adding interface routes The order in which fib_table_entry is added affects the update of adjacency. If you assign a /31 address to the interface, an ARP request is sent to the peer with the source address from the glean adjacency, which is incorrect before adding the local address route. Steps to reproduce the problem: create tap set interface state tap0 up set interface ip address tap0 192.168.100.1/31 In this case, ARP-Request was sent with an incorrect sender IP: Sender IP Address: 192.168.100.0 Target IP Address: 192.168.100.0 Type: fix Change-Id: I8712bcf9fd0cb96788fe4a6c4b4827af774c0ab9 Signed-off-by: Artem Glazychev --- diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index 4760e29a6f3..fb96159b4c7 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -452,9 +452,6 @@ ip4_add_interface_routes (u32 sw_if_index, .fp_addr.ip4 = *address, }; - /* set special routes for the prefix if needed */ - ip4_add_interface_prefix_routes (im, sw_if_index, fib_index, a); - if (sw_if_index < vec_len (lm->classify_table_index_by_sw_if_index)) { u32 classify_table_index = @@ -487,6 +484,10 @@ ip4_add_interface_routes (u32 sw_if_index, ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE); + + /* set special routes for the prefix if needed */ + if (a->address_length < 32) + ip4_add_interface_prefix_routes (im, sw_if_index, fib_index, a); } static void diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c index 803396f583c..1a77bd702c4 100644 --- a/src/vnet/ip/ip6_forward.c +++ b/src/vnet/ip/ip6_forward.c @@ -132,10 +132,6 @@ ip6_add_interface_routes (vnet_main_t * vnm, u32 sw_if_index, .fp_addr.ip6 = *address, }; - /* set special routes for the prefix if needed */ - ip6_add_interface_prefix_routes (im, sw_if_index, fib_index, - address, a->address_length); - pfx.fp_len = 128; if (sw_if_index < vec_len (lm->classify_table_index_by_sw_if_index)) { @@ -166,6 +162,11 @@ ip6_add_interface_routes (vnet_main_t * vnm, u32 sw_if_index, &pfx.fp_addr, sw_if_index, ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE); + + /* set special routes for the prefix if needed */ + if (a->address_length < 128) + ip6_add_interface_prefix_routes (im, sw_if_index, fib_index, address, + a->address_length); } static void diff --git a/test/test_ip4.py b/test/test_ip4.py index 9d5db0d38cb..5f8aafad47d 100644 --- a/test/test_ip4.py +++ b/test/test_ip4.py @@ -1194,11 +1194,33 @@ class TestIPSubNets(VppTestCase): # A /31 is a special case where the 'other-side' is an attached host # packets to that peer generate ARP requests # - ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10") + # Let's consider two cases: + # Case 1: interface has the second address of /31 + # + self.pg_enable_capture(self.pg_interfaces) + self.vapi.sw_interface_add_del_address( + sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.11/31" + ) + + rx = self.pg0.get_capture(1) + self.assertEqual(rx[0][ARP].psrc, "10.10.10.11") + self.assertEqual(rx[0][ARP].pdst, "10.10.10.10") + # remove the sub-net + self.vapi.sw_interface_add_del_address( + sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.11/31", is_add=0 + ) + + # + # Case 2: interface has the first address of /31 + # + self.pg_enable_capture(self.pg_interfaces) self.vapi.sw_interface_add_del_address( sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/31" ) + rx = self.pg0.get_capture(1) + self.assertEqual(rx[0][ARP].psrc, "10.10.10.10") + self.assertEqual(rx[0][ARP].pdst, "10.10.10.11") pn = ( Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) @@ -1211,7 +1233,8 @@ class TestIPSubNets(VppTestCase): self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg0.get_capture(1) - rx[ARP] + self.assertEqual(rx[0][ARP].psrc, "10.10.10.10") + self.assertEqual(rx[0][ARP].pdst, "10.10.10.11") # remove the sub-net and we are forwarding via the cover again self.vapi.sw_interface_add_del_address(