X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ffib%2Fip4_fib.c;h=01f4a755ec265ab00534b4035136f5d86ab3685d;hb=6a5adc369591fcac2447e9809deaa22f56b53911;hp=0f2d3f7ad89d7881981b92c84b41ea8b8aa6c057;hpb=1ec3652c25c593a7dcaae293b2f7dbed6eb15963;p=vpp.git diff --git a/src/vnet/fib/ip4_fib.c b/src/vnet/fib/ip4_fib.c index 0f2d3f7ad89..01f4a755ec2 100644 --- a/src/vnet/fib/ip4_fib.c +++ b/src/vnet/fib/ip4_fib.c @@ -108,7 +108,7 @@ ip4_create_fib_with_table_id (u32 table_id, ip4_fib_t *v4_fib; void *old_heap; - pool_get_aligned(ip4_main.fibs, fib_table, CLIB_CACHE_LINE_BYTES); + pool_get(ip4_main.fibs, fib_table); memset(fib_table, 0, sizeof(*fib_table)); old_heap = clib_mem_set_heap (ip4_main.mtrie_mheap); @@ -129,8 +129,6 @@ ip4_create_fib_with_table_id (u32 table_id, 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); @@ -417,22 +415,95 @@ ip4_fib_table_walk (ip4_fib_t *fib, 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 efficent 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; } /** @@ -443,7 +514,7 @@ typedef struct ip4_fib_show_walk_ctx_t_ 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) { @@ -451,7 +522,7 @@ ip4_fib_show_walk_cb (fib_node_index_t fib_entry_index, vec_add1(ctx->ifsw_indicies, fib_entry_index); - return (1); + return (FIB_TABLE_WALK_CONTINUE); } static void @@ -496,10 +567,18 @@ ip4_fib_table_show_one (ip4_fib_t *fib, u8 * format_ip4_fib_table_memory (u8 * s, va_list * args) { +#if USE_DLMALLOC == 0 s = format(s, "%=30s %=6d %=8ld\n", "IPv4 unicast", pool_elts(ip4_main.fibs), mheap_bytes(ip4_main.mtrie_mheap)); +#else + s = format(s, "%=30s %=6d %=8ld\n", + "IPv4 unicast", + pool_elts(ip4_main.fibs), + mspace_footprint(ip4_main.mtrie_mheap)); +#endif + return (s); }