X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ffib%2Fip6_fib.c;h=bb092cea1bfaba5af34e3b12826a3d866331b964;hb=89541992000433b743cbbe8cb396faab42bcf6ae;hp=8fde6f9f46e35381ba05e5ccc96d86aeb6e4a81d;hpb=908a5ea6e247b4a15f0ec7e8ee8ebff799abdc4f;p=vpp.git diff --git a/src/vnet/fib/ip6_fib.c b/src/vnet/fib/ip6_fib.c index 8fde6f9f46e..bb092cea1bf 100644 --- a/src/vnet/fib/ip6_fib.c +++ b/src/vnet/fib/ip6_fib.c @@ -50,7 +50,8 @@ vnet_ip6_fib_init (u32 fib_index) } static u32 -create_fib_with_table_id (u32 table_id) +create_fib_with_table_id (u32 table_id, + fib_source_t src) { fib_table_t *fib_table; ip6_fib_t *v6_fib; @@ -77,29 +78,30 @@ create_fib_with_table_id (u32 table_id) fib_table->ft_flow_hash_config = IP_FLOW_HASH_DEFAULT; vnet_ip6_fib_init(fib_table->ft_index); - fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP6); + fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP6, src); return (fib_table->ft_index); } u32 -ip6_fib_table_find_or_create_and_lock (u32 table_id) +ip6_fib_table_find_or_create_and_lock (u32 table_id, + fib_source_t src) { uword * p; p = hash_get (ip6_main.fib_index_by_table_id, table_id); if (NULL == p) - return create_fib_with_table_id(table_id); + return create_fib_with_table_id(table_id, src); - fib_table_lock(p[0], FIB_PROTOCOL_IP6); + fib_table_lock(p[0], FIB_PROTOCOL_IP6, src); return (p[0]); } u32 -ip6_fib_table_create_and_lock (void) +ip6_fib_table_create_and_lock (fib_source_t src) { - return (create_fib_with_table_id(~0)); + return (create_fib_with_table_id(~0, src)); } void @@ -435,6 +437,8 @@ typedef struct ip6_fib_walk_ctx_t_ u32 i6w_fib_index; fib_table_walk_fn_t i6w_fn; void *i6w_ctx; + fib_prefix_t i6w_root; + fib_prefix_t *i6w_sub_trees; } ip6_fib_walk_ctx_t; static int @@ -442,11 +446,58 @@ ip6_fib_walk_cb (clib_bihash_kv_24_8_t * kvp, void *arg) { ip6_fib_walk_ctx_t *ctx = arg; + ip6_address_t key; if ((kvp->key[2] >> 32) == ctx->i6w_fib_index) { - ctx->i6w_fn(kvp->value, ctx->i6w_ctx); + key.as_u64[0] = kvp->key[0]; + key.as_u64[1] = kvp->key[1]; + + if (ip6_destination_matches_route(&ip6_main, + &key, + &ctx->i6w_root.fp_addr.ip6, + ctx->i6w_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, ctx->i6w_sub_trees) + { + if (ip6_destination_matches_route(&ip6_main, + &key, + &sub_tree->fp_addr.ip6, + sub_tree->fp_len)) + { + skip = 1; + break; + } + } + + if (!skip) + { + switch (ctx->i6w_fn(kvp->value, ctx->i6w_ctx)) + { + case FIB_TABLE_WALK_CONTINUE: + break; + case FIB_TABLE_WALK_SUB_TREE_STOP: { + fib_prefix_t pfx = { + .fp_proto = FIB_PROTOCOL_IP6, + .fp_len = kvp->key[2] & 0xffffffff, + .fp_addr.ip6 = key, + }; + vec_add1(ctx->i6w_sub_trees, pfx); + break; + } + case FIB_TABLE_WALK_STOP: + goto done; + } + } + } } +done: return (1); } @@ -460,20 +511,44 @@ ip6_fib_table_walk (u32 fib_index, .i6w_fib_index = fib_index, .i6w_fn = fn, .i6w_ctx = arg, + .i6w_root = { + .fp_proto = FIB_PROTOCOL_IP6, + }, + .i6w_sub_trees = NULL, }; - ip6_main_t *im = &ip6_main; - BV(clib_bihash_foreach_key_value_pair)(&im->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash, - ip6_fib_walk_cb, - &ctx); + BV(clib_bihash_foreach_key_value_pair)( + &ip6_main.ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash, + ip6_fib_walk_cb, + &ctx); + + vec_free(ctx.i6w_sub_trees); +} + +void +ip6_fib_table_sub_tree_walk (u32 fib_index, + const fib_prefix_t *root, + fib_table_walk_fn_t fn, + void *arg) +{ + ip6_fib_walk_ctx_t ctx = { + .i6w_fib_index = fib_index, + .i6w_fn = fn, + .i6w_ctx = arg, + .i6w_root = *root, + }; + BV(clib_bihash_foreach_key_value_pair)( + &ip6_main.ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash, + ip6_fib_walk_cb, + &ctx); } typedef struct ip6_fib_show_ctx_t_ { fib_node_index_t *entries; } ip6_fib_show_ctx_t; -static int +static fib_table_walk_rc_t ip6_fib_table_show_walk (fib_node_index_t fib_entry_index, void *arg) { @@ -481,7 +556,7 @@ ip6_fib_table_show_walk (fib_node_index_t fib_entry_index, vec_add1(ctx->entries, fib_entry_index); - return (1); + return (FIB_TABLE_WALK_CONTINUE); } static void @@ -522,6 +597,18 @@ ip6_fib_table_show_one (ip6_fib_t *fib, FIB_ENTRY_FORMAT_DETAIL)); } +u8 * +format_ip6_fib_table_memory (u8 * s, va_list * args) +{ + s = format(s, "%=30s %=6d %=8ld\n", + "IPv6 unicast", + pool_elts(ip6_main.fibs), + mheap_bytes(ip6_main.ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash.mheap) + + mheap_bytes(ip6_main.ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash.mheap)); + + return (s); +} + typedef struct { u32 fib_index; u64 count_by_prefix_length[129]; @@ -588,16 +675,33 @@ ip6_show_fib (vlib_main_t * vm, pool_foreach (fib_table, im6->fibs, ({ + fib_source_t source; + u8 *s = NULL; + fib = pool_elt_at_index(im6->v6_fibs, fib_table->ft_index); if (table_id >= 0 && table_id != (int)fib->table_id) continue; if (fib_index != ~0 && fib_index != (int)fib->index) continue; - vlib_cli_output (vm, "%s, fib_index:%d, flow hash:[%U] locks:%d", - fib_table->ft_desc, fib->index, - format_ip_flow_hash_config, fib_table->ft_flow_hash_config, - fib_table->ft_locks); + s = format(s, "%U, fib_index:%d, flow hash:[%U] locks:[", + format_fib_table_name, fib->index, + FIB_PROTOCOL_IP6, + fib->index, + format_ip_flow_hash_config, + fib_table->ft_flow_hash_config); + FOR_EACH_FIB_SOURCE(source) + { + if (0 != fib_table->ft_locks[source]) + { + s = format(s, "%U:%d, ", + format_fib_source, source, + fib_table->ft_locks[source]); + } + } + s = format (s, "]"); + vlib_cli_output (vm, "%v", s); + vec_free(s); /* Show summary? */ if (! verbose)