aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vnet/fib/fib_entry_src_adj.c34
-rw-r--r--src/vnet/fib/fib_test.c67
-rw-r--r--test/test_neighbor.py73
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 """