From de393bb76d8c221e1145f62070f51a9ca4191f9f Mon Sep 17 00:00:00 2001 From: Dave Barach Date: Thu, 23 Jun 2016 11:27:51 -0400 Subject: Show command support for ip feature paths "show ip features" displays all available features, in execution order. "show ip interface features " displays all features currently configures on an interface, in execution order. Change-Id: I489bbdb85799a01721ba60b12ffaffcab1e0d1df Signed-off-by: Dave Barach --- vnet/vnet/config.c | 15 +++- vnet/vnet/config.h | 3 + vnet/vnet/ip/ip4.h | 3 + vnet/vnet/ip/ip6.h | 3 + vnet/vnet/ip/ip_feature_registration.c | 126 ++++++++++++++++++++++++++++++++- 5 files changed, 147 insertions(+), 3 deletions(-) diff --git a/vnet/vnet/config.c b/vnet/vnet/config.c index d2bcdf7d..2e056c83 100644 --- a/vnet/vnet/config.c +++ b/vnet/vnet/config.c @@ -276,8 +276,15 @@ u32 vnet_config_add_feature (vlib_main_t * vm, new = find_config_with_features (vm, cm, new_features); new->reference_count += 1; - /* User gets pointer to config string first element (which defines the pool index - this config string comes from). */ + /* + * User gets pointer to config string first element + * (which defines the pool index + * this config string comes from). + */ + vec_validate (cm->config_pool_index_by_user_index, + new->config_string_heap_index + 1); + cm->config_pool_index_by_user_index [new->config_string_heap_index + 1] + = new - cm->config_pool; return new->config_string_heap_index + 1; } @@ -327,5 +334,9 @@ u32 vnet_config_del_feature (vlib_main_t * vm, new = find_config_with_features (vm, cm, new_features); new->reference_count += 1; + vec_validate (cm->config_pool_index_by_user_index, + new->config_string_heap_index + 1); + cm->config_pool_index_by_user_index [new->config_string_heap_index + 1] + = new - cm->config_pool; return new->config_string_heap_index + 1; } diff --git a/vnet/vnet/config.h b/vnet/vnet/config.h index 1ace30fe..3d507c7b 100644 --- a/vnet/vnet/config.h +++ b/vnet/vnet/config.h @@ -95,6 +95,9 @@ typedef struct { /* Interior feature processing nodes (not including start and end nodes). */ u32 * node_index_by_feature_index; + /* vnet_config pool index by user index */ + u32 * config_pool_index_by_user_index; + /* Temporary vector for holding config strings. Used to avoid continually allocating vectors. */ u32 * config_string_temp; diff --git a/vnet/vnet/ip/ip4.h b/vnet/vnet/ip/ip4.h index f005522b..b24f18d0 100644 --- a/vnet/vnet/ip/ip4.h +++ b/vnet/vnet/ip/ip4.h @@ -144,6 +144,9 @@ typedef struct ip4_main_t { /* Built-in multicast feature path indices */ u32 ip4_multicast_rx_feature_vpath; u32 ip4_multicast_rx_feature_lookup; + + /* Save results for show command */ + char ** feature_nodes[VNET_N_CAST]; /* Seed for Jenkins hash used to compute ip4 flow hash. */ u32 flow_hash_seed; diff --git a/vnet/vnet/ip/ip6.h b/vnet/vnet/ip/ip6.h index 70e32672..2a386fee 100644 --- a/vnet/vnet/ip/ip6.h +++ b/vnet/vnet/ip/ip6.h @@ -157,6 +157,9 @@ typedef struct ip6_main_t { u32 ip6_multicast_rx_feature_vpath; u32 ip6_multicast_rx_feature_lookup; + /* Save results for show command */ + char ** feature_nodes[VNET_N_CAST]; + /* Seed for Jenkins hash used to compute ip6 flow hash. */ u32 flow_hash_seed; diff --git a/vnet/vnet/ip/ip_feature_registration.c b/vnet/vnet/ip/ip_feature_registration.c index 02699c4f..e100b1e1 100644 --- a/vnet/vnet/ip/ip_feature_registration.c +++ b/vnet/vnet/ip/ip_feature_registration.c @@ -163,7 +163,9 @@ ip_feature_init_cast (vlib_main_t * vm, /* see if we got a partial order... */ if (vec_len (result) != n_features) - return clib_error_return (0, "ip4_feature_init_cast (cast=%d), no PO!"); + return clib_error_return + (0, "ip%s_feature_init_cast (cast=%d), no partial order!", + is_ip4 ? "4" : "6", cast); /* * We win. @@ -189,6 +191,12 @@ ip_feature_init_cast (vlib_main_t * vm, feature_nodes, vec_len(feature_nodes)); + /* Save a copy for show command */ + if (is_ip4) + im4->feature_nodes[cast] = feature_nodes; + else + im6->feature_nodes[cast] = feature_nodes; + /* Finally, clean up all the shit we allocated */ hash_foreach_pair (hp, index_by_name, ({ @@ -205,3 +213,119 @@ ip_feature_init_cast (vlib_main_t * vm, return 0; } +#define foreach_af_cast \ +_(4, VNET_UNICAST, "ip4 unicast") \ +_(4, VNET_MULTICAST, "ip4 multicast") \ +_(6, VNET_UNICAST, "ip6 unicast") \ +_(6, VNET_MULTICAST, "ip6 multicast") + +static clib_error_t * +show_ip_features_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + ip4_main_t * im4 = &ip4_main; + ip6_main_t * im6 = &ip6_main; + int i; + char ** features; + + vlib_cli_output (vm, "Available IP feature nodes"); + +#define _(a,c,s) \ + do { \ + features = im##a->feature_nodes[c]; \ + vlib_cli_output (vm, "%s:", s); \ + for (i = 0; i < vec_len(features); i++) \ + vlib_cli_output (vm, " %s\n", features[i]); \ + } while(0); + foreach_af_cast; +#undef _ + + return 0; +} + +VLIB_CLI_COMMAND (show_ip_features_command, static) = { + .path = "show ip features", + .short_help = "show ip features", + .function = show_ip_features_command_fn, +}; + +static clib_error_t * +show_ip_interface_features_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vnet_main_t * vnm = vnet_get_main(); + ip4_main_t * im4 = &ip4_main; + ip_lookup_main_t * lm4 = &im4->lookup_main; + ip6_main_t * im6 = &ip6_main; + ip_lookup_main_t * lm6 = &im6->lookup_main; + + ip_lookup_main_t * lm; + ip_config_main_t * cm; + vnet_config_main_t * vcm; + vnet_config_t * cfg; + u32 cfg_index; + vnet_config_feature_t * feat; + vlib_node_t * n; + u32 sw_if_index; + u32 node_index; + u32 current_config_index; + int i, af; + u32 cast; + + if (! unformat (input, "%U", unformat_vnet_sw_interface, + vnm, &sw_if_index)) + return clib_error_return (0, "Interface not specified..."); + + vlib_cli_output (vm, "IP feature paths configured on %U...", + format_vnet_sw_if_index_name, vnm, sw_if_index); + + + for (af = 0; af < 2; af++) + { + if (af == 0) + lm = lm4; + else + lm = lm6; + + for (cast = VNET_UNICAST; cast < VNET_N_CAST; cast++) + { + cm = lm->rx_config_mains + cast; + vcm = &cm->config_main; + + vlib_cli_output (vm, "\nipv%s %scast:", + (af == 0) ? "4" : "6", + cast == VNET_UNICAST ? + "uni": "multi"); + + current_config_index = vec_elt (cm->config_index_by_sw_if_index, + sw_if_index); + + ASSERT(current_config_index + < vec_len (vcm->config_pool_index_by_user_index)); + + cfg_index = + vcm->config_pool_index_by_user_index[current_config_index]; + cfg = pool_elt_at_index (vcm->config_pool, cfg_index); + + for (i = 0; i < vec_len(cfg->features); i++) + { + feat = cfg->features + i; + node_index = feat->node_index; + n = vlib_get_node (vm, node_index); + vlib_cli_output (vm, " %v", n->name); + } + } + } + + return 0; +} + +VLIB_CLI_COMMAND (show_ip_interface_features_command, static) = { + .path = "show ip interface features", + .short_help = "show ip interface features ", + .function = show_ip_interface_features_command_fn, +}; + + -- cgit 1.2.3-korg