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) \
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 */
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)
}
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)
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;
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
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);
{
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;
{
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;
}
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;
}
}
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;
}
}
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;
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)
{
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
&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);
}
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)
{
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
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);
}
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
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
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);
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);
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)
{
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);
{
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);
}
}
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);
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 =
}
}
+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
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
{
}
}
+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 = ðernet_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)
{
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;
}
{
ethernet_arp_main_t *am = ðernet_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);
}
* 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);
}
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);
return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
}
+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)
{
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) {
#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,
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
{
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
{
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;
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);
u32
fib_table_create_and_lock (fib_protocol_t proto,
+ fib_source_t src,
const char *const fmt,
...)
{
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);
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
#include <vnet/mpls/mpls.h>
#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
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.
*
* @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
* @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,
...);
*
* @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
*
* @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
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++)
{
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());
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++)
{
/*
* 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());
*/
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
*/
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
&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());
/*
* 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),
*/
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",
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;
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);
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
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)
* @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
}
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;
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
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)
* \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)
}
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;
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)
{
}
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
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);
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
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 */
/*
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.
*
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;
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;
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)
{
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;
}
{
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)
{
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
*/
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;
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;
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)
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)
{
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);
}
}
}
+
+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,
*/
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
{
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)
{
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));
REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
}
+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);
}
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
{
*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
{
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);
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);
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))
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);
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",
.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 *
{
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);
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);
}
}
/*
* 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
/* 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);
*/
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);
}
}
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)
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);
{
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);
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);
}
l3s = lisp_gpe_sub_interface_get_i (l3si);
+ ASSERT (0 != l3s->locks);
l3s->locks--;
if (0 == l3s->locks)
};
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;
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
}
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);
}
* @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)
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 = {
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),
}
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);
}
* @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
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)
{
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,
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;
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:
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)
{
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
#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
/**
* number of locks on the table
*/
- u16 mft_locks;
+ u16 mft_locks[MFIB_TABLE_N_LOCKS];
/**
* Table ID (hash key) for this FIB.
* 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
*
* @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);
/**
*
* @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
*
* @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
#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>
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,
/*
* 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,
/*
* 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)),
*/
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
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 { \
[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
*/
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;
}
{
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 *
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;
.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)
{
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;
/* 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;
/* 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;
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);
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 */
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)
{
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);
}
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 ?
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);
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)
{
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");
}
/* 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;
}
/* 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;
}
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);
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);
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
# 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()
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)
"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"""
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"""
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
# 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:
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 = []
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
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()
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)
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()
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)
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)
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):
"""
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
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()
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)
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)
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):
"""
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
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
#
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)
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
# 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()
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(
# 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()
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)
# 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()
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
# 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):
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)
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()
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 """
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)
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
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()
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")
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)
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__(
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
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,
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,
: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)
'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,
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,
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,
: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)
'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,
table_id=0,
ip_table_id=0,
is_ip4=1,
- create_vrf_if_needed=0,
is_bind=1):
"""
"""
{'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,
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):
: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)
i_flags,
rpf_id=0,
table_id=0,
- create_vrf_if_needed=0,
is_add=1,
is_ipv6=0,
is_local=0):
'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,