#include <vnet/fib/ip4_fib.h>
/*
- * A table of pefixes to be added to tables and the sources for them
+ * A table of prefixes to be added to tables and the sources for them
*/
typedef struct ip4_fib_table_special_prefix_t_ {
fib_prefix_t ift_prefix;
ip4_fib_t *v4_fib;
void *old_heap;
- pool_get_aligned(ip4_main.fibs, fib_table, CLIB_CACHE_LINE_BYTES);
- memset(fib_table, 0, sizeof(*fib_table));
+ pool_get(ip4_main.fibs, fib_table);
+ clib_memset(fib_table, 0, sizeof(*fib_table));
old_heap = clib_mem_set_heap (ip4_main.mtrie_mheap);
pool_get_aligned(ip4_main.v4_fibs, v4_fib, CLIB_CACHE_LINE_BYTES);
v4_fib->table_id =
table_id;
fib_table->ft_flow_hash_config = IP_FLOW_HASH_DEFAULT;
- v4_fib->fwd_classify_table_index = ~0;
- v4_fib->rev_classify_table_index = ~0;
fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP4, src);
if (NULL == result)
{
/*
- * removing a non-existant entry. i'll allow it.
+ * removing a non-existent entry. i'll allow it.
*/
}
else
const dpo_id_t *dpo,
u32 cover_index)
{
- fib_prefix_t cover_prefix = {
- .fp_len = 0,
- };
+ const fib_prefix_t *cover_prefix;
const dpo_id_t *cover_dpo;
/*
* covering prefix, so it can fill the plys with the correct replacement
* for the entry being removed
*/
- fib_entry_get_prefix(cover_index, &cover_prefix);
+ cover_prefix = fib_entry_get_prefix(cover_index);
cover_dpo = fib_entry_contribute_ip_forwarding(cover_index);
ip4_fib_mtrie_route_del(&fib->mtrie,
addr, len, dpo->dpoi_index,
- cover_prefix.fp_len,
+ cover_prefix->fp_len,
cover_dpo->dpoi_index);
}
fib_table_walk_fn_t fn,
void *ctx)
{
+ fib_prefix_t root = {
+ .fp_proto = FIB_PROTOCOL_IP4,
+ // address and length default to all 0
+ };
+
+ /*
+ * A full tree walk is the dengenerate case of a sub-tree from
+ * the very root
+ */
+ return (ip4_fib_table_sub_tree_walk(fib, &root, fn, ctx));
+}
+
+void
+ip4_fib_table_sub_tree_walk (ip4_fib_t *fib,
+ const fib_prefix_t *root,
+ fib_table_walk_fn_t fn,
+ void *ctx)
+{
+ fib_prefix_t *sub_trees = NULL;
int i;
- for (i = 0; i < ARRAY_LEN (fib->fib_entry_by_dst_address); i++)
+ /*
+ * There is no efficient way to walk this array of hash tables.
+ * so we walk each table with a mask length greater than and equal to
+ * the required root and check it is covered by the root.
+ */
+ for (i = root->fp_len;
+ i < ARRAY_LEN (fib->fib_entry_by_dst_address);
+ i++)
{
uword * hash = fib->fib_entry_by_dst_address[i];
if (NULL != hash)
{
+ ip4_address_t key;
hash_pair_t * p;
hash_foreach_pair (p, hash,
({
- fn(p->value[0], ctx);
+ key.as_u32 = p->key;
+ if (ip4_destination_matches_route(&ip4_main,
+ &key,
+ &root->fp_addr.ip4,
+ root->fp_len))
+ {
+ const fib_prefix_t *sub_tree;
+ int skip = 0;
+
+ /*
+ * exclude sub-trees the walk does not want to explore
+ */
+ vec_foreach(sub_tree, sub_trees)
+ {
+ if (ip4_destination_matches_route(&ip4_main,
+ &key,
+ &sub_tree->fp_addr.ip4,
+ sub_tree->fp_len))
+ {
+ skip = 1;
+ break;
+ }
+ }
+
+ if (!skip)
+ {
+ switch (fn(p->value[0], ctx))
+ {
+ case FIB_TABLE_WALK_CONTINUE:
+ break;
+ case FIB_TABLE_WALK_SUB_TREE_STOP: {
+ fib_prefix_t pfx = {
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_len = i,
+ .fp_addr.ip4 = key,
+ };
+ vec_add1(sub_trees, pfx);
+ break;
+ }
+ case FIB_TABLE_WALK_STOP:
+ goto done;
+ }
+ }
+ }
}));
}
}
+done:
+ vec_free(sub_trees);
+ return;
}
/**
fib_node_index_t *ifsw_indicies;
} ip4_fib_show_walk_ctx_t;
-static int
+static fib_table_walk_rc_t
ip4_fib_show_walk_cb (fib_node_index_t fib_entry_index,
void *arg)
{
vec_add1(ctx->ifsw_indicies, fib_entry_index);
- return (1);
+ return (FIB_TABLE_WALK_CONTINUE);
}
static void
u8 *
format_ip4_fib_table_memory (u8 * s, va_list * args)
{
- s = format(s, "%=30s %=6d %=8ld\n",
+#if USE_DLMALLOC == 0
+ s = format(s, "%=30s %=6d %=12ld\n",
"IPv4 unicast",
pool_elts(ip4_main.fibs),
mheap_bytes(ip4_main.mtrie_mheap));
+#else
+ s = format(s, "%=30s %=6d %=12ld\n",
+ "IPv4 unicast",
+ pool_elts(ip4_main.fibs),
+ mspace_footprint(ip4_main.mtrie_mheap));
+#endif
+
return (s);
}
if (memory)
{
- uword mtrie_size, hash_size;
+ uword mtrie_size, hash_size, *old_heap;
+
mtrie_size = ip4_fib_mtrie_memory_usage(&fib->mtrie);
hash_size = 0;
+ old_heap = clib_mem_set_heap (ip4_main.mtrie_mheap);
for (i = 0; i < ARRAY_LEN (fib->fib_entry_by_dst_address); i++)
{
uword * hash = fib->fib_entry_by_dst_address[i];
hash_size += hash_bytes(hash);
}
}
+ clib_mem_set_heap (old_heap);
+
if (verbose)
vlib_cli_output (vm, "%U mtrie:%d hash:%d",
format_fib_table_name, fib->index,
continue;
}
- s = format(s, "%U, fib_index:%d, flow hash:[%U] locks:[",
+ s = format(s, "%U, fib_index:%d, flow hash:[%U] epoch:%d flags:%U locks:[",
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_flow_hash_config,
+ fib_table->ft_epoch,
+ format_fib_table_flags, fib_table->ft_flags);
FOR_EACH_FIB_SOURCE(source)
{
if (0 != fib_table->ft_locks[source])
}));
if (memory)
+ {
vlib_cli_output (vm, "totals: mtrie:%ld hash:%ld all:%ld",
total_mtrie_memory,
total_hash_memory,
total_mtrie_memory + total_hash_memory);
-
+ vlib_cli_output (vm, "\nMtrie Mheap Usage: %U\n",
+ format_mheap, ip4_main.mtrie_mheap, 1);
+ }
return 0;
}