X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ffib%2Fip4_fib.c;h=a343c2b5f37a4b44ec980b24733ea7dd7db9cb26;hb=d6953332d;hp=a7915620b372c91f38bbfe89ed178d8e2a028635;hpb=04a75e3230ab71248fc29a56b9f64bdaee0c17ac;p=vpp.git diff --git a/src/vnet/fib/ip4_fib.c b/src/vnet/fib/ip4_fib.c index a7915620b37..a343c2b5f37 100644 --- a/src/vnet/fib/ip4_fib.c +++ b/src/vnet/fib/ip4_fib.c @@ -18,7 +18,7 @@ #include /* - * 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; @@ -99,35 +99,9 @@ static const ip4_fib_table_special_prefix_t ip4_specials[] = { } }; - -static u32 -ip4_create_fib_with_table_id (u32 table_id) +void +ip4_fib_hash_load_specials (u32 fib_index) { - fib_table_t *fib_table; - - pool_get_aligned(ip4_main.fibs, fib_table, CLIB_CACHE_LINE_BYTES); - memset(fib_table, 0, sizeof(*fib_table)); - - fib_table->ft_proto = FIB_PROTOCOL_IP4; - fib_table->ft_index = - fib_table->v4.index = - (fib_table - ip4_main.fibs); - - hash_set (ip4_main.fib_index_by_table_id, table_id, fib_table->ft_index); - - fib_table->ft_table_id = - fib_table->v4.table_id = - table_id; - fib_table->ft_flow_hash_config = - fib_table->v4.flow_hash_config = - IP_FLOW_HASH_DEFAULT; - fib_table->v4.fwd_classify_table_index = ~0; - fib_table->v4.rev_classify_table_index = ~0; - - fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP4); - - ip4_mtrie_init(&fib_table->v4.mtrie); - /* * add the special entries into the new FIB */ @@ -140,20 +114,16 @@ ip4_create_fib_with_table_id (u32 table_id) prefix.fp_addr.ip4.data_u32 = clib_host_to_net_u32(prefix.fp_addr.ip4.data_u32); - fib_table_entry_special_add(fib_table->ft_index, + fib_table_entry_special_add(fib_index, &prefix, ip4_specials[ii].ift_source, - ip4_specials[ii].ift_flag, - ADJ_INDEX_INVALID); + ip4_specials[ii].ift_flag); } - - return (fib_table->ft_index); } void -ip4_fib_table_destroy (ip4_fib_t *fib) +ip4_fib_hash_flush_specials (u32 fib_index) { - fib_table_t *fib_table = (fib_table_t*)fib; int ii; /* @@ -167,46 +137,112 @@ ip4_fib_table_destroy (ip4_fib_t *fib) prefix.fp_addr.ip4.data_u32 = clib_host_to_net_u32(prefix.fp_addr.ip4.data_u32); - fib_table_entry_special_remove(fib_table->ft_index, + fib_table_entry_special_remove(fib_index, &prefix, ip4_specials[ii].ift_source); } +} + +static u32 +ip4_create_fib_with_table_id (u32 table_id, + fib_source_t src) +{ + fib_table_t *fib_table; + ip4_fib_t *v4_fib; + + pool_get(ip4_main.fibs, fib_table); + clib_memset(fib_table, 0, sizeof(*fib_table)); + + pool_get_aligned(ip4_fibs, v4_fib, CLIB_CACHE_LINE_BYTES); + + fib_table->ft_proto = FIB_PROTOCOL_IP4; + fib_table->ft_index = (v4_fib - ip4_fibs); + + /* + * It is required that the index of the fib_table_t in its pool + * is the same as the index of the ip4_fib_t in its pool, since the + * rest of the code usues the 'fib_index' to mean either of these + * objects, depending on the context. + */ + ASSERT(fib_table->ft_index == fib_table - ip4_main.fibs); + + hash_set (ip4_main.fib_index_by_table_id, table_id, fib_table->ft_index); + + fib_table->ft_table_id = + v4_fib->hash.table_id = + table_id; + fib_table->ft_flow_hash_config = IP_FLOW_HASH_DEFAULT; + + fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP4, src); + + ip4_fib_table_init(v4_fib); + + /* + * add the special entries into the new FIB + */ + ip4_fib_hash_load_specials(fib_table - ip4_main.fibs); + + return (fib_table->ft_index); +} + +void +ip4_fib_table_destroy (u32 fib_index) +{ + fib_table_t *fib_table = pool_elt_at_index(ip4_main.fibs, fib_index); + ip4_fib_t *v4_fib = pool_elt_at_index(ip4_fibs, fib_table->ft_index); + u32 *n_locks; + + /* + * remove all the specials we added when the table was created. + * In reverse order so the default route is last. + */ + ip4_fib_hash_flush_specials(fib_table - ip4_main.fibs); /* * validate no more routes. */ - ASSERT(0 == fib_table->ft_total_route_counts); - FOR_EACH_FIB_SOURCE(ii) +#if CLIB_DEBUG > 0 + if (0 != fib_table->ft_total_route_counts) + fib_table_assert_empty(fib_table); +#endif + + vec_foreach(n_locks, fib_table->ft_src_route_counts) { - ASSERT(0 == fib_table->ft_src_route_counts[ii]); + ASSERT(0 == *n_locks); } if (~0 != fib_table->ft_table_id) { hash_unset (ip4_main.fib_index_by_table_id, fib_table->ft_table_id); } + + vec_free(fib_table->ft_src_route_counts); + ip4_fib_table_free(v4_fib); + + pool_put(ip4_fibs, v4_fib); pool_put(ip4_main.fibs, fib_table); } 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 @@ -223,184 +259,6 @@ ip4_fib_table_get_index_for_sw_if_index (u32 sw_if_index) return (ip4_main.fib_index_by_sw_if_index[sw_if_index]); } -flow_hash_config_t -ip4_fib_table_get_flow_hash_config (u32 fib_index) -{ - return (ip4_fib_get(fib_index)->flow_hash_config); -} - -/* - * ip4_fib_table_lookup_exact_match - * - * Exact match prefix lookup - */ -fib_node_index_t -ip4_fib_table_lookup_exact_match (const ip4_fib_t *fib, - const ip4_address_t *addr, - u32 len) -{ - uword * hash, * result; - u32 key; - - hash = fib->fib_entry_by_dst_address[len]; - key = (addr->data_u32 & ip4_main.fib_masks[len]); - - result = hash_get(hash, key); - - if (NULL != result) { - return (result[0]); - } - return (FIB_NODE_INDEX_INVALID); -} - -/* - * ip4_fib_table_lookup_adj - * - * Longest prefix match - */ -index_t -ip4_fib_table_lookup_lb (ip4_fib_t *fib, - const ip4_address_t *addr) -{ - fib_node_index_t fei; - - fei = ip4_fib_table_lookup(fib, addr, 32); - - if (FIB_NODE_INDEX_INVALID != fei) - { - const dpo_id_t *dpo; - - dpo = fib_entry_contribute_ip_forwarding(fei); - - return (dpo->dpoi_index); - } - return (INDEX_INVALID); -} - -/* - * ip4_fib_table_lookup - * - * Longest prefix match - */ -fib_node_index_t -ip4_fib_table_lookup (const ip4_fib_t *fib, - const ip4_address_t *addr, - u32 len) -{ - uword * hash, * result; - i32 mask_len; - u32 key; - - for (mask_len = len; mask_len >= 0; mask_len--) - { - hash = fib->fib_entry_by_dst_address[mask_len]; - key = (addr->data_u32 & ip4_main.fib_masks[mask_len]); - - result = hash_get (hash, key); - - if (NULL != result) { - return (result[0]); - } - } - return (FIB_NODE_INDEX_INVALID); -} - -void -ip4_fib_table_entry_insert (ip4_fib_t *fib, - const ip4_address_t *addr, - u32 len, - fib_node_index_t fib_entry_index) -{ - uword * hash, * result; - u32 key; - - key = (addr->data_u32 & ip4_main.fib_masks[len]); - hash = fib->fib_entry_by_dst_address[len]; - result = hash_get (hash, key); - - if (NULL == result) { - /* - * adding a new entry - */ - if (NULL == hash) { - hash = hash_create (32 /* elts */, sizeof (uword)); - hash_set_flags (hash, HASH_FLAG_NO_AUTO_SHRINK); - } - hash = hash_set(hash, key, fib_entry_index); - fib->fib_entry_by_dst_address[len] = hash; - } - else - { - ASSERT(0); - } -} - -void -ip4_fib_table_entry_remove (ip4_fib_t *fib, - const ip4_address_t *addr, - u32 len) -{ - uword * hash, * result; - u32 key; - - key = (addr->data_u32 & ip4_main.fib_masks[len]); - hash = fib->fib_entry_by_dst_address[len]; - result = hash_get (hash, key); - - if (NULL == result) - { - /* - * removing a non-existant entry. i'll allow it. - */ - } - else - { - hash_unset(hash, key); - } - - fib->fib_entry_by_dst_address[len] = hash; -} - -void -ip4_fib_table_fwding_dpo_update (ip4_fib_t *fib, - const ip4_address_t *addr, - u32 len, - const dpo_id_t *dpo) -{ - ip4_fib_mtrie_add_del_route(fib, *addr, len, dpo->dpoi_index, 0); // ADD -} - -void -ip4_fib_table_fwding_dpo_remove (ip4_fib_t *fib, - const ip4_address_t *addr, - u32 len, - const dpo_id_t *dpo) -{ - ip4_fib_mtrie_add_del_route(fib, *addr, len, dpo->dpoi_index, 1); // DELETE -} - -void -ip4_fib_table_walk (ip4_fib_t *fib, - fib_table_walk_fn_t fn, - void *ctx) -{ - int i; - - for (i = 0; i < ARRAY_LEN (fib->fib_entry_by_dst_address); i++) - { - uword * hash = fib->fib_entry_by_dst_address[i]; - - if (NULL != hash) - { - hash_pair_t * p; - - hash_foreach_pair (p, hash, - ({ - fn(p->value[0], ctx); - })); - } - } -} /** * Walk show context @@ -410,7 +268,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) { @@ -418,7 +276,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 @@ -449,12 +307,24 @@ static void ip4_fib_table_show_one (ip4_fib_t *fib, vlib_main_t * vm, ip4_address_t *address, - u32 mask_len) -{ + u32 mask_len, + int detail) +{ vlib_cli_output(vm, "%U", format_fib_entry, ip4_fib_table_lookup(fib, address, mask_len), - FIB_ENTRY_FORMAT_DETAIL); + (detail ? + FIB_ENTRY_FORMAT_DETAIL2 : + FIB_ENTRY_FORMAT_DETAIL)); +} + +u8 * +format_ip4_fib_table_memory (u8 * s, va_list * args) +{ + s = format(s, "%=30s %=6d\n", + "IPv4 unicast", + pool_elts(ip4_main.fibs)); + return (s); } static clib_error_t * @@ -463,24 +333,33 @@ ip4_show_fib (vlib_main_t * vm, vlib_cli_command_t * cmd) { ip4_main_t * im4 = &ip4_main; - fib_table_t * fib_table; - int verbose, matching, mtrie; + u64 total_mtrie_memory, total_hash_memory; + int verbose, matching, mtrie, memory; ip4_address_t matching_address; - u32 matching_mask = 32; - int i, table_id = -1, fib_index = ~0; + u32 fib_index, matching_mask = 32; + int i, table_id = -1, user_fib_index = ~0; + int detail = 0; verbose = 1; - matching = 0; - mtrie = 0; + matching = mtrie = memory = 0; + total_hash_memory = total_mtrie_memory = 0; + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "brief") || unformat (input, "summary") || unformat (input, "sum")) verbose = 0; + else if (unformat (input, "detail") || unformat (input, "det")) + detail = 1; + else if (unformat (input, "mtrie")) mtrie = 1; + else if (unformat (input, "mem") || + unformat (input, "memory")) + memory = 1; + else if (unformat (input, "%U/%d", unformat_ip4_address, &matching_address, &matching_mask)) matching = 1; @@ -490,33 +369,85 @@ ip4_show_fib (vlib_main_t * vm, else if (unformat (input, "table %d", &table_id)) ; - else if (unformat (input, "index %d", &fib_index)) + else if (unformat (input, "index %d", &user_fib_index)) ; else break; } - pool_foreach (fib_table, im4->fibs, - ({ - ip4_fib_t *fib = &fib_table->v4; + pool_foreach_index (fib_index, im4->fibs) + { + fib_table_t *fib_table = pool_elt_at_index(im4->fibs, fib_index); + ip4_fib_t *fib = pool_elt_at_index(ip4_fibs, fib_table->ft_index); + fib_source_t source; + u8 *s = NULL; - if (table_id >= 0 && table_id != (int)fib->table_id) + if (table_id >= 0 && table_id != (int)fib->hash.table_id) continue; - if (fib_index != ~0 && fib_index != (int)fib->index) + if (user_fib_index != ~0 && user_fib_index != fib_index) continue; - vlib_cli_output (vm, "%U, fib_index %d, flow hash: %U", - format_fib_table_name, fib->index, FIB_PROTOCOL_IP4, - fib->index, - format_ip_flow_hash_config, fib->flow_hash_config); + if (memory) + { + uword mtrie_size, hash_size; + + + mtrie_size = ip4_mtrie_memory_usage(&fib->mtrie); + hash_size = 0; + + for (i = 0; i < ARRAY_LEN (fib->hash.fib_entry_by_dst_address); i++) + { + uword * hash = fib->hash.fib_entry_by_dst_address[i]; + if (NULL != hash) + { + hash_size += hash_bytes(hash); + } + } + + if (verbose) + vlib_cli_output (vm, "%U mtrie:%d hash:%d", + format_fib_table_name, fib_index, + FIB_PROTOCOL_IP4, + mtrie_size, + hash_size); + total_mtrie_memory += mtrie_size; + total_hash_memory += hash_size; + continue; + } + + 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_epoch, + format_fib_table_flags, fib_table->ft_flags); + vec_foreach_index(source, fib_table->ft_locks) + { + 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 (mtrie) + { + vlib_cli_output (vm, "%U", format_ip4_mtrie, &fib->mtrie, verbose); + continue; + } if (! verbose) { vlib_cli_output (vm, "%=20s%=16s", "Prefix length", "Count"); - for (i = 0; i < ARRAY_LEN (fib->fib_entry_by_dst_address); i++) + for (i = 0; i < ARRAY_LEN (fib->hash.fib_entry_by_dst_address); i++) { - uword * hash = fib->fib_entry_by_dst_address[i]; + uword * hash = fib->hash.fib_entry_by_dst_address[i]; uword n_elts = hash_elts (hash); if (n_elts > 0) vlib_cli_output (vm, "%20d%16d", i, n_elts); @@ -530,13 +461,18 @@ ip4_show_fib (vlib_main_t * vm, } else { - ip4_fib_table_show_one(fib, vm, &matching_address, matching_mask); + ip4_fib_table_show_one(fib, vm, &matching_address, + matching_mask, detail); } + } - if (mtrie) - vlib_cli_output (vm, "%U", format_ip4_fib_mtrie, &fib->mtrie); - })); - + 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); + } return 0; } @@ -687,7 +623,7 @@ ip4_show_fib (vlib_main_t * vm, /* *INDENT-OFF* */ VLIB_CLI_COMMAND (ip4_show_fib_command, static) = { .path = "show ip fib", - .short_help = "show ip fib [summary] [table ] [index ] [[/]] [mtrie]", + .short_help = "show ip fib [summary] [table ] [index ] [[/]] [mtrie] [detail]", .function = ip4_show_fib, }; /* *INDENT-ON* */