summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2017-09-10 04:39:11 -0700
committerDamjan Marion <dmarion.lists@gmail.com>2017-09-11 10:14:36 +0000
commit1500254bee11355bbd69cc1dd9705be4f002f2bd (patch)
treec403642105f399baccb3a727020232b5732fe8f7
parenta7191840beeb2c3a0f2598707ed1051a9f23c45f (diff)
FIB table add/delete API
part 2; - this adds the code to create an IP and MPLS table via the API. - but the enforcement that the table must be created before it is used is still missing, this is so that CSIT can pass. Change-Id: Id124d884ade6cb7da947225200e3bb193454c555 Signed-off-by: Neale Ranns <nranns@cisco.com>
-rw-r--r--src/plugins/nat/nat.c17
-rw-r--r--src/plugins/nat/nat64.c13
-rw-r--r--src/vnet/classify/vnet_classify.c16
-rw-r--r--src/vnet/dhcp/dhcp4_proxy_node.c9
-rw-r--r--src/vnet/dhcp/dhcp6_proxy_node.c9
-rw-r--r--src/vnet/dhcp/dhcp_proxy.c19
-rw-r--r--src/vnet/dpo/lookup_dpo.c20
-rw-r--r--src/vnet/dpo/mpls_label_dpo.c12
-rw-r--r--src/vnet/ethernet/arp.c127
-rw-r--r--src/vnet/fib/fib_api.h1
-rw-r--r--src/vnet/fib/fib_entry.c15
-rw-r--r--src/vnet/fib/fib_entry.h1
-rw-r--r--src/vnet/fib/fib_entry_src_mpls.c7
-rw-r--r--src/vnet/fib/fib_table.c43
-rw-r--r--src/vnet/fib/fib_table.h32
-rw-r--r--src/vnet/fib/fib_test.c27
-rw-r--r--src/vnet/fib/ip4_fib.c41
-rw-r--r--src/vnet/fib/ip4_fib.h5
-rw-r--r--src/vnet/fib/ip6_fib.c41
-rw-r--r--src/vnet/fib/ip6_fib.h5
-rw-r--r--src/vnet/fib/mpls_fib.c16
-rw-r--r--src/vnet/fib/mpls_fib.h5
-rw-r--r--src/vnet/interface_api.c177
-rw-r--r--src/vnet/ip/ip.h7
-rw-r--r--src/vnet/ip/ip4.h13
-rwxr-xr-xsrc/vnet/ip/ip4_forward.c101
-rw-r--r--src/vnet/ip/ip4_source_and_port_range_check.c11
-rw-r--r--src/vnet/ip/ip6.h13
-rw-r--r--src/vnet/ip/ip6_forward.c103
-rw-r--r--src/vnet/ip/ip6_neighbor.c108
-rw-r--r--src/vnet/ip/ip_api.c122
-rwxr-xr-xsrc/vnet/ip/lookup.c225
-rw-r--r--src/vnet/lisp-gpe/interface.c11
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c9
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe_sub_interface.c11
-rw-r--r--src/vnet/mfib/ip4_mfib.c12
-rw-r--r--src/vnet/mfib/ip4_mfib.h5
-rw-r--r--src/vnet/mfib/ip6_mfib.c12
-rw-r--r--src/vnet/mfib/ip6_mfib.h5
-rw-r--r--src/vnet/mfib/mfib_entry.c11
-rw-r--r--src/vnet/mfib/mfib_entry.h2
-rw-r--r--src/vnet/mfib/mfib_table.c88
-rw-r--r--src/vnet/mfib/mfib_table.h29
-rw-r--r--src/vnet/mfib/mfib_test.c11
-rw-r--r--src/vnet/mfib/mfib_types.h8
-rw-r--r--src/vnet/mpls/interface.c26
-rw-r--r--src/vnet/mpls/mpls.c76
-rw-r--r--src/vnet/mpls/mpls.h16
-rw-r--r--src/vnet/mpls/mpls_api.c66
-rwxr-xr-xsrc/vnet/srv6/sr_policy_rewrite.c6
-rwxr-xr-xsrc/vnet/srv6/sr_steering.c6
-rw-r--r--src/vpp/api/api.c5
-rw-r--r--src/vpp/api/custom_dump.c3
-rw-r--r--test/test_dhcp.py24
-rw-r--r--test/test_gre.py8
-rw-r--r--test/test_ip4.py11
-rw-r--r--test/test_ip4_vrf_multi_instance.py4
-rw-r--r--test/test_ip6.py7
-rw-r--r--test/test_ip6_vrf_multi_instance.py4
-rw-r--r--test/test_ip_mcast.py98
-rw-r--r--test/test_mpls.py48
-rw-r--r--test/test_nat.py13
-rw-r--r--test/test_neighbor.py66
-rw-r--r--test/vpp_ip_route.py73
-rw-r--r--test/vpp_papi_provider.py46
65 files changed, 1643 insertions, 538 deletions
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c
index aa7ef10ad0e..8aecac6d3ff 100644
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -167,7 +167,8 @@ void snat_add_address (snat_main_t *sm, ip4_address_t *addr, u32 vrf_id)
ap->addr = *addr;
if (vrf_id != ~0)
ap->fib_index =
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id);
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
+ FIB_SOURCE_PLUGIN_HI);
else
ap->fib_index = ~0;
#define _(N, i, n, s) \
@@ -625,7 +626,8 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
return VNET_API_ERROR_INVALID_VALUE;
fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
- vrf_id);
+ vrf_id,
+ FIB_SOURCE_PLUGIN_HI);
/* Find external address in allocated addresses and reserve port for
address and port pair mapping when dynamic translations enabled */
@@ -754,7 +756,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
if (!m)
return VNET_API_ERROR_NO_SUCH_ENTRY;
- fib_table_unlock (m->fib_index, FIB_PROTOCOL_IP4);
+ fib_table_unlock (m->fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_HI);
/* Free external address port */
if (!sm->static_mapping_only)
@@ -874,7 +876,8 @@ int snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm)
}
if (a->fib_index != ~0)
- fib_table_unlock(a->fib_index, FIB_PROTOCOL_IP4);
+ fib_table_unlock(a->fib_index, FIB_PROTOCOL_IP4,
+ FIB_SOURCE_PLUGIN_HI);
/* Delete sessions using address */
if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
@@ -2151,10 +2154,12 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
sm->max_translations_per_user = max_translations_per_user;
sm->outside_vrf_id = outside_vrf_id;
sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
- outside_vrf_id);
+ outside_vrf_id,
+ FIB_SOURCE_PLUGIN_HI);
sm->inside_vrf_id = inside_vrf_id;
sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
- inside_vrf_id);
+ inside_vrf_id,
+ FIB_SOURCE_PLUGIN_HI);
sm->static_mapping_only = static_mapping_only;
sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
diff --git a/src/plugins/nat/nat64.c b/src/plugins/nat/nat64.c
index b04901fade4..bfcfa9b3620 100644
--- a/src/plugins/nat/nat64.c
+++ b/src/plugins/nat/nat64.c
@@ -107,7 +107,8 @@ nat64_add_del_pool_addr (ip4_address_t * addr, u32 vrf_id, u8 is_add)
a->fib_index = 0;
if (vrf_id != ~0)
a->fib_index =
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id);
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id,
+ FIB_SOURCE_PLUGIN_HI);
#define _(N, i, n, s) \
clib_bitmap_alloc (a->busy_##n##_port_bitmap, 65535);
foreach_snat_protocol
@@ -119,7 +120,8 @@ nat64_add_del_pool_addr (ip4_address_t * addr, u32 vrf_id, u8 is_add)
return VNET_API_ERROR_NO_SUCH_ENTRY;
if (a->fib_index)
- fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP6);
+ fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP6,
+ FIB_SOURCE_PLUGIN_HI);
#define _(N, id, n, s) \
clib_bitmap_free (a->busy_##n##_port_bitmap);
@@ -353,8 +355,8 @@ nat64_add_del_static_bib_entry (ip6_address_t * in_addr,
{
nat64_main_t *nm = &nat64_main;
nat64_db_bib_entry_t *bibe;
- u32 fib_index =
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id);
+ u32 fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id,
+ FIB_SOURCE_PLUGIN_HI);
snat_protocol_t p = ip_proto_to_snat_proto (proto);
ip46_address_t addr;
int i;
@@ -644,7 +646,8 @@ nat64_add_del_prefix (ip6_address_t * prefix, u8 plen, u32 vrf_id, u8 is_add)
{
vec_add2 (nm->pref64, p, 1);
p->fib_index =
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id);
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id,
+ FIB_SOURCE_PLUGIN_HI);
p->vrf_id = vrf_id;
}
diff --git a/src/vnet/classify/vnet_classify.c b/src/vnet/classify/vnet_classify.c
index 879fba3c6d9..57d8674884c 100644
--- a/src/vnet/classify/vnet_classify.c
+++ b/src/vnet/classify/vnet_classify.c
@@ -368,10 +368,10 @@ vnet_classify_entry_claim_resource (vnet_classify_entry_t *e)
switch (e->action)
{
case CLASSIFY_ACTION_SET_IP4_FIB_INDEX:
- fib_table_lock (e->metadata, FIB_PROTOCOL_IP4);
+ fib_table_lock (e->metadata, FIB_PROTOCOL_IP4, FIB_SOURCE_CLASSIFY);
break;
case CLASSIFY_ACTION_SET_IP6_FIB_INDEX:
- fib_table_lock (e->metadata, FIB_PROTOCOL_IP6);
+ fib_table_lock (e->metadata, FIB_PROTOCOL_IP6, FIB_SOURCE_CLASSIFY);
break;
}
}
@@ -382,10 +382,10 @@ vnet_classify_entry_release_resource (vnet_classify_entry_t *e)
switch (e->action)
{
case CLASSIFY_ACTION_SET_IP4_FIB_INDEX:
- fib_table_unlock (e->metadata, FIB_PROTOCOL_IP4);
+ fib_table_unlock (e->metadata, FIB_PROTOCOL_IP4, FIB_SOURCE_CLASSIFY);
break;
case CLASSIFY_ACTION_SET_IP6_FIB_INDEX:
- fib_table_unlock (e->metadata, FIB_PROTOCOL_IP6);
+ fib_table_unlock (e->metadata, FIB_PROTOCOL_IP6, FIB_SOURCE_CLASSIFY);
break;
}
}
@@ -2096,9 +2096,13 @@ int vnet_classify_add_del_session (vnet_classify_main_t * cm,
e->flags = 0;
e->action = action;
if (e->action == CLASSIFY_ACTION_SET_IP4_FIB_INDEX)
- e->metadata = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, metadata);
+ e->metadata = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
+ metadata,
+ FIB_SOURCE_CLASSIFY);
else if (e->action == CLASSIFY_ACTION_SET_IP6_FIB_INDEX)
- e->metadata = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, metadata);
+ e->metadata = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
+ metadata,
+ FIB_SOURCE_CLASSIFY);
else
e->metadata = 0;
diff --git a/src/vnet/dhcp/dhcp4_proxy_node.c b/src/vnet/dhcp/dhcp4_proxy_node.c
index 1b59cdea0d9..339a78858a7 100644
--- a/src/vnet/dhcp/dhcp4_proxy_node.c
+++ b/src/vnet/dhcp/dhcp4_proxy_node.c
@@ -785,7 +785,8 @@ dhcp4_proxy_set_server (ip46_address_t *addr,
return VNET_API_ERROR_INVALID_SRC_ADDRESS;
rx_fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
- rx_table_id);
+ rx_table_id,
+ FIB_SOURCE_DHCP);
if (is_del)
{
@@ -795,7 +796,7 @@ dhcp4_proxy_set_server (ip46_address_t *addr,
fib_table_entry_special_remove(rx_fib_index,
&all_1s,
FIB_SOURCE_DHCP);
- fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4);
+ fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_DHCP);
}
}
else
@@ -808,10 +809,10 @@ dhcp4_proxy_set_server (ip46_address_t *addr,
&all_1s,
FIB_SOURCE_DHCP,
FIB_ENTRY_FLAG_LOCAL);
- fib_table_lock (rx_fib_index, FIB_PROTOCOL_IP4);
+ fib_table_lock (rx_fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_DHCP);
}
}
- fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4);
+ fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_DHCP);
return (rc);
}
diff --git a/src/vnet/dhcp/dhcp6_proxy_node.c b/src/vnet/dhcp/dhcp6_proxy_node.c
index 9c2f5220d6e..ce7a8fca3bc 100644
--- a/src/vnet/dhcp/dhcp6_proxy_node.c
+++ b/src/vnet/dhcp/dhcp6_proxy_node.c
@@ -841,7 +841,8 @@ dhcp6_proxy_set_server (ip46_address_t *addr,
return VNET_API_ERROR_INVALID_SRC_ADDRESS;
rx_fib_index = mfib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6,
- rx_table_id);
+ rx_table_id,
+ MFIB_SOURCE_DHCP);
if (is_del)
{
@@ -851,7 +852,7 @@ dhcp6_proxy_set_server (ip46_address_t *addr,
mfib_table_entry_delete(rx_fib_index,
&all_dhcp_servers,
MFIB_SOURCE_DHCP);
- mfib_table_unlock(rx_fib_index, FIB_PROTOCOL_IP6);
+ mfib_table_unlock(rx_fib_index, FIB_PROTOCOL_IP6, MFIB_SOURCE_DHCP);
}
}
else
@@ -885,11 +886,11 @@ dhcp6_proxy_set_server (ip46_address_t *addr,
MFIB_SOURCE_DHCP,
MFIB_RPF_ID_NONE,
MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF);
- mfib_table_lock(rx_fib_index, FIB_PROTOCOL_IP6);
+ mfib_table_lock(rx_fib_index, FIB_PROTOCOL_IP6, MFIB_SOURCE_DHCP);
}
}
- mfib_table_unlock(rx_fib_index, FIB_PROTOCOL_IP6);
+ mfib_table_unlock(rx_fib_index, FIB_PROTOCOL_IP6, MFIB_SOURCE_DHCP);
return (rc);
}
diff --git a/src/vnet/dhcp/dhcp_proxy.c b/src/vnet/dhcp/dhcp_proxy.c
index ba7f354e9fa..1784906b7b3 100644
--- a/src/vnet/dhcp/dhcp_proxy.c
+++ b/src/vnet/dhcp/dhcp_proxy.c
@@ -29,9 +29,9 @@ dhcp_proxy_rx_table_lock (fib_protocol_t proto,
u32 fib_index)
{
if (FIB_PROTOCOL_IP4 == proto)
- fib_table_lock(fib_index, proto);
+ fib_table_lock(fib_index, proto, FIB_SOURCE_DHCP);
else
- mfib_table_lock(fib_index, proto);
+ mfib_table_lock(fib_index, proto, MFIB_SOURCE_DHCP);
}
static void
@@ -39,9 +39,9 @@ dhcp_proxy_rx_table_unlock (fib_protocol_t proto,
u32 fib_index)
{
if (FIB_PROTOCOL_IP4 == proto)
- fib_table_unlock(fib_index, proto);
+ fib_table_unlock(fib_index, proto, FIB_SOURCE_DHCP);
else
- mfib_table_unlock(fib_index, proto);
+ mfib_table_unlock(fib_index, proto, MFIB_SOURCE_DHCP);
}
u32
@@ -169,7 +169,7 @@ dhcp_proxy_server_del (fib_protocol_t proto,
if (~0 != index)
{
server = &proxy->dhcp_servers[index];
- fib_table_unlock (server->server_fib_index, proto);
+ fib_table_unlock (server->server_fib_index, proto, FIB_SOURCE_DHCP);
vec_del1(proxy->dhcp_servers, index);
@@ -228,7 +228,8 @@ dhcp_proxy_server_add (fib_protocol_t proto,
dhcp_server_t server = {
.dhcp_server = *addr,
.server_fib_index = fib_table_find_or_create_and_lock(proto,
- server_table_id),
+ server_table_id,
+ FIB_SOURCE_DHCP),
};
vec_add1(proxy->dhcp_servers, server);
@@ -297,9 +298,11 @@ int dhcp_proxy_set_vss (fib_protocol_t proto,
int rc = 0;
if (proto == FIB_PROTOCOL_IP4)
- rx_fib_index = fib_table_find_or_create_and_lock(proto, tbl_id);
+ rx_fib_index = fib_table_find_or_create_and_lock(proto, tbl_id,
+ FIB_SOURCE_DHCP);
else
- rx_fib_index = mfib_table_find_or_create_and_lock(proto, tbl_id);
+ rx_fib_index = mfib_table_find_or_create_and_lock(proto, tbl_id,
+ MFIB_SOURCE_DHCP);
v = dhcp_get_vss_info(dm, rx_fib_index, proto);
if (NULL != v)
diff --git a/src/vnet/dpo/lookup_dpo.c b/src/vnet/dpo/lookup_dpo.c
index 26363a2f0fa..af189eda44f 100644
--- a/src/vnet/dpo/lookup_dpo.c
+++ b/src/vnet/dpo/lookup_dpo.c
@@ -135,11 +135,15 @@ lookup_dpo_add_or_lock_w_fib_index (fib_node_index_t fib_index,
{
if (LOOKUP_UNICAST == cast)
{
- fib_table_lock(fib_index, dpo_proto_to_fib(proto));
+ fib_table_lock(fib_index,
+ dpo_proto_to_fib(proto),
+ FIB_SOURCE_RR);
}
else
{
- mfib_table_lock(fib_index, dpo_proto_to_fib(proto));
+ mfib_table_lock(fib_index,
+ dpo_proto_to_fib(proto),
+ MFIB_SOURCE_RR);
}
}
lookup_dpo_add_or_lock_i(fib_index, proto, cast, input, table_config, dpo);
@@ -161,13 +165,15 @@ lookup_dpo_add_or_lock_w_table_id (u32 table_id,
{
fib_index =
fib_table_find_or_create_and_lock(dpo_proto_to_fib(proto),
- table_id);
+ table_id,
+ FIB_SOURCE_RR);
}
else
{
fib_index =
mfib_table_find_or_create_and_lock(dpo_proto_to_fib(proto),
- table_id);
+ table_id,
+ MFIB_SOURCE_RR);
}
}
@@ -238,12 +244,14 @@ lookup_dpo_unlock (dpo_id_t *dpo)
if (LOOKUP_UNICAST == lkd->lkd_cast)
{
fib_table_unlock(lkd->lkd_fib_index,
- dpo_proto_to_fib(lkd->lkd_proto));
+ dpo_proto_to_fib(lkd->lkd_proto),
+ FIB_SOURCE_RR);
}
else
{
mfib_table_unlock(lkd->lkd_fib_index,
- dpo_proto_to_fib(lkd->lkd_proto));
+ dpo_proto_to_fib(lkd->lkd_proto),
+ MFIB_SOURCE_RR);
}
}
pool_put(lookup_dpo_pool, lkd);
diff --git a/src/vnet/dpo/mpls_label_dpo.c b/src/vnet/dpo/mpls_label_dpo.c
index b178a902e32..2a6e7dd5e48 100644
--- a/src/vnet/dpo/mpls_label_dpo.c
+++ b/src/vnet/dpo/mpls_label_dpo.c
@@ -105,10 +105,18 @@ format_mpls_label_dpo (u8 *s, va_list *args)
mpls_label_dpo_t *mld;
u32 ii;
- mld = mpls_label_dpo_get(index);
-
s = format(s, "mpls-label:[%d]:", index);
+ if (pool_is_free_index(mpls_label_dpo_pool, index))
+ {
+ /*
+ * the packet trace can be printed after the DPO has been deleted
+ */
+ return (s);
+ }
+
+ mld = mpls_label_dpo_get(index);
+
for (ii = 0; ii < mld->mld_n_labels; ii++)
{
hdr.label_exp_s_ttl =
diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c
index c84ff47bc00..08e91373b64 100644
--- a/src/vnet/ethernet/arp.c
+++ b/src/vnet/ethernet/arp.c
@@ -522,6 +522,24 @@ arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
}
}
+static void
+arp_adj_fib_add (ethernet_arp_ip4_entry_t * e, uint32_t fib_index)
+{
+ fib_prefix_t pfx = {
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_addr.ip4 = e->ip4_address,
+ };
+
+ e->fib_entry_index =
+ fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
+ FIB_ENTRY_FLAG_ATTACHED,
+ DPO_PROTO_IP4, &pfx.fp_addr,
+ e->sw_if_index, ~0, 1, NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+ fib_table_lock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_ADJ);
+}
+
int
vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
vnet_arp_set_ip4_over_ethernet_rpc_args_t
@@ -576,21 +594,9 @@ vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
if (!is_no_fib_entry)
{
- fib_prefix_t pfx = {
- .fp_len = 32,
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_addr.ip4 = a->ip4,
- };
- u32 fib_index;
-
- fib_index =
- ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index);
- e->fib_entry_index =
- fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
- FIB_ENTRY_FLAG_ATTACHED,
- DPO_PROTO_IP4, &pfx.fp_addr,
- e->sw_if_index, ~0, 1, NULL,
- FIB_ROUTE_PATH_FLAG_NONE);
+ arp_adj_fib_add (e,
+ ip4_fib_table_get_index_for_sw_if_index
+ (e->sw_if_index));
}
else
{
@@ -1561,6 +1567,65 @@ arp_add_del_interface_address (ip4_main_t * im,
}
}
+void
+arp_adj_fib_remove (ethernet_arp_ip4_entry_t * e, uint32_t fib_index)
+{
+ if (FIB_NODE_INDEX_INVALID != e->fib_entry_index)
+ {
+ fib_prefix_t pfx = {
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_addr.ip4 = e->ip4_address,
+ };
+ u32 fib_index;
+
+ fib_index = ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index);
+
+ fib_table_entry_path_remove (fib_index, &pfx,
+ FIB_SOURCE_ADJ,
+ DPO_PROTO_IP4,
+ &pfx.fp_addr,
+ e->sw_if_index, ~0, 1,
+ FIB_ROUTE_PATH_FLAG_NONE);
+ fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_ADJ);
+ }
+}
+
+static void
+arp_table_bind (ip4_main_t * im,
+ uword opaque,
+ u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
+{
+ ethernet_arp_main_t *am = &ethernet_arp_main;
+ ethernet_arp_interface_t *eai;
+ ethernet_arp_ip4_entry_t *e;
+ hash_pair_t *pair;
+
+ /*
+ * the IP table that the interface is bound to has changed.
+ * reinstall all the adj fibs.
+ */
+
+ if (vec_len (am->ethernet_arp_by_sw_if_index) <= sw_if_index)
+ return;
+
+ eai = &am->ethernet_arp_by_sw_if_index[sw_if_index];
+
+ /* *INDENT-OFF* */
+ hash_foreach_pair (pair, eai->arp_entries,
+ ({
+ e = pool_elt_at_index(am->ip4_entry_pool,
+ pair->value[0]);
+ /*
+ * remove the adj-fib from the old table and add to the new
+ */
+ arp_adj_fib_remove(e, old_fib_index);
+ arp_adj_fib_add(e, new_fib_index);
+ }));
+ /* *INDENT-ON* */
+
+}
+
static clib_error_t *
ethernet_arp_init (vlib_main_t * vm)
{
@@ -1606,6 +1671,11 @@ ethernet_arp_init (vlib_main_t * vm)
cb.function_opaque = 0;
vec_add1 (im->add_del_interface_address_callbacks, cb);
+ ip4_table_bind_callback_t cbt;
+ cbt.function = arp_table_bind;
+ cbt.function_opaque = 0;
+ vec_add1 (im->table_bind_callbacks, cbt);
+
return 0;
}
@@ -1616,24 +1686,9 @@ arp_entry_free (ethernet_arp_interface_t * eai, ethernet_arp_ip4_entry_t * e)
{
ethernet_arp_main_t *am = &ethernet_arp_main;
- if (FIB_NODE_INDEX_INVALID != e->fib_entry_index)
- {
- fib_prefix_t pfx = {
- .fp_len = 32,
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_addr.ip4 = e->ip4_address,
- };
- u32 fib_index;
-
- fib_index = ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index);
-
- fib_table_entry_path_remove (fib_index, &pfx,
- FIB_SOURCE_ADJ,
- DPO_PROTO_IP4,
- &pfx.fp_addr,
- e->sw_if_index, ~0, 1,
- FIB_ROUTE_PATH_FLAG_NONE);
- }
+ arp_adj_fib_remove (e,
+ ip4_fib_table_get_index_for_sw_if_index
+ (e->sw_if_index));
hash_unset (eai->arp_entries, e->ip4_address.as_u32);
pool_put (am->ip4_entry_pool, e);
}
@@ -1693,7 +1748,11 @@ vnet_arp_flush_ip4_over_ethernet_internal (vnet_main_t * vnm,
* does in response to interface events. unset is only done
* by the control plane.
*/
- if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC)
+ if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC)
+ {
+ e->flags &= ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC;
+ }
+ else if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC)
{
arp_entry_free (eai, e);
}
diff --git a/src/vnet/fib/fib_api.h b/src/vnet/fib/fib_api.h
index d07d6caee66..f5a107ca352 100644
--- a/src/vnet/fib/fib_api.h
+++ b/src/vnet/fib/fib_api.h
@@ -23,7 +23,6 @@ add_del_route_check (fib_protocol_t table_proto,
u32 next_hop_sw_if_index,
dpo_proto_t next_hop_table_proto,
u32 next_hop_table_id,
- u8 create_missing_tables,
u8 is_rpf_id,
u32 * fib_index, u32 * next_hop_fib_index);
diff --git a/src/vnet/fib/fib_entry.c b/src/vnet/fib/fib_entry.c
index 2027f2be8b9..4cb6cf6050c 100644
--- a/src/vnet/fib/fib_entry.c
+++ b/src/vnet/fib/fib_entry.c
@@ -90,6 +90,17 @@ fib_entry_get_default_chain_type (const fib_entry_t *fib_entry)
}
u8 *
+format_fib_source (u8 * s, va_list * args)
+{
+ fib_source_t source = va_arg (*args, int);
+
+ s = format (s, "\n src:%s ",
+ fib_source_names[source]);
+
+ return (s);
+}
+
+u8 *
format_fib_entry (u8 * s, va_list * args)
{
fib_forward_chain_type_t fct;
@@ -114,8 +125,8 @@ format_fib_entry (u8 * s, va_list * args)
FOR_EACH_SRC_ADDED(fib_entry, src, source,
({
- s = format (s, "\n src:%s ",
- fib_source_names[source]);
+ s = format (s, "\n src:%U ",
+ format_fib_source, source);
s = fib_entry_src_format(fib_entry, source, s);
s = format (s, " refs:%d ", src->fes_ref_count);
if (FIB_ENTRY_FLAG_NONE != src->fes_entry_flags) {
diff --git a/src/vnet/fib/fib_entry.h b/src/vnet/fib/fib_entry.h
index 93b8016d44f..2f6e37fe69a 100644
--- a/src/vnet/fib/fib_entry.h
+++ b/src/vnet/fib/fib_entry.h
@@ -431,6 +431,7 @@ typedef struct fib_entry_t_ {
#define FIB_ENTRY_FORMAT_DETAIL2 (0x2)
extern u8 *format_fib_entry (u8 * s, va_list * args);
+extern u8 *format_fib_source (u8 * s, va_list * args);
extern fib_node_index_t fib_entry_create_special(u32 fib_index,
const fib_prefix_t *prefix,
diff --git a/src/vnet/fib/fib_entry_src_mpls.c b/src/vnet/fib/fib_entry_src_mpls.c
index a616458fcbe..6fdd5c0ac66 100644
--- a/src/vnet/fib/fib_entry_src_mpls.c
+++ b/src/vnet/fib/fib_entry_src_mpls.c
@@ -94,7 +94,9 @@ fib_entry_src_mpls_set_data (fib_entry_src_t *src,
fib_table_entry_delete_index(src->mpls.fesm_lfes[eos],
FIB_SOURCE_SPECIAL);
}
- fib_table_unlock(MPLS_FIB_DEFAULT_TABLE_ID, FIB_PROTOCOL_MPLS);
+ fib_table_unlock(MPLS_FIB_DEFAULT_TABLE_ID,
+ FIB_PROTOCOL_MPLS,
+ FIB_SOURCE_MPLS);
src->mpls.fesm_label = label;
}
else
@@ -113,7 +115,8 @@ fib_entry_src_mpls_set_data (fib_entry_src_t *src,
{
fib_index =
fib_table_find_or_create_and_lock(FIB_PROTOCOL_MPLS,
- MPLS_FIB_DEFAULT_TABLE_ID);
+ MPLS_FIB_DEFAULT_TABLE_ID,
+ FIB_SOURCE_MPLS);
}
else
{
diff --git a/src/vnet/fib/fib_table.c b/src/vnet/fib/fib_table.c
index 6b6cc5cb99a..75d15628c26 100644
--- a/src/vnet/fib/fib_table.c
+++ b/src/vnet/fib/fib_table.c
@@ -1039,7 +1039,8 @@ fib_table_find (fib_protocol_t proto,
u32
fib_table_find_or_create_and_lock (fib_protocol_t proto,
- u32 table_id)
+ u32 table_id,
+ fib_source_t src)
{
fib_table_t *fib_table;
fib_node_index_t fi;
@@ -1047,13 +1048,13 @@ fib_table_find_or_create_and_lock (fib_protocol_t proto,
switch (proto)
{
case FIB_PROTOCOL_IP4:
- fi = ip4_fib_table_find_or_create_and_lock(table_id);
+ fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
break;
case FIB_PROTOCOL_IP6:
- fi = ip6_fib_table_find_or_create_and_lock(table_id);
+ fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
break;
case FIB_PROTOCOL_MPLS:
- fi = mpls_fib_table_find_or_create_and_lock(table_id);
+ fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
break;
default:
return (~0);
@@ -1070,6 +1071,7 @@ fib_table_find_or_create_and_lock (fib_protocol_t proto,
u32
fib_table_create_and_lock (fib_protocol_t proto,
+ fib_source_t src,
const char *const fmt,
...)
{
@@ -1082,13 +1084,13 @@ fib_table_create_and_lock (fib_protocol_t proto,
switch (proto)
{
case FIB_PROTOCOL_IP4:
- fi = ip4_fib_table_create_and_lock();
+ fi = ip4_fib_table_create_and_lock(src);
break;
case FIB_PROTOCOL_IP6:
- fi = ip6_fib_table_create_and_lock();
+ fi = ip6_fib_table_create_and_lock(src);
break;
case FIB_PROTOCOL_MPLS:
- fi = mpls_fib_table_create_and_lock();
+ fi = mpls_fib_table_create_and_lock(src);
break;
default:
return (~0);
@@ -1143,26 +1145,43 @@ fib_table_walk (u32 fib_index,
void
fib_table_unlock (u32 fib_index,
- fib_protocol_t proto)
+ fib_protocol_t proto,
+ fib_source_t source)
{
fib_table_t *fib_table;
fib_table = fib_table_get(fib_index, proto);
- fib_table->ft_locks--;
+ fib_table->ft_locks[source]--;
+ fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]--;
- if (0 == fib_table->ft_locks)
+ if (0 == fib_table->ft_locks[source])
{
+ /*
+ * The source no longer needs the table. flush any routes
+ * from it just in case
+ */
+ fib_table_flush(fib_index, proto, source);
+ }
+
+ if (0 == fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS])
+ {
+ /*
+ * no more locak from any source - kill it
+ */
fib_table_destroy(fib_table);
}
}
+
void
fib_table_lock (u32 fib_index,
- fib_protocol_t proto)
+ fib_protocol_t proto,
+ fib_source_t source)
{
fib_table_t *fib_table;
fib_table = fib_table_get(fib_index, proto);
- fib_table->ft_locks++;
+ fib_table->ft_locks[source]++;
+ fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]++;
}
u32
diff --git a/src/vnet/fib/fib_table.h b/src/vnet/fib/fib_table.h
index 579740e9c42..6b7011b3316 100644
--- a/src/vnet/fib/fib_table.h
+++ b/src/vnet/fib/fib_table.h
@@ -23,6 +23,12 @@
#include <vnet/mpls/packet.h>
/**
+ * Keep a lock per-source and a total
+ */
+#define FIB_TABLE_N_LOCKS (FIB_SOURCE_MAX+1)
+#define FIB_TABLE_TOTAL_LOCKS FIB_SOURCE_MAX
+
+/**
* @brief
* A protocol Independent FIB table
*/
@@ -34,9 +40,9 @@ typedef struct fib_table_t_
fib_protocol_t ft_proto;
/**
- * number of locks on the table
+ * per-source number of locks on the table
*/
- u16 ft_locks;
+ u16 ft_locks[FIB_TABLE_N_LOCKS];
/**
* Table ID (hash key) for this FIB.
@@ -628,9 +634,13 @@ extern u32 fib_table_find(fib_protocol_t proto, u32 table_id);
*
* @return fib_index
* The index of the FIB
+ *
+ * @param source
+ * The ID of the client/source.
*/
extern u32 fib_table_find_or_create_and_lock(fib_protocol_t proto,
- u32 table_id);
+ u32 table_id,
+ fib_source_t source);
/**
* @brief
@@ -643,10 +653,14 @@ extern u32 fib_table_find_or_create_and_lock(fib_protocol_t proto,
* @param fmt
* A string to describe the table
*
+ * @param source
+ * The ID of the client/source.
+ *
* @return fib_index
* The index of the FIB
*/
extern u32 fib_table_create_and_lock(fib_protocol_t proto,
+ fib_source_t source,
const char *const fmt,
...);
@@ -704,9 +718,13 @@ extern void fib_table_set_flow_hash_config(u32 fib_index,
*
* @paran proto
* The protocol of the FIB (and thus the entries therein)
+ *
+ * @param source
+ * The ID of the client/source.
*/
extern void fib_table_unlock(u32 fib_index,
- fib_protocol_t proto);
+ fib_protocol_t proto,
+ fib_source_t source);
/**
* @brief
@@ -718,9 +736,13 @@ extern void fib_table_unlock(u32 fib_index,
*
* @paran proto
* The protocol of the FIB (and thus the entries therein)
+ *
+ * @param source
+ * The ID of the client/source.
*/
extern void fib_table_lock(u32 fib_index,
- fib_protocol_t proto);
+ fib_protocol_t proto,
+ fib_source_t source);
/**
* @brief
diff --git a/src/vnet/fib/fib_test.c b/src/vnet/fib/fib_test.c
index 6867cca8959..572d7f0d156 100644
--- a/src/vnet/fib/fib_test.c
+++ b/src/vnet/fib/fib_test.c
@@ -739,7 +739,8 @@ fib_test_v4 (void)
lb_count = pool_elts(load_balance_pool);
/* Find or create FIB table 11 */
- fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
+ fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
+ FIB_SOURCE_API);
for (ii = 0; ii < 4; ii++)
{
@@ -4150,7 +4151,7 @@ fib_test_v4 (void)
FIB_SOURCE_INTERFACE)),
"NO INterface Source'd prefixes");
- fib_table_unlock(fib_index, FIB_PROTOCOL_IP4);
+ fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
@@ -4201,7 +4202,8 @@ fib_test_v6 (void)
dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
/* Find or create FIB table 11 */
- fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11);
+ fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
+ FIB_SOURCE_API);
for (ii = 0; ii < 4; ii++)
{
@@ -5025,7 +5027,7 @@ fib_test_v6 (void)
/*
* now remove the VRF
*/
- fib_table_unlock(fib_index, FIB_PROTOCOL_IP6);
+ fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
@@ -5157,7 +5159,9 @@ fib_test_ae (void)
*/
u32 import_fib_index1;
- import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
+ import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
+ 11,
+ FIB_SOURCE_CLI);
/*
* Add an attached route in the import FIB
@@ -5233,7 +5237,8 @@ fib_test_ae (void)
*/
u32 import_fib_index2;
- import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12);
+ import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
+ FIB_SOURCE_CLI);
/*
* Add an attached route in the import FIB
@@ -5595,8 +5600,8 @@ fib_test_ae (void)
&local_pfx,
FIB_SOURCE_API);
- fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4);
- fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4);
+ fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
+ fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
adj_nbr_db_size());
@@ -8168,9 +8173,10 @@ lfib_test (void)
/*
* MPLS enable an interface so we get the MPLS table created
*/
+ mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
mpls_sw_interface_enable_disable(&mpls_main,
tm->hw[0]->sw_if_index,
- 1);
+ 1, 1);
ip46_address_t nh_10_10_10_1 = {
.ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
@@ -8662,7 +8668,8 @@ lfib_test (void)
*/
mpls_sw_interface_enable_disable(&mpls_main,
tm->hw[0]->sw_if_index,
- 0);
+ 0, 1);
+ mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
FIB_TEST(lb_count == pool_elts(load_balance_pool),
"Load-balance resources freed %d of %d",
diff --git a/src/vnet/fib/ip4_fib.c b/src/vnet/fib/ip4_fib.c
index d563bafda0c..865e2dd5faf 100644
--- a/src/vnet/fib/ip4_fib.c
+++ b/src/vnet/fib/ip4_fib.c
@@ -101,7 +101,8 @@ static const ip4_fib_table_special_prefix_t ip4_specials[] = {
static u32
-ip4_create_fib_with_table_id (u32 table_id)
+ip4_create_fib_with_table_id (u32 table_id,
+ fib_source_t src)
{
fib_table_t *fib_table;
ip4_fib_t *v4_fib;
@@ -128,7 +129,7 @@ ip4_create_fib_with_table_id (u32 table_id)
v4_fib->fwd_classify_table_index = ~0;
v4_fib->rev_classify_table_index = ~0;
- fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP4);
+ fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP4, src);
ip4_mtrie_init(&v4_fib->mtrie);
@@ -198,23 +199,24 @@ ip4_fib_table_destroy (u32 fib_index)
u32
-ip4_fib_table_find_or_create_and_lock (u32 table_id)
+ip4_fib_table_find_or_create_and_lock (u32 table_id,
+ fib_source_t src)
{
u32 index;
index = ip4_fib_index_from_table_id(table_id);
if (~0 == index)
- return ip4_create_fib_with_table_id(table_id);
+ return ip4_create_fib_with_table_id(table_id, src);
- fib_table_lock(index, FIB_PROTOCOL_IP4);
+ fib_table_lock(index, FIB_PROTOCOL_IP4, src);
return (index);
}
u32
-ip4_fib_table_create_and_lock (void)
+ip4_fib_table_create_and_lock (fib_source_t src)
{
- return (ip4_create_fib_with_table_id(~0));
+ return (ip4_create_fib_with_table_id(~0, src));
}
u32
@@ -525,17 +527,32 @@ ip4_show_fib (vlib_main_t * vm,
pool_foreach (fib_table, im4->fibs,
({
ip4_fib_t *fib = pool_elt_at_index(im4->v4_fibs, fib_table->ft_index);
+ fib_source_t source;
+ u8 *s = NULL;
if (table_id >= 0 && table_id != (int)fib->table_id)
continue;
if (fib_index != ~0 && fib_index != (int)fib->index)
continue;
- vlib_cli_output (vm, "%U, fib_index:%d, flow hash:[%U] locks:%d",
- format_fib_table_name, fib->index, FIB_PROTOCOL_IP4,
- fib->index,
- format_ip_flow_hash_config, fib_table->ft_flow_hash_config,
- fib_table->ft_locks);
+ s = format(s, "%U, fib_index:%d, flow hash:[%U] locks:[",
+ format_fib_table_name, fib->index,
+ FIB_PROTOCOL_IP4,
+ fib->index,
+ format_ip_flow_hash_config,
+ fib_table->ft_flow_hash_config);
+ FOR_EACH_FIB_SOURCE(source)
+ {
+ if (0 != fib_table->ft_locks[source])
+ {
+ s = format(s, "%U:%d, ",
+ format_fib_source, source,
+ fib_table->ft_locks[source]);
+ }
+ }
+ s = format (s, "]");
+ vlib_cli_output (vm, "%V", s);
+ vec_free(s);
/* Show summary? */
if (! verbose)
diff --git a/src/vnet/fib/ip4_fib.h b/src/vnet/fib/ip4_fib.h
index 006163b4d13..495b45ccab4 100644
--- a/src/vnet/fib/ip4_fib.h
+++ b/src/vnet/fib/ip4_fib.h
@@ -127,8 +127,9 @@ ip4_fib_lookup (ip4_main_t * im, u32 sw_if_index, ip4_address_t * dst)
* @returns A pointer to the retrieved or created fib.
*
*/
-extern u32 ip4_fib_table_find_or_create_and_lock(u32 table_id);
-extern u32 ip4_fib_table_create_and_lock(void);
+extern u32 ip4_fib_table_find_or_create_and_lock(u32 table_id,
+ fib_source_t src);
+extern u32 ip4_fib_table_create_and_lock(fib_source_t src);
static inline
diff --git a/src/vnet/fib/ip6_fib.c b/src/vnet/fib/ip6_fib.c
index 8fde6f9f46e..3ddb8453eaa 100644
--- a/src/vnet/fib/ip6_fib.c
+++ b/src/vnet/fib/ip6_fib.c
@@ -50,7 +50,8 @@ vnet_ip6_fib_init (u32 fib_index)
}
static u32
-create_fib_with_table_id (u32 table_id)
+create_fib_with_table_id (u32 table_id,
+ fib_source_t src)
{
fib_table_t *fib_table;
ip6_fib_t *v6_fib;
@@ -77,29 +78,30 @@ create_fib_with_table_id (u32 table_id)
fib_table->ft_flow_hash_config = IP_FLOW_HASH_DEFAULT;
vnet_ip6_fib_init(fib_table->ft_index);
- fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP6);
+ fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP6, src);
return (fib_table->ft_index);
}
u32
-ip6_fib_table_find_or_create_and_lock (u32 table_id)
+ip6_fib_table_find_or_create_and_lock (u32 table_id,
+ fib_source_t src)
{
uword * p;
p = hash_get (ip6_main.fib_index_by_table_id, table_id);
if (NULL == p)
- return create_fib_with_table_id(table_id);
+ return create_fib_with_table_id(table_id, src);
- fib_table_lock(p[0], FIB_PROTOCOL_IP6);
+ fib_table_lock(p[0], FIB_PROTOCOL_IP6, src);
return (p[0]);
}
u32
-ip6_fib_table_create_and_lock (void)
+ip6_fib_table_create_and_lock (fib_source_t src)
{
- return (create_fib_with_table_id(~0));
+ return (create_fib_with_table_id(~0, src));
}
void
@@ -588,16 +590,33 @@ ip6_show_fib (vlib_main_t * vm,
pool_foreach (fib_table, im6->fibs,
({
+ fib_source_t source;
+ u8 *s = NULL;
+
fib = pool_elt_at_index(im6->v6_fibs, fib_table->ft_index);
if (table_id >= 0 && table_id != (int)fib->table_id)
continue;
if (fib_index != ~0 && fib_index != (int)fib->index)
continue;
- vlib_cli_output (vm, "%s, fib_index:%d, flow hash:[%U] locks:%d",
- fib_table->ft_desc, fib->index,
- format_ip_flow_hash_config, fib_table->ft_flow_hash_config,
- fib_table->ft_locks);
+ s = format(s, "%U, fib_index:%d, flow hash:[%U] locks:[",
+ format_fib_table_name, fib->index,
+ FIB_PROTOCOL_IP6,
+ fib->index,
+ format_ip_flow_hash_config,
+ fib_table->ft_flow_hash_config);
+ FOR_EACH_FIB_SOURCE(source)
+ {
+ if (0 != fib_table->ft_locks[source])
+ {
+ s = format(s, "%U:%d, ",
+ format_fib_source, source,
+ fib_table->ft_locks[source]);
+ }
+ }
+ s = format (s, "]");
+ vlib_cli_output (vm, "%V", s);
+ vec_free(s);
/* Show summary? */
if (! verbose)
diff --git a/src/vnet/fib/ip6_fib.h b/src/vnet/fib/ip6_fib.h
index aad8305c990..9728eecca8b 100644
--- a/src/vnet/fib/ip6_fib.h
+++ b/src/vnet/fib/ip6_fib.h
@@ -144,8 +144,9 @@ ip6_src_lookup_for_packet (ip6_main_t * im,
* \returns A pointer to the retrieved or created fib.
*
*/
-extern u32 ip6_fib_table_find_or_create_and_lock(u32 table_id);
-extern u32 ip6_fib_table_create_and_lock(void);
+extern u32 ip6_fib_table_find_or_create_and_lock(u32 table_id,
+ fib_source_t src);
+extern u32 ip6_fib_table_create_and_lock(fib_source_t src);
static inline ip6_fib_t *
ip6_fib_get (fib_node_index_t index)
diff --git a/src/vnet/fib/mpls_fib.c b/src/vnet/fib/mpls_fib.c
index ca6271fe3d7..4eeef7abb73 100644
--- a/src/vnet/fib/mpls_fib.c
+++ b/src/vnet/fib/mpls_fib.c
@@ -83,7 +83,8 @@ mpls_fib_index_from_table_id (u32 table_id)
}
static u32
-mpls_fib_create_with_table_id (u32 table_id)
+mpls_fib_create_with_table_id (u32 table_id,
+ fib_source_t src)
{
dpo_id_t dpo = DPO_INVALID;
fib_table_t *fib_table;
@@ -107,7 +108,7 @@ mpls_fib_create_with_table_id (u32 table_id)
fib_table->ft_table_id = table_id;
fib_table->ft_flow_hash_config = MPLS_FLOW_HASH_DEFAULT;
- fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_MPLS);
+ fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_MPLS, src);
if (INDEX_INVALID == mpls_fib_drop_dpo_index)
{
@@ -220,22 +221,23 @@ mpls_fib_create_with_table_id (u32 table_id)
}
u32
-mpls_fib_table_find_or_create_and_lock (u32 table_id)
+mpls_fib_table_find_or_create_and_lock (u32 table_id,
+ fib_source_t src)
{
u32 index;
index = mpls_fib_index_from_table_id(table_id);
if (~0 == index)
- return mpls_fib_create_with_table_id(table_id);
+ return mpls_fib_create_with_table_id(table_id, src);
- fib_table_lock(index, FIB_PROTOCOL_MPLS);
+ fib_table_lock(index, FIB_PROTOCOL_MPLS, src);
return (index);
}
u32
-mpls_fib_table_create_and_lock (void)
+mpls_fib_table_create_and_lock (fib_source_t src)
{
- return (mpls_fib_create_with_table_id(~0));
+ return (mpls_fib_create_with_table_id(~0, src));
}
void
diff --git a/src/vnet/fib/mpls_fib.h b/src/vnet/fib/mpls_fib.h
index dfb8b7fc37a..29cd1d20dab 100644
--- a/src/vnet/fib/mpls_fib.h
+++ b/src/vnet/fib/mpls_fib.h
@@ -59,8 +59,9 @@ mpls_fib_get (fib_node_index_t index)
return (pool_elt_at_index(mpls_main.mpls_fibs, index));
}
-extern u32 mpls_fib_table_find_or_create_and_lock(u32 table_id);
-extern u32 mpls_fib_table_create_and_lock(void);
+extern u32 mpls_fib_table_find_or_create_and_lock(u32 table_id,
+ fib_source_t src);
+extern u32 mpls_fib_table_create_and_lock(fib_source_t src);
// extern mpls_fib_t * mpls_fib_find(u32 table_id);
extern u32 mpls_fib_index_from_table_id(u32 table_id);
diff --git a/src/vnet/interface_api.c b/src/vnet/interface_api.c
index 113728cd3c3..419fef94f63 100644
--- a/src/vnet/interface_api.c
+++ b/src/vnet/interface_api.c
@@ -320,68 +320,189 @@ stats_dsunlock (void)
static void
vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp)
{
- int rv = 0;
- u32 table_id = ntohl (mp->vrf_id);
- u32 sw_if_index = ntohl (mp->sw_if_index);
vl_api_sw_interface_set_table_reply_t *rmp;
- CLIB_UNUSED (ip_interface_address_t * ia);
- u32 fib_index;
+ u32 sw_if_index = ntohl (mp->sw_if_index);
+ u32 table_id = ntohl (mp->vrf_id);
+ int rv = 0;
VALIDATE_SW_IF_INDEX (mp);
stats_dslock_with_hint (1 /* release hint */ , 4 /* tag */ );
if (mp->is_ipv6)
+ rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, table_id, 1);
+ else
+ rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, table_id, 1);
+
+ stats_dsunlock ();
+
+ BAD_SW_IF_INDEX_LABEL;
+
+ REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
+}
+
+int
+ip_table_bind (fib_protocol_t fproto,
+ uint32_t sw_if_index, uint32_t table_id, u8 is_api)
+{
+ CLIB_UNUSED (ip_interface_address_t * ia);
+ u32 fib_index, mfib_index;
+ fib_source_t src;
+ mfib_source_t msrc;
+
+ if (is_api)
+ {
+ src = FIB_SOURCE_API;
+ msrc = MFIB_SOURCE_API;
+ }
+ else
+ {
+ src = FIB_SOURCE_CLI;
+ msrc = MFIB_SOURCE_CLI;
+ }
+
+ /*
+ * This is temporary whilst I do the song and dance with the CSIT version
+ */
+ if (0 != table_id)
{
+ fib_index = fib_table_find_or_create_and_lock (fproto, table_id, src);
+ mfib_index =
+ mfib_table_find_or_create_and_lock (fproto, table_id, msrc);
+ }
+ else
+ {
+ fib_index = 0;
+ mfib_index = 0;
+ }
+
+ /*
+ * 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 (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 thoses subnets are valid in the destination VRF.
+ */
/* *INDENT-OFF* */
foreach_ip_interface_address (&ip6_main.lookup_main,
ia, sw_if_index,
1 /* honor unnumbered */ ,
({
- rv = VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE;
- goto done;
+ return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
}));
/* *INDENT-ON* */
- fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
- table_id);
vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
- ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
-
- fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
- table_id);
vec_validate (ip6_main.mfib_index_by_sw_if_index, sw_if_index);
- ip6_main.mfib_index_by_sw_if_index[sw_if_index] = fib_index;
+
+ /*
+ * tell those that are interested that the binding is changing.
+ */
+ ip6_table_bind_callback_t *cb;
+ vec_foreach (cb, ip6_main.table_bind_callbacks)
+ cb->function (&ip6_main, cb->function_opaque,
+ sw_if_index,
+ fib_index,
+ ip6_main.fib_index_by_sw_if_index[sw_if_index]);
+
+ if (0 == table_id)
+ {
+ /* reset back to default */
+ 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, src);
+ 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, msrc);
+
+ }
+ else
+ {
+ /* we need to lock the table now it's inuse */
+ fib_table_lock (fib_index, FIB_PROTOCOL_IP6, src);
+ mfib_table_lock (mfib_index, FIB_PROTOCOL_IP6, msrc);
+ }
+
+ 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 thoses subnets are valid in the destination VRF.
+ */
/* *INDENT-OFF* */
foreach_ip_interface_address (&ip4_main.lookup_main,
ia, sw_if_index,
1 /* honor unnumbered */ ,
({
- rv = VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE;
- goto done;
+ return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
}));
/* *INDENT-ON* */
- fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
- table_id);
vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index);
- ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
-
- fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
- table_id);
vec_validate (ip4_main.mfib_index_by_sw_if_index, sw_if_index);
- ip4_main.mfib_index_by_sw_if_index[sw_if_index] = fib_index;
- }
-done:
- stats_dsunlock ();
+ /*
+ * tell those that are interested that the binding is changing.
+ */
+ ip4_table_bind_callback_t *cb;
+ vec_foreach (cb, ip4_main.table_bind_callbacks)
+ cb->function (&ip4_main, cb->function_opaque,
+ sw_if_index,
+ fib_index,
+ ip4_main.fib_index_by_sw_if_index[sw_if_index]);
+
+ if (0 == table_id)
+ {
+ /* reset back to default */
+ 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, src);
+ 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, msrc);
- BAD_SW_IF_INDEX_LABEL;
+ }
+ else
+ {
+ /* we need to lock the table now it's inuse */
+ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
+ table_id, src);
- REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
+ mfib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
+ table_id, msrc);
+ }
+
+ 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;
+ }
+
+ /*
+ * Temporary. undo the locks from the find and create at the staart
+ */
+ if (0 != table_id)
+ {
+ fib_table_unlock (fib_index, fproto, src);
+ mfib_table_unlock (mfib_index, fproto, msrc);
+ }
+
+ return (0);
}
static void
diff --git a/src/vnet/ip/ip.h b/src/vnet/ip/ip.h
index 70b4ccd8dd7..7aae73ff64a 100644
--- a/src/vnet/ip/ip.h
+++ b/src/vnet/ip/ip.h
@@ -184,6 +184,13 @@ void ip_del_all_interface_addresses (vlib_main_t * vm, u32 sw_if_index);
extern vlib_node_registration_t ip4_inacl_node;
extern vlib_node_registration_t ip6_inacl_node;
+void ip_table_create (fib_protocol_t fproto, uint32_t table_id, u8 is_api);
+
+void ip_table_delete (fib_protocol_t fproto, uint32_t table_id, u8 is_api);
+
+int ip_table_bind (fib_protocol_t fproto,
+ uint32_t sw_if_index, uint32_t table_id, u8 is_api);
+
#endif /* included_ip_main_h */
/*
diff --git a/src/vnet/ip/ip4.h b/src/vnet/ip/ip4.h
index 8f9a8e27bf5..decb840b390 100644
--- a/src/vnet/ip/ip4.h
+++ b/src/vnet/ip/ip4.h
@@ -72,6 +72,16 @@ typedef struct
uword function_opaque;
} ip4_add_del_interface_address_callback_t;
+typedef void (ip4_table_bind_function_t)
+ (struct ip4_main_t * im,
+ uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index);
+
+typedef struct
+{
+ ip4_table_bind_function_t *function;
+ uword function_opaque;
+} ip4_table_bind_callback_t;
+
/**
* @brief IPv4 main type.
*
@@ -117,6 +127,9 @@ typedef struct ip4_main_t
ip4_add_del_interface_address_callback_t
* add_del_interface_address_callbacks;
+ /** Functions to call when interface to table biding changes. */
+ ip4_table_bind_callback_t *table_bind_callbacks;
+
/** Template used to generate IP4 ARP packets. */
vlib_packet_template_t ip4_arp_request_packet_template;
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index 2d48e8a9ab5..ec4287bb008 100755
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -1198,8 +1198,10 @@ ip4_lookup_init (vlib_main_t * vm)
ip_lookup_init (&im->lookup_main, /* is_ip6 */ 0);
/* Create FIB with index 0 and table id of 0. */
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0);
- mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0);
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0,
+ FIB_SOURCE_DEFAULT_ROUTE);
+ mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0,
+ MFIB_SOURCE_DEFAULT_ROUTE);
{
pg_node_t *pn;
@@ -2794,101 +2796,6 @@ VLIB_REGISTER_NODE (ip4_midchain_node) = {
VLIB_NODE_FUNCTION_MULTIARCH (ip4_midchain_node, ip4_midchain);
/* *INDENT-ON */
-static clib_error_t *
-add_del_interface_table (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- vnet_main_t *vnm = vnet_get_main ();
- ip_interface_address_t *ia;
- clib_error_t *error = 0;
- u32 sw_if_index, table_id;
-
- sw_if_index = ~0;
-
- if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
- {
- error = clib_error_return (0, "unknown interface `%U'",
- format_unformat_error, input);
- goto done;
- }
-
- if (unformat (input, "%d", &table_id))
- ;
- else
- {
- error = clib_error_return (0, "expected table id `%U'",
- format_unformat_error, input);
- goto done;
- }
-
- /*
- * 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 thoses subnets are valid in the destination VRF.
- */
- /* *INDENT-OFF* */
- foreach_ip_interface_address (&ip4_main.lookup_main,
- ia, sw_if_index,
- 1 /* honor unnumbered */,
- ({
- ip4_address_t * a;
-
- a = ip_interface_address_get_address (&ip4_main.lookup_main, ia);
- error = clib_error_return (0, "interface %U has address %U",
- format_vnet_sw_if_index_name, vnm,
- sw_if_index,
- format_ip4_address, a);
- goto done;
- }));
- /* *INDENT-ON* */
-
-{
- ip4_main_t *im = &ip4_main;
- u32 fib_index;
-
- fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
-
- vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
- im->fib_index_by_sw_if_index[sw_if_index] = fib_index;
-
- fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
- vec_validate (im->mfib_index_by_sw_if_index, sw_if_index);
- im->mfib_index_by_sw_if_index[sw_if_index] = fib_index;
-}
-
-done:
-return error;
-}
-
-/*?
- * Place the indicated interface into the supplied IPv4 FIB table (also known
- * as a VRF). If the FIB table does not exist, this command creates it. To
- * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
- * FIB table will only be displayed if a route has been added to the table, or
- * an IP Address is assigned to an interface in the table (which adds a route
- * automatically).
- *
- * @note IP addresses added after setting the interface IP table are added to
- * the indicated FIB table. If an IP address is added prior to changing the
- * table then this is an error. The control plane must remove these addresses
- * first and then change the table. VPP will not automatically move the
- * addresses from the old to the new table as it does not know the validity
- * of such a change.
- *
- * @cliexpar
- * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id):
- * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
- ?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
-{
- .path = "set interface ip table",
- .function = add_del_interface_table,
- .short_help = "set interface ip table <interface> <table-id>",
-};
-/* *INDENT-ON* */
-
int
ip4_lookup_validate (ip4_address_t * a, u32 fib_index0)
{
diff --git a/src/vnet/ip/ip4_source_and_port_range_check.c b/src/vnet/ip/ip4_source_and_port_range_check.c
index ae836a113a5..9aa880aee32 100644
--- a/src/vnet/ip/ip4_source_and_port_range_check.c
+++ b/src/vnet/ip/ip4_source_and_port_range_check.c
@@ -1126,6 +1126,14 @@ ip6_source_and_port_range_check_add_del (ip6_address_t * address,
u16 * low_ports,
u16 * high_ports, int is_add)
{
+ uint32_t fib_index;
+
+ fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
+
+ ASSERT (~0 != fib_index);
+
+ fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_CLASSIFY);
+
return 0;
}
@@ -1138,7 +1146,8 @@ ip4_source_and_port_range_check_add_del (ip4_address_t * address,
{
u32 fib_index;
- fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id);
+ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
+ FIB_SOURCE_CLASSIFY);
if (is_add == 0)
{
diff --git a/src/vnet/ip/ip6.h b/src/vnet/ip/ip6.h
index fa922725d4a..8aef53a9dcb 100644
--- a/src/vnet/ip/ip6.h
+++ b/src/vnet/ip/ip6.h
@@ -103,6 +103,16 @@ typedef struct
uword function_opaque;
} ip6_add_del_interface_address_callback_t;
+typedef void (ip6_table_bind_function_t)
+ (struct ip6_main_t * im,
+ uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index);
+
+typedef struct
+{
+ ip6_table_bind_function_t *function;
+ uword function_opaque;
+} ip6_table_bind_callback_t;
+
/**
* Enumeration of the FIB table instance types
*/
@@ -183,6 +193,9 @@ typedef struct ip6_main_t
ip6_add_del_interface_address_callback_t
* add_del_interface_address_callbacks;
+ /** Functions to call when interface to table biding changes. */
+ ip6_table_bind_callback_t *table_bind_callbacks;
+
/* Template used to generate IP6 neighbor solicitation packets. */
vlib_packet_template_t discover_neighbor_packet_template;
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index 5832bd0b505..1002f6b6dd9 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -2999,8 +2999,10 @@ ip6_lookup_init (vlib_main_t * vm)
im->lookup_table_nbuckets, im->lookup_table_size);
/* Create FIB with index 0 and table id of 0. */
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0);
- mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0);
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0,
+ FIB_SOURCE_DEFAULT_ROUTE);
+ mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0,
+ MFIB_SOURCE_DEFAULT_ROUTE);
{
pg_node_t *pn;
@@ -3045,103 +3047,6 @@ ip6_lookup_init (vlib_main_t * vm)
VLIB_INIT_FUNCTION (ip6_lookup_init);
-static clib_error_t *
-add_del_ip6_interface_table (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- vnet_main_t *vnm = vnet_get_main ();
- ip_interface_address_t *ia;
- clib_error_t *error = 0;
- u32 sw_if_index, table_id;
-
- sw_if_index = ~0;
-
- if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
- {
- error = clib_error_return (0, "unknown interface `%U'",
- format_unformat_error, input);
- goto done;
- }
-
- if (unformat (input, "%d", &table_id))
- ;
- else
- {
- error = clib_error_return (0, "expected table id `%U'",
- format_unformat_error, input);
- goto done;
- }
-
- /*
- * 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 thoses subnets are valid in the destination VRF.
- */
- /* *INDENT-OFF* */
- foreach_ip_interface_address (&ip6_main.lookup_main,
- ia, sw_if_index,
- 1 /* honor unnumbered */,
- ({
- ip4_address_t * a;
-
- a = ip_interface_address_get_address (&ip6_main.lookup_main, ia);
- error = clib_error_return (0, "interface %U has address %U",
- format_vnet_sw_if_index_name, vnm,
- sw_if_index,
- format_ip6_address, a);
- goto done;
- }));
- /* *INDENT-ON* */
-
- {
- u32 fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
- table_id);
-
- vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
- ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
-
- fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
- table_id);
-
- vec_validate (ip6_main.mfib_index_by_sw_if_index, sw_if_index);
- ip6_main.mfib_index_by_sw_if_index[sw_if_index] = fib_index;
- }
-
-
-done:
- return error;
-}
-
-/*?
- * Place the indicated interface into the supplied IPv6 FIB table (also known
- * as a VRF). If the FIB table does not exist, this command creates it. To
- * display the current IPv6 FIB table, use the command '<em>show ip6 fib</em>'.
- * FIB table will only be displayed if a route has been added to the table, or
- * an IP Address is assigned to an interface in the table (which adds a route
- * automatically).
- *
- * @note IP addresses added after setting the interface IP table are added to
- * the indicated FIB table. If an IP address is added prior to changing the
- * table then this is an error. The control plane must remove these addresses
- * first and then change the table. VPP will not automatically move the
- * addresses from the old to the new table as it does not know the validity
- * of such a change.
- *
- * @cliexpar
- * Example of how to add an interface to an IPv6 FIB table (where 2 is the table-id):
- * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2}
- ?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) =
-{
- .path = "set interface ip6 table",
- .function = add_del_ip6_interface_table,
- .short_help = "set interface ip6 table <interface> <table-id>"
-};
-/* *INDENT-ON* */
-
void
ip6_link_local_address_from_ethernet_mac_address (ip6_address_t * ip,
u8 * mac)
diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c
index 62cf23ac3f5..56f33ac821d 100644
--- a/src/vnet/ip/ip6_neighbor.c
+++ b/src/vnet/ip/ip6_neighbor.c
@@ -250,6 +250,26 @@ format_ip6_neighbor_ip6_entry (u8 * s, va_list * va)
return s;
}
+static void
+ip6_neighbor_adj_fib_remove (ip6_neighbor_t * n, uint32_t fib_index)
+{
+ if (FIB_NODE_INDEX_INVALID != n->fib_entry_index)
+ {
+ fib_prefix_t pfx = {
+ .fp_len = 128,
+ .fp_proto = FIB_PROTOCOL_IP6,
+ .fp_addr.ip6 = n->key.ip6_address,
+ };
+ fib_table_entry_path_remove (fib_index,
+ &pfx,
+ FIB_SOURCE_ADJ,
+ DPO_PROTO_IP6,
+ &pfx.fp_addr,
+ n->key.sw_if_index, ~0,
+ 1, FIB_ROUTE_PATH_FLAG_NONE);
+ }
+}
+
static clib_error_t *
ip6_neighbor_sw_interface_up_down (vnet_main_t * vnm,
u32 sw_if_index, u32 flags)
@@ -273,22 +293,10 @@ ip6_neighbor_sw_interface_up_down (vnet_main_t * vnm,
{
n = pool_elt_at_index (nm->neighbor_pool, to_delete[i]);
mhash_unset (&nm->neighbor_index_by_key, &n->key, 0);
- if (FIB_NODE_INDEX_INVALID != n->fib_entry_index)
- {
- fib_prefix_t pfx = {
- .fp_len = 128,
- .fp_proto = FIB_PROTOCOL_IP6,
- .fp_addr.ip6 = n->key.ip6_address,
- };
- fib_table_entry_path_remove
- (ip6_fib_table_get_index_for_sw_if_index (n->key.sw_if_index),
- &pfx,
- FIB_SOURCE_ADJ,
- DPO_PROTO_IP6,
- &pfx.fp_addr,
- n->key.sw_if_index, ~0, 1, FIB_ROUTE_PATH_FLAG_NONE);
- pool_put (nm->neighbor_pool, n);
- }
+ ip6_neighbor_adj_fib_remove (n,
+ ip6_fib_table_get_index_for_sw_if_index
+ (n->key.sw_if_index));
+ pool_put (nm->neighbor_pool, n);
}
vec_free (to_delete);
}
@@ -579,6 +587,24 @@ ip6_ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
}
}
+
+static void
+ip6_neighbor_adj_fib_add (ip6_neighbor_t * n, uint32_t fib_index)
+{
+ fib_prefix_t pfx = {
+ .fp_len = 128,
+ .fp_proto = FIB_PROTOCOL_IP6,
+ .fp_addr.ip6 = n->key.ip6_address,
+ };
+
+ n->fib_entry_index =
+ fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
+ FIB_ENTRY_FLAG_ATTACHED,
+ DPO_PROTO_IP6, &pfx.fp_addr,
+ n->key.sw_if_index, ~0, 1, NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+}
+
int
vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
u32 sw_if_index,
@@ -633,21 +659,9 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
*/
if (!is_no_fib_entry)
{
- fib_prefix_t pfx = {
- .fp_len = 128,
- .fp_proto = FIB_PROTOCOL_IP6,
- .fp_addr.ip6 = k.ip6_address,
- };
- u32 fib_index;
-
- fib_index =
- ip6_fib_table_get_index_for_sw_if_index (n->key.sw_if_index);
- n->fib_entry_index =
- fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
- FIB_ENTRY_FLAG_ATTACHED,
- DPO_PROTO_IP6, &pfx.fp_addr,
- n->key.sw_if_index, ~0, 1, NULL,
- FIB_ROUTE_PATH_FLAG_NONE);
+ ip6_neighbor_adj_fib_add (n,
+ ip6_fib_table_get_index_for_sw_if_index
+ (n->key.sw_if_index));
}
else
{
@@ -3843,6 +3857,33 @@ ip6_set_neighbor_limit (u32 neighbor_limit)
return 0;
}
+static void
+ip6_neighbor_table_bind (ip6_main_t * im,
+ uword opaque,
+ u32 sw_if_index,
+ u32 new_fib_index, u32 old_fib_index)
+{
+ ip6_neighbor_main_t *nm = &ip6_neighbor_main;
+ ip6_neighbor_t *n = NULL;
+ u32 i, *to_re_add = 0;
+
+ /* *INDENT-OFF* */
+ pool_foreach (n, nm->neighbor_pool,
+ ({
+ if (n->key.sw_if_index == sw_if_index)
+ vec_add1 (to_re_add, n - nm->neighbor_pool);
+ }));
+ /* *INDENT-ON* */
+
+ for (i = 0; i < vec_len (to_re_add); i++)
+ {
+ n = pool_elt_at_index (nm->neighbor_pool, to_re_add[i]);
+ ip6_neighbor_adj_fib_remove (n, old_fib_index);
+ ip6_neighbor_adj_fib_add (n, new_fib_index);
+ }
+ vec_free (to_re_add);
+}
+
static clib_error_t *
ip6_neighbor_init (vlib_main_t * vm)
{
@@ -3874,6 +3915,11 @@ ip6_neighbor_init (vlib_main_t * vm)
cb.function_opaque = 0;
vec_add1 (im->add_del_interface_address_callbacks, cb);
+ ip6_table_bind_callback_t cbt;
+ cbt.function = ip6_neighbor_table_bind;
+ cbt.function_opaque = 0;
+ vec_add1 (im->table_bind_callbacks, cbt);
+
mhash_init (&nm->pending_resolutions_by_address,
/* value size */ sizeof (uword),
/* key size */ sizeof (ip6_address_t));
diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c
index bba65ab4923..384ec3e0ec4 100644
--- a/src/vnet/ip/ip_api.c
+++ b/src/vnet/ip/ip_api.c
@@ -700,11 +700,57 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp,
}
void
+ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api)
+{
+ u32 fib_index, mfib_index;
+
+ /*
+ * ignore action on the default table - this is always present
+ * and cannot be added nor deleted from the API
+ */
+ if (0 != table_id)
+ {
+ /*
+ * The API holds only one lock on the table.
+ * i.e. it can be added many times via the API but needs to be
+ * deleted only once.
+ * The FIB index for unicast and multicast is not necessarily the
+ * same, since internal VPP systesm (like LISP and SR) create
+ * their own unicast tables.
+ */
+ fib_index = fib_table_find (fproto, table_id);
+ mfib_index = mfib_table_find (fproto, table_id);
+
+ if (~0 != fib_index)
+ {
+ fib_table_unlock (fib_index, fproto,
+ (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI));
+ }
+ if (~0 != mfib_index)
+ {
+ mfib_table_unlock (mfib_index, fproto,
+ (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI));
+ }
+ }
+}
+
+void
vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
{
vl_api_ip_table_add_del_reply_t *rmp;
+ fib_protocol_t fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
+ u32 table_id = ntohl (mp->table_id);
int rv = 0;
+ if (mp->is_add)
+ {
+ ip_table_create (fproto, table_id, 1);
+ }
+ else
+ {
+ ip_table_delete (fproto, table_id, 1);
+ }
+
REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY);
}
@@ -866,18 +912,21 @@ add_del_route_check (fib_protocol_t table_proto,
u32 next_hop_sw_if_index,
dpo_proto_t next_hop_table_proto,
u32 next_hop_table_id,
- u8 create_missing_tables,
u8 is_rpf_id, u32 * fib_index, u32 * next_hop_fib_index)
{
vnet_main_t *vnm = vnet_get_main ();
+ /* Temporaray whilst I do the CSIT dance */
+ u8 create_missing_tables = 1;
+
*fib_index = fib_table_find (table_proto, ntohl (table_id));
if (~0 == *fib_index)
{
if (create_missing_tables)
{
*fib_index = fib_table_find_or_create_and_lock (table_proto,
- ntohl (table_id));
+ ntohl (table_id),
+ FIB_SOURCE_API);
}
else
{
@@ -918,12 +967,14 @@ add_del_route_check (fib_protocol_t table_proto,
*next_hop_fib_index =
mfib_table_find_or_create_and_lock (fib_nh_proto,
ntohl
- (next_hop_table_id));
+ (next_hop_table_id),
+ MFIB_SOURCE_API);
else
*next_hop_fib_index =
fib_table_find_or_create_and_lock (fib_nh_proto,
ntohl
- (next_hop_table_id));
+ (next_hop_table_id),
+ FIB_SOURCE_API);
}
else
{
@@ -948,8 +999,7 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
mp->next_hop_sw_if_index,
DPO_PROTO_IP4,
mp->next_hop_table_id,
- mp->create_vrf_if_needed, 0,
- &fib_index, &next_hop_fib_index);
+ 0, &fib_index, &next_hop_fib_index);
if (0 != rv)
return (rv);
@@ -1008,8 +1058,7 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
mp->next_hop_sw_if_index,
DPO_PROTO_IP6,
mp->next_hop_table_id,
- mp->create_vrf_if_needed, 0,
- &fib_index, &next_hop_fib_index);
+ 0, &fib_index, &next_hop_fib_index);
if (0 != rv)
return (rv);
@@ -1074,27 +1123,57 @@ vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
REPLY_MACRO (VL_API_IP_ADD_DEL_ROUTE_REPLY);
}
+void
+ip_table_create (fib_protocol_t fproto, u32 table_id, u8 is_api)
+{
+ u32 fib_index, mfib_index;
+
+ /*
+ * ignore action on the default table - this is always present
+ * and cannot be added nor deleted from the API
+ */
+ if (0 != table_id)
+ {
+ /*
+ * The API holds only one lock on the table.
+ * i.e. it can be added many times via the API but needs to be
+ * deleted only once.
+ * The FIB index for unicast and multicast is not necessarily the
+ * same, since internal VPP systesm (like LISP and SR) create
+ * their own unicast tables.
+ */
+ fib_index = fib_table_find (fproto, table_id);
+ mfib_index = mfib_table_find (fproto, table_id);
+
+ if (~0 == fib_index)
+ {
+ fib_table_find_or_create_and_lock (fproto, table_id,
+ (is_api ?
+ FIB_SOURCE_API :
+ FIB_SOURCE_CLI));
+ }
+ if (~0 == mfib_index)
+ {
+ mfib_table_find_or_create_and_lock (fproto, table_id,
+ (is_api ?
+ MFIB_SOURCE_API :
+ MFIB_SOURCE_CLI));
+ }
+ }
+}
+
static int
add_del_mroute_check (fib_protocol_t table_proto,
u32 table_id,
- u32 next_hop_sw_if_index,
- u8 is_local, u8 create_missing_tables, u32 * fib_index)
+ u32 next_hop_sw_if_index, u8 is_local, u32 * fib_index)
{
vnet_main_t *vnm = vnet_get_main ();
*fib_index = mfib_table_find (table_proto, ntohl (table_id));
if (~0 == *fib_index)
{
- if (create_missing_tables)
- {
- *fib_index = mfib_table_find_or_create_and_lock (table_proto,
- ntohl (table_id));
- }
- else
- {
- /* No such VRF, and we weren't asked to create one */
- return VNET_API_ERROR_NO_SUCH_FIB;
- }
+ /* No such table */
+ return VNET_API_ERROR_NO_SUCH_FIB;
}
if (~0 != ntohl (next_hop_sw_if_index))
@@ -1163,8 +1242,7 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
rv = add_del_mroute_check (fproto,
mp->table_id,
mp->next_hop_sw_if_index,
- mp->is_local,
- mp->create_vrf_if_needed, &fib_index);
+ mp->is_local, &fib_index);
if (0 != rv)
return (rv);
diff --git a/src/vnet/ip/lookup.c b/src/vnet/ip/lookup.c
index 5537bb04a40..667c67914d5 100755
--- a/src/vnet/ip/lookup.c
+++ b/src/vnet/ip/lookup.c
@@ -687,6 +687,78 @@ done:
return error;
}
+clib_error_t *
+vnet_ip_table_cmd (vlib_main_t * vm,
+ unformat_input_t * main_input,
+ vlib_cli_command_t * cmd, fib_protocol_t fproto)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t *error = NULL;
+ u32 table_id, is_add;
+
+ is_add = 1;
+ table_id = ~0;
+
+ /* Get a line of input. */
+ if (!unformat_user (main_input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "%d", &table_id))
+ ;
+ else if (unformat (line_input, "del"))
+ is_add = 0;
+ else if (unformat (line_input, "add"))
+ is_add = 1;
+ else
+ {
+ error = unformat_parse_error (line_input);
+ goto done;
+ }
+ }
+
+ if (~0 == table_id)
+ {
+ error = clib_error_return (0, "No table id");
+ goto done;
+ }
+ else if (0 == table_id)
+ {
+ error = clib_error_return (0, "Can't change the default table");
+ goto done;
+ }
+ else
+ {
+ if (is_add)
+ {
+ ip_table_create (fproto, table_id, 0);
+ }
+ else
+ {
+ ip_table_delete (fproto, table_id, 0);
+ }
+ }
+
+done:
+ unformat_free (line_input);
+ return error;
+}
+
+clib_error_t *
+vnet_ip4_table_cmd (vlib_main_t * vm,
+ unformat_input_t * main_input, vlib_cli_command_t * cmd)
+{
+ return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP4));
+}
+
+clib_error_t *
+vnet_ip6_table_cmd (vlib_main_t * vm,
+ unformat_input_t * main_input, vlib_cli_command_t * cmd)
+{
+ return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP6));
+}
+
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (vlib_cli_ip_command, static) = {
.path = "ip",
@@ -749,6 +821,159 @@ VLIB_CLI_COMMAND (ip_route_command, static) = {
.function = vnet_ip_route_cmd,
.is_mp_safe = 1,
};
+
+/* *INDENT-ON* */
+/*?
+ * This command is used to add or delete IPv4 Tables. All
+ * Tables must be explicitly added before that can be used. Creating a
+ * table will add both unicast and multicast FIBs
+ *
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (ip4_table_command, static) = {
+ .path = "ip table",
+ .short_help = "ip table [add|del] <table-id>",
+ .function = vnet_ip4_table_cmd,
+ .is_mp_safe = 1,
+};
+/* *INDENT-ON* */
+
+/* *INDENT-ON* */
+/*?
+ * This command is used to add or delete IPv4 Tables. All
+ * Tables must be explicitly added before that can be used. Creating a
+ * table will add both unicast and multicast FIBs
+ *
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (ip6_table_command, static) = {
+ .path = "ip6 table",
+ .short_help = "ip6 table [add|del] <table-id>",
+ .function = vnet_ip6_table_cmd,
+ .is_mp_safe = 1,
+};
+
+static clib_error_t *
+ip_table_bind_cmd (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd,
+ fib_protocol_t fproto)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ clib_error_t *error = 0;
+ u32 sw_if_index, table_id;
+ int rv;
+
+ sw_if_index = ~0;
+
+ if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
+ {
+ error = clib_error_return (0, "unknown interface `%U'",
+ format_unformat_error, input);
+ goto done;
+ }
+
+ if (unformat (input, "%d", &table_id))
+ ;
+ else
+ {
+ error = clib_error_return (0, "expected table id `%U'",
+ format_unformat_error, input);
+ goto done;
+ }
+
+ rv = ip_table_bind (fproto, sw_if_index, table_id, 0);
+
+ if (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE == rv)
+ {
+ error = clib_error_return (0, "IP addresses are still present on %U",
+ format_vnet_sw_if_index_name,
+ vnet_get_main(),
+ sw_if_index);
+ }
+ else if (VNET_API_ERROR_NO_SUCH_FIB == rv)
+ {
+ error = clib_error_return (0, "no such table %d", table_id);
+ }
+ else if (0 != rv)
+ {
+ error = clib_error_return (0, "unknown error");
+ }
+
+ done:
+ return error;
+}
+
+static clib_error_t *
+ip4_table_bind_cmd (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP4));
+}
+
+static clib_error_t *
+ip6_table_bind_cmd (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP6));
+}
+
+/*?
+ * Place the indicated interface into the supplied IPv4 FIB table (also known
+ * as a VRF). If the FIB table does not exist, this command creates it. To
+ * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
+ * FIB table will only be displayed if a route has been added to the table, or
+ * an IP Address is assigned to an interface in the table (which adds a route
+ * automatically).
+ *
+ * @note IP addresses added after setting the interface IP table are added to
+ * the indicated FIB table. If an IP address is added prior to changing the
+ * table then this is an error. The control plane must remove these addresses
+ * first and then change the table. VPP will not automatically move the
+ * addresses from the old to the new table as it does not know the validity
+ * of such a change.
+ *
+ * @cliexpar
+ * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id):
+ * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
+{
+ .path = "set interface ip table",
+ .function = ip4_table_bind_cmd,
+ .short_help = "set interface ip table <interface> <table-id>",
+};
+/* *INDENT-ON* */
+
+/*?
+ * Place the indicated interface into the supplied IPv6 FIB table (also known
+ * as a VRF). If the FIB table does not exist, this command creates it. To
+ * display the current IPv6 FIB table, use the command '<em>show ip6 fib</em>'.
+ * FIB table will only be displayed if a route has been added to the table, or
+ * an IP Address is assigned to an interface in the table (which adds a route
+ * automatically).
+ *
+ * @note IP addresses added after setting the interface IP table are added to
+ * the indicated FIB table. If an IP address is added prior to changing the
+ * table then this is an error. The control plane must remove these addresses
+ * first and then change the table. VPP will not automatically move the
+ * addresses from the old to the new table as it does not know the validity
+ * of such a change.
+ *
+ * @cliexpar
+ * Example of how to add an interface to an IPv6 FIB table (where 2 is the table-id):
+ * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2}
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) =
+{
+ .path = "set interface ip6 table",
+ .function = ip6_table_bind_cmd,
+ .short_help = "set interface ip6 table <interface> <table-id>"
+};
/* *INDENT-ON* */
clib_error_t *
diff --git a/src/vnet/lisp-gpe/interface.c b/src/vnet/lisp-gpe/interface.c
index e832c23fd8e..a0c05e85682 100644
--- a/src/vnet/lisp-gpe/interface.c
+++ b/src/vnet/lisp-gpe/interface.c
@@ -505,12 +505,14 @@ lisp_gpe_iface_set_table (u32 sw_if_index, u32 table_id)
{
fib_node_index_t fib_index;
- fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
+ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id,
+ FIB_SOURCE_LISP);
vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index);
ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
ip4_sw_interface_enable_disable (sw_if_index, 1);
- fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id);
+ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id,
+ FIB_SOURCE_LISP);
vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
ip6_sw_interface_enable_disable (sw_if_index, 1);
@@ -530,7 +532,7 @@ lisp_gpe_tenant_del_default_routes (u32 table_id)
fib_index = fib_table_find (prefix.fp_proto, table_id);
fib_table_entry_special_remove (fib_index, &prefix, FIB_SOURCE_LISP);
- fib_table_unlock (fib_index, prefix.fp_proto);
+ fib_table_unlock (fib_index, prefix.fp_proto, FIB_SOURCE_LISP);
}
}
@@ -549,7 +551,8 @@ lisp_gpe_tenant_add_default_routes (u32 table_id)
/*
* Add a deafult route that results in a control plane punt DPO
*/
- fib_index = fib_table_find_or_create_and_lock (prefix.fp_proto, table_id);
+ fib_index = fib_table_find_or_create_and_lock (prefix.fp_proto, table_id,
+ FIB_SOURCE_LISP);
fib_table_entry_special_dpo_add (fib_index, &prefix, FIB_SOURCE_LISP,
FIB_ENTRY_FLAG_EXCLUSIVE,
lisp_cp_dpo_get (fib_proto_to_dpo
diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
index d7d3cb8652f..0a8dc039909 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
+++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
@@ -66,6 +66,7 @@ ip_dst_fib_add_route (u32 dst_fib_index, const ip_prefix_t * dst_prefix)
/* create a new src FIB. */
src_fib_index =
fib_table_create_and_lock (dst_fib_prefix.fp_proto,
+ FIB_SOURCE_LISP,
"LISP-src for [%d,%U]",
dst_fib_index,
format_fib_prefix, &dst_fib_prefix);
@@ -180,7 +181,8 @@ ip_src_dst_fib_del_route (u32 src_fib_index,
*/
fib_table_entry_special_remove (dst_fib_index,
&dst_fib_prefix, FIB_SOURCE_LISP);
- fib_table_unlock (src_fib_index, src_fib_prefix.fp_proto);
+ fib_table_unlock (src_fib_index, src_fib_prefix.fp_proto,
+ FIB_SOURCE_LISP);
}
}
@@ -544,7 +546,8 @@ add_ip_fwd_entry (lisp_gpe_main_t * lgm,
lfe->tenant = lisp_gpe_tenant_find_or_create (lfe->key->vni);
lfe->eid_table_id = a->table_id;
lfe->eid_fib_index = fib_table_find_or_create_and_lock (fproto,
- lfe->eid_table_id);
+ lfe->eid_table_id,
+ FIB_SOURCE_LISP);
lfe->is_src_dst = a->is_src_dst;
if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type)
@@ -578,7 +581,7 @@ del_ip_fwd_entry_i (lisp_gpe_main_t * lgm, lisp_gpe_fwd_entry_t * lfe)
fproto = (IP4 == ip_prefix_version (&fid_addr_ippref (&lfe->key->rmt)) ?
FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6);
- fib_table_unlock (lfe->eid_fib_index, fproto);
+ fib_table_unlock (lfe->eid_fib_index, fproto, FIB_SOURCE_LISP);
hash_unset_mem (lgm->lisp_gpe_fwd_entries, lfe->key);
clib_mem_free (lfe->key);
diff --git a/src/vnet/lisp-gpe/lisp_gpe_sub_interface.c b/src/vnet/lisp-gpe/lisp_gpe_sub_interface.c
index b234d9dc581..26664f53104 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_sub_interface.c
+++ b/src/vnet/lisp-gpe/lisp_gpe_sub_interface.c
@@ -89,13 +89,15 @@ lisp_gpe_sub_interface_set_table (u32 sw_if_index, u32 table_id)
{
fib_node_index_t fib_index;
- fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
+ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id,
+ FIB_SOURCE_LISP);
ASSERT (FIB_NODE_INDEX_INVALID != fib_index);
vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index);
ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
- fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id);
+ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id,
+ FIB_SOURCE_LISP);
ASSERT (FIB_NODE_INDEX_INVALID != fib_index);
vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
@@ -105,9 +107,13 @@ lisp_gpe_sub_interface_set_table (u32 sw_if_index, u32 table_id)
static void
lisp_gpe_sub_interface_unset_table (u32 sw_if_index, u32 table_id)
{
+ fib_table_unlock (ip4_main.fib_index_by_sw_if_index[sw_if_index],
+ FIB_PROTOCOL_IP4, FIB_SOURCE_LISP);
ip4_main.fib_index_by_sw_if_index[sw_if_index] = 0;
ip4_sw_interface_enable_disable (sw_if_index, 0);
+ fib_table_unlock (ip6_main.fib_index_by_sw_if_index[sw_if_index],
+ FIB_PROTOCOL_IP6, FIB_SOURCE_LISP);
ip6_main.fib_index_by_sw_if_index[sw_if_index] = 0;
ip6_sw_interface_enable_disable (sw_if_index, 0);
}
@@ -185,6 +191,7 @@ lisp_gpe_sub_interface_unlock (index_t l3si)
l3s = lisp_gpe_sub_interface_get_i (l3si);
+ ASSERT (0 != l3s->locks);
l3s->locks--;
if (0 == l3s->locks)
diff --git a/src/vnet/mfib/ip4_mfib.c b/src/vnet/mfib/ip4_mfib.c
index 1849a3a4201..b2482580678 100644
--- a/src/vnet/mfib/ip4_mfib.c
+++ b/src/vnet/mfib/ip4_mfib.c
@@ -33,7 +33,8 @@ static const mfib_prefix_t ip4_specials[] = {
};
static u32
-ip4_create_mfib_with_table_id (u32 table_id)
+ip4_create_mfib_with_table_id (u32 table_id,
+ mfib_source_t src)
{
mfib_table_t *mfib_table;
@@ -53,7 +54,7 @@ ip4_create_mfib_with_table_id (u32 table_id)
mfib_table->v4.table_id =
table_id;
- mfib_table_lock(mfib_table->mft_index, FIB_PROTOCOL_IP4);
+ mfib_table_lock(mfib_table->mft_index, FIB_PROTOCOL_IP4, src);
/*
* add the special entries into the new FIB
@@ -113,14 +114,15 @@ ip4_mfib_table_destroy (ip4_mfib_t *mfib)
}
u32
-ip4_mfib_table_find_or_create_and_lock (u32 table_id)
+ip4_mfib_table_find_or_create_and_lock (u32 table_id,
+ mfib_source_t src)
{
u32 index;
index = ip4_mfib_index_from_table_id(table_id);
if (~0 == index)
- return ip4_create_mfib_with_table_id(table_id);
- mfib_table_lock(index, FIB_PROTOCOL_IP4);
+ return ip4_create_mfib_with_table_id(table_id, src);
+ mfib_table_lock(index, FIB_PROTOCOL_IP4, src);
return (index);
}
diff --git a/src/vnet/mfib/ip4_mfib.h b/src/vnet/mfib/ip4_mfib.h
index ea682651767..e31fb744b9b 100644
--- a/src/vnet/mfib/ip4_mfib.h
+++ b/src/vnet/mfib/ip4_mfib.h
@@ -72,8 +72,9 @@ ip4_mfib_get (u32 index)
* @returns A pointer to the retrieved or created fib.
*
*/
-extern u32 ip4_mfib_table_find_or_create_and_lock(u32 table_id);
-extern u32 ip4_mfib_table_create_and_lock(void);
+extern u32 ip4_mfib_table_find_or_create_and_lock(u32 table_id,
+ mfib_source_t src);
+extern u32 ip4_mfib_table_create_and_lock(mfib_source_t src);
static inline
u32 ip4_mfib_index_from_table_id (u32 table_id)
diff --git a/src/vnet/mfib/ip6_mfib.c b/src/vnet/mfib/ip6_mfib.c
index 5e48e9193b5..e4861330654 100644
--- a/src/vnet/mfib/ip6_mfib.c
+++ b/src/vnet/mfib/ip6_mfib.c
@@ -151,7 +151,8 @@ static const ip6_mfib_special_t ip6_mfib_specials[] =
static u32
-ip6_create_mfib_with_table_id (u32 table_id)
+ip6_create_mfib_with_table_id (u32 table_id,
+ mfib_source_t src)
{
mfib_table_t *mfib_table;
mfib_prefix_t pfx = {
@@ -182,7 +183,7 @@ ip6_create_mfib_with_table_id (u32 table_id)
mfib_table->v6.table_id =
table_id;
- mfib_table_lock(mfib_table->mft_index, FIB_PROTOCOL_IP6);
+ mfib_table_lock(mfib_table->mft_index, FIB_PROTOCOL_IP6, src);
mfib_table->v6.rhead =
clib_mem_alloc_aligned (sizeof(*mfib_table->v6.rhead),
@@ -297,14 +298,15 @@ ip6_mfib_interface_enable_disable (u32 sw_if_index, int is_enable)
}
u32
-ip6_mfib_table_find_or_create_and_lock (u32 table_id)
+ip6_mfib_table_find_or_create_and_lock (u32 table_id,
+ mfib_source_t src)
{
u32 index;
index = ip6_mfib_index_from_table_id(table_id);
if (~0 == index)
- return ip6_create_mfib_with_table_id(table_id);
- mfib_table_lock(index, FIB_PROTOCOL_IP6);
+ return ip6_create_mfib_with_table_id(table_id, src);
+ mfib_table_lock(index, FIB_PROTOCOL_IP6, src);
return (index);
}
diff --git a/src/vnet/mfib/ip6_mfib.h b/src/vnet/mfib/ip6_mfib.h
index adaa7ec24fe..ea81b553cd5 100644
--- a/src/vnet/mfib/ip6_mfib.h
+++ b/src/vnet/mfib/ip6_mfib.h
@@ -79,8 +79,9 @@ ip6_mfib_get (u32 index)
* @returns A pointer to the retrieved or created fib.
*
*/
-extern u32 ip6_mfib_table_find_or_create_and_lock(u32 table_id);
-extern u32 ip6_mfib_table_create_and_lock(void);
+extern u32 ip6_mfib_table_find_or_create_and_lock(u32 table_id,
+ mfib_source_t src);
+extern u32 ip6_mfib_table_create_and_lock(mfib_source_t src);
static inline
diff --git a/src/vnet/mfib/mfib_entry.c b/src/vnet/mfib/mfib_entry.c
index 804e10ab0e2..2302b9a1707 100644
--- a/src/vnet/mfib/mfib_entry.c
+++ b/src/vnet/mfib/mfib_entry.c
@@ -334,6 +334,17 @@ mfib_entry_get_best_src (const mfib_entry_t *mfib_entry)
return (bsrc);
}
+int
+mfib_entry_is_sourced (fib_node_index_t mfib_entry_index,
+ mfib_source_t source)
+{
+ mfib_entry_t *mfib_entry;
+
+ mfib_entry = mfib_entry_get(mfib_entry_index);
+
+ return (NULL != mfib_entry_src_find(mfib_entry, source, NULL));
+}
+
static void
mfib_entry_src_flush (mfib_entry_src_t *msrc)
{
diff --git a/src/vnet/mfib/mfib_entry.h b/src/vnet/mfib/mfib_entry.h
index d4377878a2c..96ee49f799e 100644
--- a/src/vnet/mfib/mfib_entry.h
+++ b/src/vnet/mfib/mfib_entry.h
@@ -130,6 +130,8 @@ extern void mfib_entry_unlock(fib_node_index_t fib_entry_index);
extern void mfib_entry_get_prefix(fib_node_index_t fib_entry_index,
mfib_prefix_t *pfx);
extern u32 mfib_entry_get_fib_index(fib_node_index_t fib_entry_index);
+extern int mfib_entry_is_sourced(fib_node_index_t fib_entry_index,
+ mfib_source_t source);
extern void mfib_entry_contribute_forwarding(
fib_node_index_t mfib_entry_index,
diff --git a/src/vnet/mfib/mfib_table.c b/src/vnet/mfib/mfib_table.c
index 7ffe8941e75..e5550adc8f7 100644
--- a/src/vnet/mfib/mfib_table.c
+++ b/src/vnet/mfib/mfib_table.c
@@ -424,7 +424,8 @@ mfib_table_find (fib_protocol_t proto,
u32
mfib_table_find_or_create_and_lock (fib_protocol_t proto,
- u32 table_id)
+ u32 table_id,
+ mfib_source_t src)
{
mfib_table_t *mfib_table;
fib_node_index_t fi;
@@ -432,10 +433,10 @@ mfib_table_find_or_create_and_lock (fib_protocol_t proto,
switch (proto)
{
case FIB_PROTOCOL_IP4:
- fi = ip4_mfib_table_find_or_create_and_lock(table_id);
+ fi = ip4_mfib_table_find_or_create_and_lock(table_id, src);
break;
case FIB_PROTOCOL_IP6:
- fi = ip6_mfib_table_find_or_create_and_lock(table_id);
+ fi = ip6_mfib_table_find_or_create_and_lock(table_id, src);
break;
case FIB_PROTOCOL_MPLS:
default:
@@ -451,6 +452,59 @@ mfib_table_find_or_create_and_lock (fib_protocol_t proto,
return (fi);
}
+/**
+ * @brief Table flush context. Store the indicies of matching FIB entries
+ * that need to be removed.
+ */
+typedef struct mfib_table_flush_ctx_t_
+{
+ /**
+ * The list of entries to flush
+ */
+ fib_node_index_t *mftf_entries;
+
+ /**
+ * The source we are flushing
+ */
+ mfib_source_t mftf_source;
+} mfib_table_flush_ctx_t;
+
+static int
+mfib_table_flush_cb (fib_node_index_t mfib_entry_index,
+ void *arg)
+{
+ mfib_table_flush_ctx_t *ctx = arg;
+
+ if (mfib_entry_is_sourced(mfib_entry_index, ctx->mftf_source))
+ {
+ vec_add1(ctx->mftf_entries, mfib_entry_index);
+ }
+ return (1);
+}
+
+void
+mfib_table_flush (u32 mfib_index,
+ fib_protocol_t proto,
+ mfib_source_t source)
+{
+ fib_node_index_t *mfib_entry_index;
+ mfib_table_flush_ctx_t ctx = {
+ .mftf_entries = NULL,
+ .mftf_source = source,
+ };
+
+ mfib_table_walk(mfib_index, proto,
+ mfib_table_flush_cb,
+ &ctx);
+
+ vec_foreach(mfib_entry_index, ctx.mftf_entries)
+ {
+ mfib_table_entry_delete_index(*mfib_entry_index, source);
+ }
+
+ vec_free(ctx.mftf_entries);
+}
+
static void
mfib_table_destroy (mfib_table_t *mfib_table)
{
@@ -472,27 +526,43 @@ mfib_table_destroy (mfib_table_t *mfib_table)
void
mfib_table_unlock (u32 fib_index,
- fib_protocol_t proto)
+ fib_protocol_t proto,
+ mfib_source_t source)
{
mfib_table_t *mfib_table;
mfib_table = mfib_table_get(fib_index, proto);
- mfib_table->mft_locks--;
+ mfib_table->mft_locks[source]--;
+ mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS]--;
+
+ if (0 == mfib_table->mft_locks[source])
+ {
+ /*
+ * The source no longer needs the table. flush any routes
+ * from it just in case
+ */
+ mfib_table_flush(fib_index, proto, source);
+ }
- if (0 == mfib_table->mft_locks)
+ if (0 == mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS])
{
- mfib_table_destroy(mfib_table);
+ /*
+ * no more locak from any source - kill it
+ */
+ mfib_table_destroy(mfib_table);
}
}
void
mfib_table_lock (u32 fib_index,
- fib_protocol_t proto)
+ fib_protocol_t proto,
+ mfib_source_t source)
{
mfib_table_t *mfib_table;
mfib_table = mfib_table_get(fib_index, proto);
- mfib_table->mft_locks++;
+ mfib_table->mft_locks[source]++;
+ mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS]++;
}
void
diff --git a/src/vnet/mfib/mfib_table.h b/src/vnet/mfib/mfib_table.h
index 83aa04ef797..c6b0b0973a1 100644
--- a/src/vnet/mfib/mfib_table.h
+++ b/src/vnet/mfib/mfib_table.h
@@ -23,6 +23,12 @@
#include <vnet/mfib/mfib_types.h>
/**
+ * Keep a lock per-source and a total
+ */
+#define MFIB_TABLE_N_LOCKS (MFIB_N_SOURCES+1)
+#define MFIB_TABLE_TOTAL_LOCKS MFIB_N_SOURCES
+
+/**
* @brief
* A protocol Independent IP multicast FIB table
*/
@@ -47,7 +53,7 @@ typedef struct mfib_table_t_
/**
* number of locks on the table
*/
- u16 mft_locks;
+ u16 mft_locks[MFIB_TABLE_N_LOCKS];
/**
* Table ID (hash key) for this FIB.
@@ -259,7 +265,8 @@ extern fib_node_index_t mfib_table_entry_special_add(u32 fib_index,
* the source to flush
*/
extern void mfib_table_flush(u32 fib_index,
- fib_protocol_t proto);
+ fib_protocol_t proto,
+ mfib_source_t source);
/**
* @brief
@@ -307,9 +314,13 @@ extern u32 mfib_table_find(fib_protocol_t proto, u32 table_id);
*
* @return fib_index
* The index of the FIB
+ *
+ * @param source
+ * The ID of the client/source.
*/
extern u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto,
- u32 table_id);
+ u32 table_id,
+ mfib_source_t source);
/**
@@ -321,9 +332,13 @@ extern u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto,
*
* @paran proto
* The protocol of the FIB (and thus the entries therein)
+ *
+ * @param source
+ * The ID of the client/source.
*/
extern void mfib_table_unlock(u32 fib_index,
- fib_protocol_t proto);
+ fib_protocol_t proto,
+ mfib_source_t source);
/**
* @brief
@@ -335,9 +350,13 @@ extern void mfib_table_unlock(u32 fib_index,
*
* @paran proto
* The protocol of the FIB (and thus the entries therein)
+ *
+ * @param source
+ * The ID of the client/source.
*/
extern void mfib_table_lock(u32 fib_index,
- fib_protocol_t proto);
+ fib_protocol_t proto,
+ mfib_source_t source);
/**
* @brief
diff --git a/src/vnet/mfib/mfib_test.c b/src/vnet/mfib/mfib_test.c
index 57787eca641..3055844dd59 100644
--- a/src/vnet/mfib/mfib_test.c
+++ b/src/vnet/mfib/mfib_test.c
@@ -22,6 +22,7 @@
#include <vnet/fib/fib_path_list.h>
#include <vnet/fib/fib_test.h>
#include <vnet/fib/fib_table.h>
+#include <vnet/fib/mpls_fib.h>
#include <vnet/dpo/replicate_dpo.h>
#include <vnet/adj/adj_mcast.h>
@@ -366,7 +367,7 @@ mfib_test_i (fib_protocol_t PROTO,
MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
/* Find or create FIB table 11 */
- fib_index = mfib_table_find_or_create_and_lock(PROTO, 11);
+ fib_index = mfib_table_find_or_create_and_lock(PROTO, 11, MFIB_SOURCE_API);
mfib_prefix_t pfx_dft = {
.fp_len = 0,
@@ -1113,9 +1114,10 @@ mfib_test_i (fib_protocol_t PROTO,
/*
* MPLS enable an interface so we get the MPLS table created
*/
+ mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
mpls_sw_interface_enable_disable(&mpls_main,
tm->hw[0]->sw_if_index,
- 1);
+ 1, 0);
lfei = fib_table_entry_update_one_path(0, // default MPLS Table
&pfx_3500,
@@ -1192,7 +1194,7 @@ mfib_test_i (fib_protocol_t PROTO,
/*
* Unlock the table - it's the last lock so should be gone thereafter
*/
- mfib_table_unlock(fib_index, PROTO);
+ mfib_table_unlock(fib_index, PROTO, MFIB_SOURCE_API);
MFIB_TEST((FIB_NODE_INDEX_INVALID ==
mfib_table_find(PROTO, fib_index)),
@@ -1207,7 +1209,8 @@ mfib_test_i (fib_protocol_t PROTO,
*/
mpls_sw_interface_enable_disable(&mpls_main,
tm->hw[0]->sw_if_index,
- 0);
+ 0, 0);
+ mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
/*
* test we've leaked no resources
diff --git a/src/vnet/mfib/mfib_types.h b/src/vnet/mfib/mfib_types.h
index 863fad169a5..50aede044ec 100644
--- a/src/vnet/mfib/mfib_types.h
+++ b/src/vnet/mfib/mfib_types.h
@@ -166,9 +166,10 @@ typedef enum mfib_source_t_
MFIB_SOURCE_VXLAN,
MFIB_SOURCE_DHCP,
MFIB_SOURCE_SRv6,
- MFIB_SOURCE_DEFAULT_ROUTE,
MFIB_SOURCE_GTPU,
MFIB_SOURCE_VXLAN_GPE,
+ MFIB_SOURCE_RR,
+ MFIB_SOURCE_DEFAULT_ROUTE,
} mfib_source_t;
#define MFIB_SOURCE_NAMES { \
@@ -178,11 +179,14 @@ typedef enum mfib_source_t_
[MFIB_SOURCE_DHCP] = "DHCP", \
[MFIB_SOURCE_VXLAN] = "VXLAN", \
[MFIB_SOURCE_SRv6] = "SRv6", \
- [MFIB_SOURCE_DEFAULT_ROUTE] = "Default Route", \
[MFIB_SOURCE_GTPU] = "GTPU", \
[MFIB_SOURCE_VXLAN_GPE] = "VXLAN-GPE", \
+ [MFIB_SOURCE_RR] = "Recursive-resolution", \
+ [MFIB_SOURCE_DEFAULT_ROUTE] = "Default Route", \
}
+#define MFIB_N_SOURCES (MFIB_SOURCE_DEFAULT_ROUTE)
+
/**
* \brief Compare two prefixes for equality
*/
diff --git a/src/vnet/mpls/interface.c b/src/vnet/mpls/interface.c
index a085aaa2f19..d7c8e7d340e 100644
--- a/src/vnet/mpls/interface.c
+++ b/src/vnet/mpls/interface.c
@@ -35,25 +35,33 @@ mpls_sw_interface_is_enabled (u32 sw_if_index)
return (mm->mpls_enabled_by_sw_if_index[sw_if_index]);
}
-void
+int
mpls_sw_interface_enable_disable (mpls_main_t * mm,
u32 sw_if_index,
- u8 is_enable)
+ u8 is_enable,
+ u8 is_api)
{
fib_node_index_t lfib_index;
vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
+ lfib_index = fib_table_find(FIB_PROTOCOL_MPLS,
+ MPLS_FIB_DEFAULT_TABLE_ID);
+
+ if (~0 == lfib_index)
+ return VNET_API_ERROR_NO_SUCH_FIB;
+
/*
* enable/disable only on the 1<->0 transition
*/
if (is_enable)
{
if (1 != ++mm->mpls_enabled_by_sw_if_index[sw_if_index])
- return;
+ return (0);
+
+ fib_table_lock(lfib_index, FIB_PROTOCOL_MPLS,
+ (is_api? FIB_SOURCE_API: FIB_SOURCE_CLI));
- lfib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_MPLS,
- MPLS_FIB_DEFAULT_TABLE_ID);
vec_validate(mm->fib_index_by_sw_if_index, 0);
mm->fib_index_by_sw_if_index[sw_if_index] = lfib_index;
}
@@ -61,15 +69,17 @@ mpls_sw_interface_enable_disable (mpls_main_t * mm,
{
ASSERT(mm->mpls_enabled_by_sw_if_index[sw_if_index] > 0);
if (0 != --mm->mpls_enabled_by_sw_if_index[sw_if_index])
- return;
+ return (0);
fib_table_unlock(mm->fib_index_by_sw_if_index[sw_if_index],
- FIB_PROTOCOL_MPLS);
+ FIB_PROTOCOL_MPLS,
+ (is_api? FIB_SOURCE_API: FIB_SOURCE_CLI));
}
vnet_feature_enable_disable ("mpls-input", "mpls-not-enabled",
sw_if_index, !is_enable, 0, 0);
+ return (0);
}
static clib_error_t *
@@ -101,7 +111,7 @@ mpls_interface_enable_disable (vlib_main_t * vm,
goto done;
}
- mpls_sw_interface_enable_disable(&mpls_main, sw_if_index, enable);
+ mpls_sw_interface_enable_disable(&mpls_main, sw_if_index, enable, 0);
done:
return error;
diff --git a/src/vnet/mpls/mpls.c b/src/vnet/mpls/mpls.c
index 5021ac23bc0..7bdfd8c7c8d 100644
--- a/src/vnet/mpls/mpls.c
+++ b/src/vnet/mpls/mpls.c
@@ -536,6 +536,78 @@ VLIB_CLI_COMMAND (mpls_local_label_command, static) = {
.short_help = "Create/Delete MPL local labels",
};
+clib_error_t *
+vnet_mpls_table_cmd (vlib_main_t * vm,
+ unformat_input_t * main_input,
+ vlib_cli_command_t * cmdo)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t *error = NULL;
+ u32 table_id, is_add;
+
+ is_add = 1;
+ table_id = ~0;
+
+ /* Get a line of input. */
+ if (!unformat_user (main_input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "%d", &table_id))
+ ;
+ else if (unformat (line_input, "del"))
+ is_add = 0;
+ else if (unformat (line_input, "add"))
+ is_add = 1;
+ else
+ {
+ error = unformat_parse_error (line_input);
+ goto done;
+ }
+ }
+
+ if (~0 == table_id)
+ {
+ error = clib_error_return (0, "No table id");
+ goto done;
+ }
+ else if (0 == table_id)
+ {
+ error = clib_error_return (0, "Can't change the default table");
+ goto done;
+ }
+ else
+ {
+ if (is_add)
+ {
+ mpls_table_create (table_id, 0);
+ }
+ else
+ {
+ mpls_table_delete (table_id, 0);
+ }
+ }
+
+ done:
+ unformat_free (line_input);
+ return error;
+}
+
+/* *INDENT-ON* */
+/*?
+ * This command is used to add or delete MPLS Tables. All
+ * Tables must be explicitly added before that can be used,
+ * Including the default table.
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (ip6_table_command, static) = {
+ .path = "mpla table",
+ .short_help = "mpls table [add|del] <table-id>",
+ .function = vnet_mpls_table_cmd,
+ .is_mp_safe = 1,
+};
+
int
mpls_fib_reset_labels (u32 fib_id)
{
@@ -546,12 +618,8 @@ mpls_fib_reset_labels (u32 fib_id)
static clib_error_t *
mpls_init (vlib_main_t * vm)
{
- mpls_main_t * mm = &mpls_main;
clib_error_t * error;
- mm->vlib_main = vm;
- mm->vnet_main = vnet_get_main();
-
if ((error = vlib_call_init_function (vm, ip_main_init)))
return error;
diff --git a/src/vnet/mpls/mpls.h b/src/vnet/mpls/mpls.h
index b0125e60c63..31cb1746f71 100644
--- a/src/vnet/mpls/mpls.h
+++ b/src/vnet/mpls/mpls.h
@@ -56,10 +56,6 @@ typedef struct {
/* IP4 enabled count by software interface */
u8 * mpls_enabled_by_sw_if_index;
-
- /* convenience */
- vlib_main_t * vlib_main;
- vnet_main_t * vnet_main;
} mpls_main_t;
extern mpls_main_t mpls_main;
@@ -77,8 +73,6 @@ extern vlib_node_registration_t mpls_midchain_node;
/* Parse mpls protocol as 0xXXXX or protocol name.
In either host or network byte order. */
-unformat_function_t unformat_mpls_protocol_host_byte_order;
-unformat_function_t unformat_mpls_protocol_net_byte_order;
unformat_function_t unformat_mpls_label_net_byte_order;
unformat_function_t unformat_mpls_unicast_label;
@@ -86,9 +80,10 @@ unformat_function_t unformat_mpls_unicast_label;
unformat_function_t unformat_mpls_header;
unformat_function_t unformat_pg_mpls_header;
-void mpls_sw_interface_enable_disable (mpls_main_t * mm,
- u32 sw_if_index,
- u8 is_enable);
+int mpls_sw_interface_enable_disable (mpls_main_t * mm,
+ u32 sw_if_index,
+ u8 is_enable,
+ u8 is_api);
u8 mpls_sw_interface_is_enabled (u32 sw_if_index);
@@ -103,4 +98,7 @@ mpls_fib_index_cmp(void * a1, void * a2);
int
mpls_label_cmp(void * a1, void * a2);
+void mpls_table_create(uint32_t table_id, u8 is_api);
+void mpls_table_delete(uint32_t table_id, u8 is_api);
+
#endif /* included_vnet_mpls_h */
diff --git a/src/vnet/mpls/mpls_api.c b/src/vnet/mpls/mpls_api.c
index a44b1a25653..38f5b014344 100644
--- a/src/vnet/mpls/mpls_api.c
+++ b/src/vnet/mpls/mpls_api.c
@@ -59,6 +59,29 @@ extern void stats_dslock_with_hint (int hint, int tag);
extern void stats_dsunlock (void);
void
+mpls_table_delete (u32 table_id, u8 is_api)
+{
+ u32 fib_index;
+
+ /*
+ * The MPLS defult table must also be explicitly created via the API.
+ * So in contrast to IP, it gets no special treatment here.
+ *
+ * The API holds only one lock on the table.
+ * i.e. it can be added many times via the API but needs to be
+ * deleted only once.
+ */
+ fib_index = fib_table_find (FIB_PROTOCOL_MPLS, table_id);
+
+ if (~0 != fib_index)
+ {
+ fib_table_unlock (fib_index,
+ FIB_PROTOCOL_MPLS,
+ (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI));
+ }
+}
+
+void
vl_api_mpls_table_add_del_t_handler (vl_api_mpls_table_add_del_t * mp)
{
vl_api_mpls_table_add_del_reply_t *rmp;
@@ -68,6 +91,13 @@ vl_api_mpls_table_add_del_t_handler (vl_api_mpls_table_add_del_t * mp)
vnm = vnet_get_main ();
vnm->api_errno = 0;
+ if (mp->mt_is_add)
+ mpls_table_create (ntohl (mp->mt_table_id), 1);
+ else
+ mpls_table_delete (ntohl (mp->mt_table_id), 1);
+
+ rv = (rv == 0) ? vnm->api_errno : rv;
+
REPLY_MACRO (VL_API_MPLS_TABLE_ADD_DEL_REPLY);
}
@@ -82,14 +112,7 @@ mpls_ip_bind_unbind_handler (vnet_main_t * vnm,
if (~0 == mpls_fib_index)
{
- if (mp->mb_create_table_if_needed)
- {
- mpls_fib_index =
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS,
- ntohl (mp->mb_mpls_table_id));
- }
- else
- return VNET_API_ERROR_NO_SUCH_FIB;
+ return VNET_API_ERROR_NO_SUCH_FIB;
}
ip_fib_index = fib_table_find ((mp->mb_is_ip4 ?
@@ -170,7 +193,6 @@ mpls_route_add_del_t_handler (vnet_main_t * vnm,
mp->mr_next_hop_sw_if_index,
pfx.fp_payload_proto,
mp->mr_next_hop_table_id,
- mp->mr_create_table_if_needed,
mp->mr_is_rpf_id,
&fib_index, &next_hop_fib_index);
@@ -235,6 +257,32 @@ vl_api_mpls_route_add_del_t_handler (vl_api_mpls_route_add_del_t * mp)
REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
}
+void
+mpls_table_create (u32 table_id, u8 is_api)
+{
+ u32 fib_index;
+
+ /*
+ * The MPLS defult table must also be explicitly created via the API.
+ * So in contrast to IP, it gets no special treatment here.
+ */
+
+ /*
+ * The API holds only one lock on the table.
+ * i.e. it can be added many times via the API but needs to be
+ * deleted only once.
+ */
+ fib_index = fib_table_find (FIB_PROTOCOL_MPLS, table_id);
+
+ if (~0 == fib_index)
+ {
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS,
+ table_id,
+ (is_api ?
+ FIB_SOURCE_API : FIB_SOURCE_CLI));
+ }
+}
+
static void
vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp)
{
diff --git a/src/vnet/srv6/sr_policy_rewrite.c b/src/vnet/srv6/sr_policy_rewrite.c
index f427bbf379c..2f90993a4be 100755
--- a/src/vnet/srv6/sr_policy_rewrite.c
+++ b/src/vnet/srv6/sr_policy_rewrite.c
@@ -595,8 +595,10 @@ sr_policy_add (ip6_address_t * bsid, ip6_address_t * segments,
if (sm->fib_table_ip6 == (u32) ~ 0)
{
sm->fib_table_ip6 = fib_table_create_and_lock (FIB_PROTOCOL_IP6,
+ FIB_SOURCE_SR,
"SRv6 steering of IP6 prefixes through BSIDs");
sm->fib_table_ip4 = fib_table_create_and_lock (FIB_PROTOCOL_IP6,
+ FIB_SOURCE_SR,
"SRv6 steering of IP4 prefixes through BSIDs");
}
@@ -684,8 +686,8 @@ sr_policy_del (ip6_address_t * bsid, u32 index)
/* If FIB empty unlock it */
if (!pool_elts (sm->sr_policies) && !pool_elts (sm->steer_policies))
{
- fib_table_unlock (sm->fib_table_ip6, FIB_PROTOCOL_IP6);
- fib_table_unlock (sm->fib_table_ip4, FIB_PROTOCOL_IP6);
+ fib_table_unlock (sm->fib_table_ip6, FIB_PROTOCOL_IP6, FIB_SOURCE_SR);
+ fib_table_unlock (sm->fib_table_ip4, FIB_PROTOCOL_IP6, FIB_SOURCE_SR);
sm->fib_table_ip6 = (u32) ~ 0;
sm->fib_table_ip4 = (u32) ~ 0;
}
diff --git a/src/vnet/srv6/sr_steering.c b/src/vnet/srv6/sr_steering.c
index 57fe21f6746..cf4e81abfd4 100755
--- a/src/vnet/srv6/sr_steering.c
+++ b/src/vnet/srv6/sr_steering.c
@@ -159,8 +159,10 @@ sr_steering_policy (int is_del, ip6_address_t * bsid, u32 sr_policy_index,
/* If no more SR policies or steering policies */
if (!pool_elts (sm->sr_policies) && !pool_elts (sm->steer_policies))
{
- fib_table_unlock (sm->fib_table_ip6, FIB_PROTOCOL_IP6);
- fib_table_unlock (sm->fib_table_ip4, FIB_PROTOCOL_IP6);
+ fib_table_unlock (sm->fib_table_ip6,
+ FIB_PROTOCOL_IP6, FIB_SOURCE_SR);
+ fib_table_unlock (sm->fib_table_ip4,
+ FIB_PROTOCOL_IP6, FIB_SOURCE_SR);
sm->fib_table_ip6 = (u32) ~ 0;
sm->fib_table_ip4 = (u32) ~ 0;
}
diff --git a/src/vpp/api/api.c b/src/vpp/api/api.c
index f9c3129cc78..044ddb5b0c8 100644
--- a/src/vpp/api/api.c
+++ b/src/vpp/api/api.c
@@ -699,8 +699,9 @@ static void
VALIDATE_SW_IF_INDEX (mp);
- mpls_sw_interface_enable_disable (&mpls_main,
- ntohl (mp->sw_if_index), mp->enable);
+ rv = mpls_sw_interface_enable_disable (&mpls_main,
+ ntohl (mp->sw_if_index),
+ mp->enable, 1);
BAD_SW_IF_INDEX_LABEL;
REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
diff --git a/src/vpp/api/custom_dump.c b/src/vpp/api/custom_dump.c
index 1353fe28719..be74b83ace8 100644
--- a/src/vpp/api/custom_dump.c
+++ b/src/vpp/api/custom_dump.c
@@ -560,9 +560,6 @@ static void *vl_api_ip_add_del_route_t_print
if (mp->table_id != 0)
s = format (s, "vrf %d ", ntohl (mp->table_id));
- if (mp->create_vrf_if_needed)
- s = format (s, "create-vrf ");
-
if (mp->next_hop_weight != 1)
s = format (s, "weight %d ", mp->next_hop_weight);
diff --git a/test/test_dhcp.py b/test/test_dhcp.py
index 6fc291824ec..fe97f6c9a2b 100644
--- a/test/test_dhcp.py
+++ b/test/test_dhcp.py
@@ -6,7 +6,7 @@ import struct
from framework import VppTestCase, VppTestRunner
from vpp_neighbor import VppNeighbor
-from vpp_ip_route import find_route
+from vpp_ip_route import find_route, VppIpTable
from util import mk_ll_addr
from scapy.layers.l2 import Ether, getmacbyip, ARP
@@ -34,10 +34,20 @@ class TestDHCP(VppTestCase):
# create 3 pg interfaces
self.create_pg_interfaces(range(4))
+ self.tables = []
# pg0 and 1 are IP configured in VRF 0 and 1.
# pg2 and 3 are non IP-configured in VRF 0 and 1
table_id = 0
+ for table_id in range(1, 4):
+ tbl4 = VppIpTable(self, table_id)
+ tbl4.add_vpp_config()
+ self.tables.append(tbl4)
+ tbl6 = VppIpTable(self, table_id, is_ip6=1)
+ tbl6.add_vpp_config()
+ self.tables.append(tbl6)
+
+ table_id = 0
for i in self.pg_interfaces[:2]:
i.admin_up()
i.set_table_ip4(table_id)
@@ -56,11 +66,15 @@ class TestDHCP(VppTestCase):
table_id += 1
def tearDown(self):
- super(TestDHCP, self).tearDown()
- for i in self.pg_interfaces:
+ for i in self.pg_interfaces[:2]:
i.unconfig_ip4()
i.unconfig_ip6()
+
+ for i in self.pg_interfaces:
+ i.set_table_ip4(0)
+ i.set_table_ip6(0)
i.admin_down()
+ super(TestDHCP, self).tearDown()
def send_and_assert_no_replies(self, intf, pkts, remark):
intf.add_stream(pkts)
@@ -667,6 +681,8 @@ class TestDHCP(VppTestCase):
"DHCP cleanup VRF 0")
self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
"DHCP cleanup VRF 1")
+ self.pg2.unconfig_ip4()
+ self.pg3.unconfig_ip4()
def test_dhcp6_proxy(self):
""" DHCPv6 Proxy"""
@@ -1045,6 +1061,8 @@ class TestDHCP(VppTestCase):
server_table_id=0,
is_ipv6=1,
is_add=0)
+ self.pg2.unconfig_ip6()
+ self.pg3.unconfig_ip6()
def test_dhcp_client(self):
""" DHCP Client"""
diff --git a/test/test_gre.py b/test/test_gre.py
index 1afc44fb423..9046b05f2f6 100644
--- a/test/test_gre.py
+++ b/test/test_gre.py
@@ -6,7 +6,7 @@ from logging import *
from framework import VppTestCase, VppTestRunner
from vpp_sub_interface import VppDot1QSubint
from vpp_gre_interface import VppGreInterface, VppGre6Interface
-from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto
+from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto, VppIpTable
from vpp_papi_provider import L2_VTR_OP
from scapy.packet import Raw
@@ -30,6 +30,9 @@ class TestGRE(VppTestCase):
# create 3 pg interfaces - set one in a non-default table.
self.create_pg_interfaces(range(3))
+
+ self.tbl = VppIpTable(self, 1)
+ self.tbl.add_vpp_config()
self.pg1.set_table_ip4(1)
for i in self.pg_interfaces:
@@ -43,11 +46,12 @@ class TestGRE(VppTestCase):
self.pg2.resolve_ndp()
def tearDown(self):
- super(TestGRE, self).tearDown()
for i in self.pg_interfaces:
i.unconfig_ip4()
i.unconfig_ip6()
i.admin_down()
+ self.pg1.set_table_ip4(0)
+ super(TestGRE, self).tearDown()
def create_stream_ip4(self, src_if, src_ip, dst_ip):
pkts = []
diff --git a/test/test_ip4.py b/test/test_ip4.py
index 7a7098c36f0..55d16735a01 100644
--- a/test/test_ip4.py
+++ b/test/test_ip4.py
@@ -6,7 +6,8 @@ import unittest
from framework import VppTestCase, VppTestRunner
from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \
- VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind
+ VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
+ VppMplsTable
from scapy.packet import Raw
from scapy.layers.l2 import Ether, Dot1Q, ARP
@@ -774,6 +775,8 @@ class TestIPLoadBalance(VppTestCase):
super(TestIPLoadBalance, self).setUp()
self.create_pg_interfaces(range(5))
+ mpls_tbl = VppMplsTable(self, 0)
+ mpls_tbl.add_vpp_config()
for i in self.pg_interfaces:
i.admin_up()
@@ -782,11 +785,11 @@ class TestIPLoadBalance(VppTestCase):
i.enable_mpls()
def tearDown(self):
- super(TestIPLoadBalance, self).tearDown()
for i in self.pg_interfaces:
i.disable_mpls()
i.unconfig_ip4()
i.admin_down()
+ super(TestIPLoadBalance, self).tearDown()
def send_and_expect_load_balancing(self, input, pkts, outputs):
input.add_stream(pkts)
@@ -966,6 +969,8 @@ class TestIPVlan0(VppTestCase):
super(TestIPVlan0, self).setUp()
self.create_pg_interfaces(range(2))
+ mpls_tbl = VppMplsTable(self, 0)
+ mpls_tbl.add_vpp_config()
for i in self.pg_interfaces:
i.admin_up()
@@ -974,11 +979,11 @@ class TestIPVlan0(VppTestCase):
i.enable_mpls()
def tearDown(self):
- super(TestIPVlan0, self).tearDown()
for i in self.pg_interfaces:
i.disable_mpls()
i.unconfig_ip4()
i.admin_down()
+ super(TestIPVlan0, self).tearDown()
def send_and_expect(self, input, pkts, output):
input.add_stream(pkts)
diff --git a/test/test_ip4_vrf_multi_instance.py b/test/test_ip4_vrf_multi_instance.py
index b73ac9483c3..5a8d6760586 100644
--- a/test/test_ip4_vrf_multi_instance.py
+++ b/test/test_ip4_vrf_multi_instance.py
@@ -172,9 +172,10 @@ class TestIp4VrfMultiInst(VppTestCase):
pg_if = self.pg_if_by_vrf_id[vrf_id][0]
dest_addr = pg_if.remote_hosts[0].ip4n
dest_addr_len = 24
+ self.vapi.ip_table_add_del(vrf_id, is_add=1)
self.vapi.ip_add_del_route(
dest_addr, dest_addr_len, pg_if.local_ip4n,
- table_id=vrf_id, create_vrf_if_needed=1, is_multipath=1)
+ table_id=vrf_id, is_multipath=1)
self.logger.info("IPv4 VRF ID %d created" % vrf_id)
if vrf_id not in self.vrf_list:
self.vrf_list.append(vrf_id)
@@ -216,6 +217,7 @@ class TestIp4VrfMultiInst(VppTestCase):
self.logger.info("IPv4 VRF ID %d reset" % vrf_id)
self.logger.debug(self.vapi.ppcli("show ip fib"))
self.logger.debug(self.vapi.ppcli("show ip arp"))
+ self.vapi.ip_table_add_del(vrf_id, is_add=0)
def create_stream(self, src_if, packet_sizes):
"""
diff --git a/test/test_ip6.py b/test/test_ip6.py
index 285ce18150c..aad3713c4c0 100644
--- a/test/test_ip6.py
+++ b/test/test_ip6.py
@@ -8,7 +8,7 @@ from vpp_sub_interface import VppSubInterface, VppDot1QSubint
from vpp_pg_interface import is_ipv6_misc
from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, VppIpMRoute, \
VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
- VppMplsRoute, DpoProto
+ VppMplsRoute, DpoProto, VppMplsTable
from vpp_neighbor import find_nbr, VppNeighbor
from scapy.packet import Raw
@@ -1260,6 +1260,9 @@ class TestIP6LoadBalance(VppTestCase):
self.create_pg_interfaces(range(5))
+ mpls_tbl = VppMplsTable(self, 0)
+ mpls_tbl.add_vpp_config()
+
for i in self.pg_interfaces:
i.admin_up()
i.config_ip6()
@@ -1267,11 +1270,11 @@ class TestIP6LoadBalance(VppTestCase):
i.enable_mpls()
def tearDown(self):
- super(TestIP6LoadBalance, self).tearDown()
for i in self.pg_interfaces:
i.unconfig_ip6()
i.admin_down()
i.disable_mpls()
+ super(TestIP6LoadBalance, self).tearDown()
def send_and_expect_load_balancing(self, input, pkts, outputs):
input.add_stream(pkts)
diff --git a/test/test_ip6_vrf_multi_instance.py b/test/test_ip6_vrf_multi_instance.py
index af80b5ba065..769cb2e51b3 100644
--- a/test/test_ip6_vrf_multi_instance.py
+++ b/test/test_ip6_vrf_multi_instance.py
@@ -187,9 +187,10 @@ class TestIP6VrfMultiInst(VppTestCase):
pg_if = self.pg_if_by_vrf_id[vrf_id][0]
dest_addr = pg_if.remote_hosts[0].ip6n
dest_addr_len = 64
+ self.vapi.ip_table_add_del(vrf_id, is_add=1, is_ipv6=1)
self.vapi.ip_add_del_route(
dest_addr, dest_addr_len, pg_if.local_ip6n, is_ipv6=1,
- table_id=vrf_id, create_vrf_if_needed=1, is_multipath=1)
+ table_id=vrf_id, is_multipath=1)
self.logger.info("IPv6 VRF ID %d created" % vrf_id)
if vrf_id not in self.vrf_list:
self.vrf_list.append(vrf_id)
@@ -232,6 +233,7 @@ class TestIP6VrfMultiInst(VppTestCase):
self.logger.info("IPv6 VRF ID %d reset" % vrf_id)
self.logger.debug(self.vapi.ppcli("show ip6 fib"))
self.logger.debug(self.vapi.ppcli("show ip6 neighbors"))
+ self.vapi.ip_table_add_del(vrf_id, is_add=0, is_ipv6=1)
def create_stream(self, src_if, packet_sizes):
"""
diff --git a/test/test_ip_mcast.py b/test/test_ip_mcast.py
index 276555d6267..7cad683cac5 100644
--- a/test/test_ip_mcast.py
+++ b/test/test_ip_mcast.py
@@ -5,7 +5,7 @@ import unittest
from framework import VppTestCase, VppTestRunner
from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
from vpp_ip_route import VppIpMRoute, VppMRoutePath, VppMFibSignal, \
- MRouteItfFlags, MRouteEntryFlags
+ MRouteItfFlags, MRouteEntryFlags, VppIpTable
from scapy.packet import Raw
from scapy.layers.l2 import Ether
@@ -44,16 +44,37 @@ class TestIPMcast(VppTestCase):
super(TestIPMcast, self).setUp()
# create 8 pg interfaces
- self.create_pg_interfaces(range(8))
+ self.create_pg_interfaces(range(9))
# setup interfaces
- for i in self.pg_interfaces:
+ for i in self.pg_interfaces[:8]:
i.admin_up()
i.config_ip4()
i.config_ip6()
i.resolve_arp()
i.resolve_ndp()
+ # one more in a vrf
+ tbl4 = VppIpTable(self, 10)
+ tbl4.add_vpp_config()
+ self.pg8.set_table_ip4(10)
+ self.pg8.config_ip4()
+
+ tbl6 = VppIpTable(self, 10, is_ip6=1)
+ tbl6.add_vpp_config()
+ self.pg8.set_table_ip6(10)
+ self.pg8.config_ip6()
+
+ def tearDown(self):
+ for i in self.pg_interfaces:
+ i.unconfig_ip4()
+ i.unconfig_ip6()
+ i.admin_down()
+
+ self.pg8.set_table_ip4(0)
+ self.pg8.set_table_ip6(0)
+ super(TestIPMcast, self).tearDown()
+
def create_stream_ip4(self, src_if, src_ip, dst_ip, payload_size=0):
pkts = []
# default to small packet sizes
@@ -663,6 +684,77 @@ class TestIPMcast(VppTestCase):
#
route_232_1_1_1.remove_vpp_config()
+ def test_ip_mcast_vrf(self):
+ """ IP Multicast Replication in non-default table"""
+
+ #
+ # An (S,G).
+ # one accepting interface, pg0, 2 forwarding interfaces
+ #
+ route_1_1_1_1_232_1_1_1 = VppIpMRoute(
+ self,
+ "1.1.1.1",
+ "232.1.1.1", 64,
+ MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
+ [VppMRoutePath(self.pg8.sw_if_index,
+ MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
+ VppMRoutePath(self.pg1.sw_if_index,
+ MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
+ VppMRoutePath(self.pg2.sw_if_index,
+ MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
+ table_id=10)
+ route_1_1_1_1_232_1_1_1.add_vpp_config()
+
+ #
+ # a stream that matches the route for (1.1.1.1,232.1.1.1)
+ # small packets
+ #
+ self.vapi.cli("clear trace")
+ tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
+ self.pg8.add_stream(tx)
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ # We expect replications on Pg1 & 2
+ self.verify_capture_ip4(self.pg1, tx)
+ self.verify_capture_ip4(self.pg2, tx)
+
+ def test_ip6_mcast_vrf(self):
+ """ IPv6 Multicast Replication in non-default table"""
+
+ #
+ # An (S,G).
+ # one accepting interface, pg0, 2 forwarding interfaces
+ #
+ route_2001_ff01_1 = VppIpMRoute(
+ self,
+ "2001::1",
+ "ff01::1", 256,
+ MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
+ [VppMRoutePath(self.pg8.sw_if_index,
+ MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
+ VppMRoutePath(self.pg1.sw_if_index,
+ MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
+ VppMRoutePath(self.pg2.sw_if_index,
+ MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
+ table_id=10,
+ is_ip6=1)
+ route_2001_ff01_1.add_vpp_config()
+
+ #
+ # a stream that matches the route for (2001::1, ff00::1)
+ #
+ self.vapi.cli("clear trace")
+ tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
+ self.pg8.add_stream(tx)
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ # We expect replications on Pg1, 2,
+ self.verify_capture_ip6(self.pg1, tx)
+ self.verify_capture_ip6(self.pg2, tx)
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_mpls.py b/test/test_mpls.py
index b2226a74bdf..460a32d1fc1 100644
--- a/test/test_mpls.py
+++ b/test/test_mpls.py
@@ -6,7 +6,7 @@ import socket
from framework import VppTestCase, VppTestRunner
from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \
VppMplsIpBind, VppIpMRoute, VppMRoutePath, \
- MRouteItfFlags, MRouteEntryFlags, DpoProto
+ MRouteItfFlags, MRouteEntryFlags, DpoProto, VppIpTable, VppMplsTable
from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
from scapy.packet import Raw
@@ -60,9 +60,23 @@ class TestMPLS(VppTestCase):
# setup both interfaces
# assign them different tables.
table_id = 0
+ self.tables = []
+
+ tbl = VppMplsTable(self, 0)
+ tbl.add_vpp_config()
+ self.tables.append(tbl)
for i in self.pg_interfaces:
i.admin_up()
+
+ if table_id != 0:
+ tbl = VppIpTable(self, table_id)
+ tbl.add_vpp_config()
+ self.tables.append(tbl)
+ tbl = VppIpTable(self, table_id, is_ip6=1)
+ tbl.add_vpp_config()
+ self.tables.append(tbl)
+
i.set_table_ip4(table_id)
i.set_table_ip6(table_id)
i.config_ip4()
@@ -73,12 +87,15 @@ class TestMPLS(VppTestCase):
table_id += 1
def tearDown(self):
- super(TestMPLS, self).tearDown()
for i in self.pg_interfaces:
i.unconfig_ip4()
i.unconfig_ip6()
i.ip6_disable()
+ i.set_table_ip4(0)
+ i.set_table_ip6(0)
+ i.disable_mpls()
i.admin_down()
+ super(TestMPLS, self).tearDown()
# the default of 64 matches the IP packet TTL default
def create_stream_labelled_ip4(
@@ -1092,6 +1109,9 @@ class TestMPLSDisabled(VppTestCase):
# create 2 pg interfaces
self.create_pg_interfaces(range(2))
+ self.tbl = VppMplsTable(self, 0)
+ self.tbl.add_vpp_config()
+
# PG0 is MPLS enalbed
self.pg0.admin_up()
self.pg0.config_ip4()
@@ -1102,11 +1122,13 @@ class TestMPLSDisabled(VppTestCase):
self.pg1.admin_up()
def tearDown(self):
- super(TestMPLSDisabled, self).tearDown()
for i in self.pg_interfaces:
i.unconfig_ip4()
i.admin_down()
+ self.pg0.disable_mpls()
+ super(TestMPLSDisabled, self).tearDown()
+
def send_and_assert_no_replies(self, intf, pkts, remark):
intf.add_stream(pkts)
self.pg_enable_capture(self.pg_interfaces)
@@ -1174,6 +1196,13 @@ class TestMPLSPIC(VppTestCase):
# create 2 pg interfaces
self.create_pg_interfaces(range(4))
+ mpls_tbl = VppMplsTable(self, 0)
+ mpls_tbl.add_vpp_config()
+ tbl4 = VppIpTable(self, 1)
+ tbl4.add_vpp_config()
+ tbl6 = VppIpTable(self, 1, is_ip6=1)
+ tbl6.add_vpp_config()
+
# core links
self.pg0.admin_up()
self.pg0.config_ip4()
@@ -1201,14 +1230,15 @@ class TestMPLSPIC(VppTestCase):
self.pg3.resolve_ndp()
def tearDown(self):
- super(TestMPLSPIC, self).tearDown()
self.pg0.disable_mpls()
+ self.pg1.disable_mpls()
for i in self.pg_interfaces:
i.unconfig_ip4()
i.unconfig_ip6()
i.set_table_ip4(0)
i.set_table_ip6(0)
i.admin_down()
+ super(TestMPLSPIC, self).tearDown()
def test_mpls_ibgp_pic(self):
""" MPLS iBGP PIC edge convergence
@@ -1534,24 +1564,30 @@ class TestMPLSL2(VppTestCase):
# create 2 pg interfaces
self.create_pg_interfaces(range(2))
+ # create the default MPLS table
+ self.tables = []
+ tbl = VppMplsTable(self, 0)
+ tbl.add_vpp_config()
+ self.tables.append(tbl)
+
# use pg0 as the core facing interface
self.pg0.admin_up()
self.pg0.config_ip4()
self.pg0.resolve_arp()
self.pg0.enable_mpls()
- # use the other 2 for customer facg L2 links
+ # use the other 2 for customer facing L2 links
for i in self.pg_interfaces[1:]:
i.admin_up()
def tearDown(self):
- super(TestMPLSL2, self).tearDown()
for i in self.pg_interfaces[1:]:
i.admin_down()
self.pg0.disable_mpls()
self.pg0.unconfig_ip4()
self.pg0.admin_down()
+ super(TestMPLSL2, self).tearDown()
def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels,
ttl=255, top=None):
diff --git a/test/test_nat.py b/test/test_nat.py
index 1f2d17ab101..73e9e217348 100644
--- a/test/test_nat.py
+++ b/test/test_nat.py
@@ -549,6 +549,8 @@ class TestNAT44(MethodHolder):
cls.pg0.configure_ipv4_neighbors()
cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
+ cls.vapi.ip_table_add_del(10, is_add=1)
+ cls.vapi.ip_table_add_del(20, is_add=1)
cls.pg4._local_ip4 = "172.16.255.1"
cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
@@ -1797,6 +1799,8 @@ class TestNAT44(MethodHolder):
self.pg0.unconfig_ip4()
self.pg1.unconfig_ip4()
+ self.vapi.ip_table_add_del(vrf_id1, is_add=1)
+ self.vapi.ip_table_add_del(vrf_id2, is_add=1)
self.pg0.set_table_ip4(vrf_id1)
self.pg1.set_table_ip4(vrf_id2)
self.pg0.config_ip4()
@@ -1825,6 +1829,13 @@ class TestNAT44(MethodHolder):
capture = self.pg2.get_capture(len(pkts))
self.verify_capture_out(capture, nat_ip2)
+ self.pg0.unconfig_ip4()
+ self.pg1.unconfig_ip4()
+ self.pg0.set_table_ip4(0)
+ self.pg1.set_table_ip4(0)
+ self.vapi.ip_table_add_del(vrf_id1, is_add=0)
+ self.vapi.ip_table_add_del(vrf_id2, is_add=0)
+
def test_vrf_feature_independent(self):
""" NAT44 tenant VRF independent address pool mode """
@@ -3042,6 +3053,8 @@ class TestNAT64(MethodHolder):
cls.ip6_interfaces.append(cls.pg_interfaces[2])
cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
+ cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
+
cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
cls.pg0.generate_remote_hosts(2)
diff --git a/test/test_neighbor.py b/test/test_neighbor.py
index 1c7cc2678ff..68dde2fb840 100644
--- a/test/test_neighbor.py
+++ b/test/test_neighbor.py
@@ -5,7 +5,8 @@ from socket import AF_INET, AF_INET6, inet_pton
from framework import VppTestCase, VppTestRunner
from vpp_neighbor import VppNeighbor, find_nbr
-from vpp_ip_route import VppIpRoute, VppRoutePath, find_route
+from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
+ VppIpTable
from scapy.packet import Raw
from scapy.layers.l2 import Ether, ARP, Dot1Q
@@ -39,11 +40,13 @@ class ARPTestCase(VppTestCase):
self.pg1.config_ip6()
# pg3 in a different VRF
+ self.tbl = VppIpTable(self, 1)
+ self.tbl.add_vpp_config()
+
self.pg3.set_table_ip4(1)
self.pg3.config_ip4()
def tearDown(self):
- super(ARPTestCase, self).tearDown()
self.pg0.unconfig_ip4()
self.pg0.unconfig_ip6()
@@ -51,10 +54,13 @@ class ARPTestCase(VppTestCase):
self.pg1.unconfig_ip6()
self.pg3.unconfig_ip4()
+ self.pg3.set_table_ip4(0)
for i in self.pg_interfaces:
i.admin_down()
+ super(ARPTestCase, self).tearDown()
+
def verify_arp_req(self, rx, smac, sip, dip):
ether = rx[Ether]
self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
@@ -1080,6 +1086,62 @@ class ARPTestCase(VppTestCase):
self.pg0.remote_ip4,
self.pg1.remote_hosts[1].ip4)
+ def test_arp_static(self):
+ """ ARP Static"""
+ self.pg2.generate_remote_hosts(3)
+
+ #
+ # Add a static ARP entry
+ #
+ static_arp = VppNeighbor(self,
+ self.pg2.sw_if_index,
+ self.pg2.remote_hosts[1].mac,
+ self.pg2.remote_hosts[1].ip4,
+ is_static=1)
+ static_arp.add_vpp_config()
+
+ #
+ # Add the connected prefix to the interface
+ #
+ self.pg2.config_ip4()
+
+ #
+ # We should now find the adj-fib
+ #
+ self.assertTrue(find_nbr(self,
+ self.pg2.sw_if_index,
+ self.pg2.remote_hosts[1].ip4,
+ is_static=1))
+ self.assertTrue(find_route(self,
+ self.pg2.remote_hosts[1].ip4,
+ 32))
+
+ #
+ # remove the connected
+ #
+ self.pg2.unconfig_ip4()
+
+ #
+ # put the interface into table 1
+ #
+ self.pg2.set_table_ip4(1)
+
+ #
+ # configure the same connected and expect to find the
+ # adj fib in the new table
+ #
+ self.pg2.config_ip4()
+ self.assertTrue(find_route(self,
+ self.pg2.remote_hosts[1].ip4,
+ 32,
+ table_id=1))
+
+ #
+ # clean-up
+ #
+ self.pg2.unconfig_ip4()
+ self.pg2.set_table_ip4(0)
+
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)
diff --git a/test/vpp_ip_route.py b/test/vpp_ip_route.py
index 2c489e3ccb0..b79937939c0 100644
--- a/test/vpp_ip_route.py
+++ b/test/vpp_ip_route.py
@@ -54,6 +54,46 @@ def find_route(test, ip_addr, len, table_id=0, inet=AF_INET):
return False
+class VppIpTable(VppObject):
+
+ def __init__(self,
+ test,
+ table_id,
+ is_ip6=0):
+ self._test = test
+ self.table_id = table_id
+ self.is_ip6 = is_ip6
+
+ def add_vpp_config(self):
+ self._test.vapi.ip_table_add_del(
+ self.table_id,
+ is_ipv6=self.is_ip6,
+ is_add=1)
+ self._test.registry.register(self, self._test.logger)
+
+ def remove_vpp_config(self):
+ self._test.vapi.ip_table_add_del(
+ self.table_id,
+ is_ipv6=self.is_ip6,
+ is_add=0)
+
+ def query_vpp_config(self):
+ # find the default route
+ return find_route(self._test,
+ "::" if self.is_ip6 else "0.0.0.0",
+ 0,
+ self.table_id,
+ inet=AF_INET6 if self.is_ip6 == 1 else AF_INET)
+
+ def __str__(self):
+ return self.object_id()
+
+ def object_id(self):
+ return ("table-%s-%d" %
+ ("v6" if self.is_ip6 == 1 else "v4",
+ self.table_id))
+
+
class VppRoutePath(object):
def __init__(
@@ -391,6 +431,39 @@ class VppMplsIpBind(VppObject):
self.dest_addr_len))
+class VppMplsTable(VppObject):
+
+ def __init__(self,
+ test,
+ table_id):
+ self._test = test
+ self.table_id = table_id
+
+ def add_vpp_config(self):
+ self._test.vapi.mpls_table_add_del(
+ self.table_id,
+ is_add=1)
+ self._test.registry.register(self, self._test.logger)
+
+ def remove_vpp_config(self):
+ self._test.vapi.mpls_table_add_del(
+ self.table_id,
+ is_add=0)
+
+ def query_vpp_config(self):
+ # find the default route
+ dump = self._test.vapi.mpls_fib_dump()
+ if len(dump):
+ return True
+ return False
+
+ def __str__(self):
+ return self.object_id()
+
+ def object_id(self):
+ return ("table-mpls-%d" % (self.table_id))
+
+
class VppMplsRoute(VppObject):
"""
MPLS Route/LSP
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index b70da026901..519aff80899 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -652,6 +652,24 @@ class VppPapiProvider(object):
return self.api(self.papi.delete_loopback,
{'sw_if_index': sw_if_index, })
+ def ip_table_add_del(self,
+ table_id,
+ is_add=1,
+ is_ipv6=0):
+ """
+
+ :param table_id
+ :param is_add: (Default value = 1)
+ :param is_ipv6: (Default value = 0)
+
+ """
+
+ return self.api(
+ self.papi.ip_table_add_del,
+ {'table_id': table_id,
+ 'is_add': is_add,
+ 'is_ipv6': is_ipv6})
+
def ip_add_del_route(
self,
dst_address,
@@ -664,7 +682,6 @@ class VppPapiProvider(object):
next_hop_n_out_labels=0,
next_hop_out_label_stack=[],
next_hop_via_label=MPLS_LABEL_INVALID,
- create_vrf_if_needed=0,
is_resolve_host=0,
is_resolve_attached=0,
classify_table_index=0xFFFFFFFF,
@@ -687,7 +704,6 @@ class VppPapiProvider(object):
:param vrf_id: (Default value = 0)
:param lookup_in_vrf: (Default value = 0)
:param classify_table_index: (Default value = 0xFFFFFFFF)
- :param create_vrf_if_needed: (Default value = 0)
:param is_add: (Default value = 1)
:param is_drop: (Default value = 0)
:param is_ipv6: (Default value = 0)
@@ -707,7 +723,6 @@ class VppPapiProvider(object):
'table_id': table_id,
'classify_table_index': classify_table_index,
'next_hop_table_id': next_hop_table_id,
- 'create_vrf_if_needed': create_vrf_if_needed,
'is_add': is_add,
'is_drop': is_drop,
'is_unreach': is_unreach,
@@ -912,6 +927,22 @@ class VppPapiProvider(object):
def mpls_fib_dump(self):
return self.api(self.papi.mpls_fib_dump, {})
+ def mpls_table_add_del(
+ self,
+ table_id,
+ is_add=1):
+ """
+
+ :param table_id
+ :param is_add: (Default value = 1)
+
+ """
+
+ return self.api(
+ self.papi.mpls_table_add_del,
+ {'mt_table_id': table_id,
+ 'mt_is_add': is_add})
+
def mpls_route_add_del(
self,
label,
@@ -925,7 +956,6 @@ class VppPapiProvider(object):
next_hop_n_out_labels=0,
next_hop_out_label_stack=[],
next_hop_via_label=MPLS_LABEL_INVALID,
- create_vrf_if_needed=0,
is_resolve_host=0,
is_resolve_attached=0,
is_interface_rx=0,
@@ -947,7 +977,6 @@ class VppPapiProvider(object):
:param vrf_id: (Default value = 0)
:param lookup_in_vrf: (Default value = 0)
:param classify_table_index: (Default value = 0xFFFFFFFF)
- :param create_vrf_if_needed: (Default value = 0)
:param is_add: (Default value = 1)
:param is_drop: (Default value = 0)
:param is_ipv6: (Default value = 0)
@@ -968,7 +997,6 @@ class VppPapiProvider(object):
'mr_eos': eos,
'mr_table_id': table_id,
'mr_classify_table_index': classify_table_index,
- 'mr_create_table_if_needed': create_vrf_if_needed,
'mr_is_add': is_add,
'mr_is_classify': is_classify,
'mr_is_multipath': is_multipath,
@@ -994,7 +1022,6 @@ class VppPapiProvider(object):
table_id=0,
ip_table_id=0,
is_ip4=1,
- create_vrf_if_needed=0,
is_bind=1):
"""
"""
@@ -1003,7 +1030,6 @@ class VppPapiProvider(object):
{'mb_mpls_table_id': table_id,
'mb_label': label,
'mb_ip_table_id': ip_table_id,
- 'mb_create_table_if_needed': create_vrf_if_needed,
'mb_is_bind': is_bind,
'mb_is_ip4': is_ip4,
'mb_address_length': dst_address_length,
@@ -1020,7 +1046,6 @@ class VppPapiProvider(object):
next_hop_n_out_labels=0,
next_hop_out_label_stack=[],
next_hop_via_label=MPLS_LABEL_INVALID,
- create_vrf_if_needed=0,
is_add=1,
l2_only=0,
is_multicast=0):
@@ -1034,7 +1059,6 @@ class VppPapiProvider(object):
:param vrf_id: (Default value = 0)
:param lookup_in_vrf: (Default value = 0)
:param classify_table_index: (Default value = 0xFFFFFFFF)
- :param create_vrf_if_needed: (Default value = 0)
:param is_add: (Default value = 1)
:param is_drop: (Default value = 0)
:param is_ipv6: (Default value = 0)
@@ -1844,7 +1868,6 @@ class VppPapiProvider(object):
i_flags,
rpf_id=0,
table_id=0,
- create_vrf_if_needed=0,
is_add=1,
is_ipv6=0,
is_local=0):
@@ -1857,7 +1880,6 @@ class VppPapiProvider(object):
'itf_flags': i_flags,
'table_id': table_id,
'rpf_id': rpf_id,
- 'create_vrf_if_needed': create_vrf_if_needed,
'is_add': is_add,
'is_ipv6': is_ipv6,
'is_local': is_local,