summaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/interface_api.c133
-rw-r--r--src/vnet/ip/ip.h2
-rw-r--r--src/vnet/ip/ip4_forward.c9
-rw-r--r--src/vnet/ip/ip6_forward.c9
4 files changed, 99 insertions, 54 deletions
diff --git a/src/vnet/interface_api.c b/src/vnet/interface_api.c
index bbb6168df9e..a765c0bbc3d 100644
--- a/src/vnet/interface_api.c
+++ b/src/vnet/interface_api.c
@@ -470,41 +470,17 @@ vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp)
REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
}
-int
-ip_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 table_id)
+void
+fib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 fib_index)
{
- CLIB_UNUSED (ip_interface_address_t * ia);
- u32 fib_index, mfib_index;
+ u32 table_id;
- /*
- * This if table does not exist = error is what we want in the end.
- */
- fib_index = fib_table_find (fproto, table_id);
- mfib_index = mfib_table_find (fproto, table_id);
-
- if (~0 == fib_index || ~0 == mfib_index)
- {
- return (VNET_API_ERROR_NO_SUCH_FIB);
- }
+ table_id = fib_table_get_table_id (fib_index, fproto);
+ ASSERT (table_id != ~0);
if (FIB_PROTOCOL_IP6 == fproto)
{
/*
- * If the interface already has in IP address, then a change int
- * VRF is not allowed. The IP address applied must first be removed.
- * We do not do that automatically here, since VPP has no knowledge
- * of whether those subnets are valid in the destination VRF.
- */
- /* *INDENT-OFF* */
- foreach_ip_interface_address (&ip6_main.lookup_main,
- ia, sw_if_index,
- 1 /* honor unnumbered */ ,
- ({
- return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
- }));
- /* *INDENT-ON* */
-
- /*
* tell those that are interested that the binding is changing.
*/
ip6_table_bind_callback_t *cb;
@@ -518,39 +494,18 @@ ip_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 table_id)
if (0 != ip6_main.fib_index_by_sw_if_index[sw_if_index])
fib_table_unlock (ip6_main.fib_index_by_sw_if_index[sw_if_index],
FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
- if (0 != ip6_main.mfib_index_by_sw_if_index[sw_if_index])
- mfib_table_unlock (ip6_main.mfib_index_by_sw_if_index[sw_if_index],
- FIB_PROTOCOL_IP6, MFIB_SOURCE_INTERFACE);
if (0 != table_id)
{
/* we need to lock the table now it's inuse */
fib_table_lock (fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
- mfib_table_lock (mfib_index, FIB_PROTOCOL_IP6,
- MFIB_SOURCE_INTERFACE);
}
ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
- ip6_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
}
else
{
/*
- * If the interface already has in IP address, then a change int
- * VRF is not allowed. The IP address applied must first be removed.
- * We do not do that automatically here, since VPP has no knowledge
- * of whether those subnets are valid in the destination VRF.
- */
- /* *INDENT-OFF* */
- foreach_ip_interface_address (&ip4_main.lookup_main,
- ia, sw_if_index,
- 1 /* honor unnumbered */ ,
- ({
- return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
- }));
- /* *INDENT-ON* */
-
- /*
* tell those that are interested that the binding is changing.
*/
ip4_table_bind_callback_t *cb;
@@ -564,23 +519,93 @@ ip_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 table_id)
if (0 != ip4_main.fib_index_by_sw_if_index[sw_if_index])
fib_table_unlock (ip4_main.fib_index_by_sw_if_index[sw_if_index],
FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
- if (0 != ip4_main.mfib_index_by_sw_if_index[sw_if_index])
- mfib_table_unlock (ip4_main.mfib_index_by_sw_if_index[sw_if_index],
- FIB_PROTOCOL_IP4, MFIB_SOURCE_INTERFACE);
if (0 != table_id)
{
/* we need to lock the table now it's inuse */
fib_index = fib_table_find_or_create_and_lock (
FIB_PROTOCOL_IP4, table_id, FIB_SOURCE_INTERFACE);
+ }
+
+ ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
+ }
+}
+
+void
+mfib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 mfib_index)
+{
+ u32 table_id;
+
+ table_id = mfib_table_get_table_id (mfib_index, fproto);
+ ASSERT (table_id != ~0);
+
+ if (FIB_PROTOCOL_IP6 == fproto)
+ {
+ if (0 != ip6_main.mfib_index_by_sw_if_index[sw_if_index])
+ mfib_table_unlock (ip6_main.mfib_index_by_sw_if_index[sw_if_index],
+ FIB_PROTOCOL_IP6, MFIB_SOURCE_INTERFACE);
+ if (0 != table_id)
+ {
+ /* we need to lock the table now it's inuse */
+ mfib_table_lock (mfib_index, FIB_PROTOCOL_IP6,
+ MFIB_SOURCE_INTERFACE);
+ }
+
+ ip6_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
+ }
+ else
+ {
+ if (0 != ip4_main.mfib_index_by_sw_if_index[sw_if_index])
+ mfib_table_unlock (ip4_main.mfib_index_by_sw_if_index[sw_if_index],
+ FIB_PROTOCOL_IP4, MFIB_SOURCE_INTERFACE);
+
+ if (0 != table_id)
+ {
+ /* we need to lock the table now it's inuse */
mfib_index = mfib_table_find_or_create_and_lock (
FIB_PROTOCOL_IP4, table_id, MFIB_SOURCE_INTERFACE);
}
- ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
ip4_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
}
+}
+
+int
+ip_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 table_id)
+{
+ CLIB_UNUSED (ip_interface_address_t * ia);
+ u32 fib_index, mfib_index;
+
+ /*
+ * This if table does not exist = error is what we want in the end.
+ */
+ fib_index = fib_table_find (fproto, table_id);
+ mfib_index = mfib_table_find (fproto, table_id);
+
+ if (~0 == fib_index || ~0 == mfib_index)
+ {
+ return (VNET_API_ERROR_NO_SUCH_FIB);
+ }
+
+ /*
+ * If the interface already has in IP address, then a change int
+ * VRF is not allowed. The IP address applied must first be removed.
+ * We do not do that automatically here, since VPP has no knowledge
+ * of whether those subnets are valid in the destination VRF.
+ */
+ /* clang-format off */
+ foreach_ip_interface_address (FIB_PROTOCOL_IP6 == fproto ?
+ &ip6_main.lookup_main : &ip4_main.lookup_main,
+ ia, sw_if_index,
+ 1 /* honor unnumbered */ ,
+ ({
+ return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
+ }));
+ /* clang-format on */
+
+ fib_table_bind (fproto, sw_if_index, fib_index);
+ mfib_table_bind (fproto, sw_if_index, mfib_index);
return (0);
}
diff --git a/src/vnet/ip/ip.h b/src/vnet/ip/ip.h
index 131d6879c14..c2a38016ba5 100644
--- a/src/vnet/ip/ip.h
+++ b/src/vnet/ip/ip.h
@@ -267,6 +267,8 @@ void ip_table_create (fib_protocol_t fproto, u32 table_id, u8 is_api,
void ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api);
+void fib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 fib_index);
+void mfib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 mfib_index);
int ip_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 table_id);
u32 ip_table_get_unused_id (fib_protocol_t fproto);
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index 58af706e2b2..de8e8e8538f 100644
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -1090,6 +1090,15 @@ ip4_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
}));
/* *INDENT-ON* */
ip4_mfib_interface_enable_disable (sw_if_index, 0);
+
+ if (0 != im4->fib_index_by_sw_if_index[sw_if_index])
+ fib_table_bind (FIB_PROTOCOL_IP4, sw_if_index, 0);
+ if (0 != im4->mfib_index_by_sw_if_index[sw_if_index])
+ mfib_table_bind (FIB_PROTOCOL_IP4, sw_if_index, 0);
+
+ /* Erase the lookup tables just in case */
+ im4->fib_index_by_sw_if_index[sw_if_index] = ~0;
+ im4->mfib_index_by_sw_if_index[sw_if_index] = ~0;
}
vnet_feature_enable_disable ("ip4-unicast", "ip4-not-enabled", sw_if_index,
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index 833ce142999..9ee3d11cef2 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -717,6 +717,15 @@ ip6_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
}));
/* *INDENT-ON* */
ip6_mfib_interface_enable_disable (sw_if_index, 0);
+
+ if (0 != im6->fib_index_by_sw_if_index[sw_if_index])
+ fib_table_bind (FIB_PROTOCOL_IP6, sw_if_index, 0);
+ if (0 != im6->mfib_index_by_sw_if_index[sw_if_index])
+ mfib_table_bind (FIB_PROTOCOL_IP6, sw_if_index, 0);
+
+ /* Erase the lookup tables just in case */
+ im6->fib_index_by_sw_if_index[sw_if_index] = ~0;
+ im6->mfib_index_by_sw_if_index[sw_if_index] = ~0;
}
vnet_feature_enable_disable ("ip6-unicast", "ip6-not-enabled", sw_if_index,