diff options
-rw-r--r-- | src/vnet/fib/fib_entry_src_adj.c | 34 | ||||
-rw-r--r-- | src/vnet/fib/fib_test.c | 67 | ||||
-rw-r--r-- | test/test_neighbor.py | 73 |
3 files changed, 150 insertions, 24 deletions
diff --git a/src/vnet/fib/fib_entry_src_adj.c b/src/vnet/fib/fib_entry_src_adj.c index 64f82a73e07..9990223037a 100644 --- a/src/vnet/fib/fib_entry_src_adj.c +++ b/src/vnet/fib/fib_entry_src_adj.c @@ -48,7 +48,7 @@ fib_entry_src_adj_remove (fib_entry_src_t *src) /* * Source activate. - * Called when the source is teh new longer best source on the entry + * Called when the source is the new longer best source on the entry */ static int fib_entry_src_adj_activate (fib_entry_src_t *src, @@ -75,8 +75,8 @@ fib_entry_src_adj_activate (fib_entry_src_t *src, fib_entry_get_index(fib_entry)); /* - * if the ocver is attached then this adj source entry can install, - * via the adj. otherwise install a drop. + * if the cover is attached on the same interface as this adj source then + * install the FIB entry via the adj. otherwise install a drop. * This prevents ARP/ND entries that on interface X that do not belong * on X's subnet from being added to the FIB. To do so would allow * nefarious gratuitous ARP requests from attracting traffic to the sender. @@ -86,7 +86,33 @@ fib_entry_src_adj_activate (fib_entry_src_t *src, * ip route add 10.0.0.0/24 Eth0 * is attached. and we want adj-fibs to install on Eth0. */ - return (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover)); + if (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover)) + { + u32 cover_itf = fib_entry_get_resolving_interface(src->adj.fesa_cover); + u32 adj_itf = fib_path_list_get_resolving_interface(src->fes_pl); + + if (cover_itf == adj_itf) + { + return (1); + } + else + { + /* + * if the interface the adj is on is unnumbered to the + * cover's, then allow that too. + */ + vnet_sw_interface_t *swif; + + swif = vnet_get_sw_interface (vnet_get_main(), adj_itf); + + if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED && + cover_itf == swif->unnumbered_sw_if_index) + { + return (1); + } + } + } + return (0); } /* diff --git a/src/vnet/fib/fib_test.c b/src/vnet/fib/fib_test.c index 1c4a63a20d9..1a9cce241d5 100644 --- a/src/vnet/fib/fib_test.c +++ b/src/vnet/fib/fib_test.c @@ -3557,6 +3557,73 @@ fib_test_v4 (void) fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT); /* + * An adj-fib that fails the refinement criteria - no connected cover + */ + fib_prefix_t pfx_12_10_10_2_s_32 = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = { + /* 12.10.10.2 */ + .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02), + }, + }; + + fib_table_entry_update_one_path(fib_index, + &pfx_12_10_10_2_s_32, + FIB_SOURCE_ADJ, + FIB_ENTRY_FLAG_ATTACHED, + FIB_PROTOCOL_IP4, + &pfx_12_10_10_2_s_32.fp_addr, + tm->hw[0]->sw_if_index, + ~0, // invalid fib index + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + + fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32); + dpo = fib_entry_contribute_ip_forwarding(fei); + FIB_TEST(!dpo_id_is_valid(dpo), + "no connected cover adj-fib fails refinement"); + + fib_table_entry_delete(fib_index, + &pfx_12_10_10_2_s_32, + FIB_SOURCE_ADJ); + + /* + * An adj-fib that fails the refinement criteria - cover is connected + * but on a different interface + */ + fib_prefix_t pfx_10_10_10_127_s_32 = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr = { + /* 10.10.10.127 */ + .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f), + }, + }; + + fib_table_entry_update_one_path(fib_index, + &pfx_10_10_10_127_s_32, + FIB_SOURCE_ADJ, + FIB_ENTRY_FLAG_ATTACHED, + FIB_PROTOCOL_IP4, + &pfx_10_10_10_127_s_32.fp_addr, + tm->hw[1]->sw_if_index, + ~0, // invalid fib index + 1, + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + + fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32); + dpo = fib_entry_contribute_ip_forwarding(fei); + FIB_TEST(!dpo_id_is_valid(dpo), + "wrong interface adj-fib fails refinement"); + + fib_table_entry_delete(fib_index, + &pfx_10_10_10_127_s_32, + FIB_SOURCE_ADJ); + + /* * CLEANUP * remove adj-fibs: */ diff --git a/test/test_neighbor.py b/test/test_neighbor.py index 1dfae241faf..a97a63fc7a6 100644 --- a/test/test_neighbor.py +++ b/test/test_neighbor.py @@ -115,7 +115,7 @@ class ARPTestCase(VppTestCase): # # Generate some hosts on the LAN # - self.pg1.generate_remote_hosts(5) + self.pg1.generate_remote_hosts(6) # # Send IP traffic to one of these unresolved hosts. @@ -251,6 +251,57 @@ class ARPTestCase(VppTestCase): self.pg1._remote_hosts[3].ip4)) # + # A neighbor entry that has no associated FIB-entry + # + arp_no_fib = VppNeighbor(self, + self.pg1.sw_if_index, + self.pg1.remote_hosts[4].mac, + self.pg1.remote_hosts[4].ip4, + is_no_fib_entry=1) + arp_no_fib.add_vpp_config() + + # + # check we have the neighbor, but no route + # + self.assertTrue(find_nbr(self, + self.pg1.sw_if_index, + self.pg1._remote_hosts[4].ip4)) + self.assertFalse(find_route(self, + self.pg1._remote_hosts[4].ip4, + 32)) + # + # Unnumbered pg2 to pg1 + # + self.pg2.set_unnumbered(self.pg1.sw_if_index) + + # + # now we can form adjacencies out of pg2 from within pg1's subnet + # + arp_unnum = VppNeighbor(self, + self.pg2.sw_if_index, + self.pg1.remote_hosts[5].mac, + self.pg1.remote_hosts[5].ip4) + arp_unnum.add_vpp_config() + + p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / + IP(src=self.pg0.remote_ip4, + dst=self.pg1._remote_hosts[5].ip4) / + UDP(sport=1234, dport=1234) / + Raw()) + + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg2.get_capture(1) + + self.verify_ip(rx[0], + self.pg2.local_mac, + self.pg1.remote_hosts[5].mac, + self.pg0.remote_ip4, + self.pg1._remote_hosts[5].ip4) + + # # ERROR Cases # 1 - don't respond to ARP request for address not within the # interface's sub-net @@ -301,29 +352,11 @@ class ARPTestCase(VppTestCase): "ARP req for non-local source") # - # A neighbor entry that has no associated FIB-entry - # - arp_no_fib = VppNeighbor(self, - self.pg1.sw_if_index, - self.pg1.remote_hosts[4].mac, - self.pg1.remote_hosts[4].ip4, - is_no_fib_entry=1) - arp_no_fib.add_vpp_config() - - # - # check we have the neighbor, but no route - # - self.assertTrue(find_nbr(self, - self.pg1.sw_if_index, - self.pg1._remote_hosts[4].ip4)) - self.assertFalse(find_route(self, - self.pg1._remote_hosts[4].ip4, - 32)) - # # cleanup # dyn_arp.remove_vpp_config() static_arp.remove_vpp_config() + self.pg2.unset_unnumbered(self.pg1.sw_if_index) def test_proxy_arp(self): """ Proxy ARP """ |