X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ffeature%2Ffeature.c;h=2cdbcff88c89d96e77584088b431929e673b4b76;hb=2dd192b76774beb9c7960527fb3f397a2848f679;hp=80ef08d04a1cd529a9242083cd074ee55a28129d;hpb=614c13161815c2de21c4679cb217da1ebc4fdb76;p=vpp.git diff --git a/src/vnet/feature/feature.c b/src/vnet/feature/feature.c index 80ef08d04a1..2cdbcff88c8 100644 --- a/src/vnet/feature/feature.c +++ b/src/vnet/feature/feature.c @@ -14,6 +14,7 @@ */ #include +#include vnet_feature_main_t feature_main; @@ -23,6 +24,7 @@ vnet_feature_init (vlib_main_t * vm) vnet_feature_main_t *fm = &feature_main; vnet_feature_registration_t *freg; vnet_feature_arc_registration_t *areg; + vnet_feature_constraint_registration_t *creg; u32 arc_index = 0; fm->arc_index_by_name = hash_create_string (0, sizeof (uword)); @@ -57,6 +59,7 @@ vnet_feature_init (vlib_main_t * vm) vec_validate (fm->next_feature_by_name, arc_index - 1); vec_validate (fm->sw_if_index_has_features, arc_index - 1); vec_validate (fm->feature_count_by_sw_if_index, arc_index - 1); + vec_validate (fm->next_constraint_by_arc, arc_index - 1); freg = fm->next_feature; while (freg) @@ -64,20 +67,48 @@ vnet_feature_init (vlib_main_t * vm) vnet_feature_registration_t *next; uword *p = hash_get_mem (fm->arc_index_by_name, freg->arc_name); if (p == 0) - return clib_error_return (0, "Unknown feature arc '%s'", - freg->arc_name); + { + /* Don't start vpp with broken features arcs */ + clib_warning ("Unknown feature arc '%s'", freg->arc_name); + os_exit (1); + } areg = uword_to_pointer (p[0], vnet_feature_arc_registration_t *); arc_index = areg->feature_arc_index; next = freg->next; - freg->next = fm->next_feature_by_arc[arc_index]; + freg->next_in_arc = fm->next_feature_by_arc[arc_index]; fm->next_feature_by_arc[arc_index] = freg; /* next */ freg = next; } + /* Move bulk constraints to the constraint by arc lists */ + creg = fm->next_constraint; + while (creg) + { + vnet_feature_constraint_registration_t *next; + uword *p = hash_get_mem (fm->arc_index_by_name, creg->arc_name); + if (p == 0) + { + /* Don't start vpp with broken features arcs */ + clib_warning ("Unknown feature arc '%s'", creg->arc_name); + os_exit (1); + } + + areg = uword_to_pointer (p[0], vnet_feature_arc_registration_t *); + arc_index = areg->feature_arc_index; + + next = creg->next; + creg->next_in_arc = fm->next_constraint_by_arc[arc_index]; + fm->next_constraint_by_arc[arc_index] = creg; + + /* next */ + creg = next; + } + + areg = fm->next_arc; while (areg) { @@ -88,13 +119,14 @@ vnet_feature_init (vlib_main_t * vm) arc_index = areg->feature_arc_index; cm = &fm->feature_config_mains[arc_index]; vcm = &cm->config_main; - if ((error = vnet_feature_arc_init (vm, vcm, - areg->start_nodes, - areg->n_start_nodes, - fm->next_feature_by_arc[arc_index], - &fm->feature_nodes[arc_index]))) + if ((error = vnet_feature_arc_init + (vm, vcm, areg->start_nodes, areg->n_start_nodes, + fm->next_feature_by_arc[arc_index], + fm->next_constraint_by_arc[arc_index], + &fm->feature_nodes[arc_index]))) { - return error; + clib_error_report (error); + os_exit (1); } fm->next_feature_by_name[arc_index] = @@ -105,12 +137,9 @@ vnet_feature_init (vlib_main_t * vm) { hash_set_mem (fm->next_feature_by_name[arc_index], freg->node_name, pointer_to_uword (freg)); - freg = freg->next; + freg = freg->next_in_arc; } - cm->end_feature_index = - vnet_get_feature_index (arc_index, areg->end_node); - /* next */ areg = areg->next; arc_index++; @@ -184,7 +213,6 @@ vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index, vnet_feature_main_t *fm = &feature_main; vnet_feature_config_main_t *cm; i16 feature_count; - int is_first_or_last; u32 ci; if (arc_index == (u8) ~ 0) @@ -208,27 +236,21 @@ vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index, : vnet_config_del_feature) (vlib_get_main (), &cm->config_main, ci, feature_index, feature_config, n_feature_config_bytes); + if (ci == ~0) + { + return 0; + } cm->config_index_by_sw_if_index[sw_if_index] = ci; /* update feature count */ enable_disable = (enable_disable > 0); feature_count += enable_disable ? 1 : -1; - is_first_or_last = (feature_count == enable_disable); ASSERT (feature_count >= 0); - if (is_first_or_last && cm->end_feature_index != ~0) - { - /*register end node */ - ci = (enable_disable - ? vnet_config_add_feature - : vnet_config_del_feature) - (vlib_get_main (), &cm->config_main, ci, cm->end_feature_index, 0, 0); - cm->config_index_by_sw_if_index[sw_if_index] = ci; - } - fm->sw_if_index_has_features[arc_index] = clib_bitmap_set (fm->sw_if_index_has_features[arc_index], sw_if_index, (feature_count > 0)); + adj_feature_update (sw_if_index, arc_index, (feature_count > 0)); fm->feature_count_by_sw_if_index[arc_index][sw_if_index] = feature_count; return 0; @@ -255,6 +277,14 @@ vnet_feature_enable_disable (const char *arc_name, const char *node_name, n_feature_config_bytes); } +static int +feature_cmp (void *a1, void *a2) +{ + vnet_feature_registration_t *reg1 = a1; + vnet_feature_registration_t *reg2 = a2; + + return (int) reg1->feature_index - reg2->feature_index; +} /** Display the set of available driver features. Useful for verifying that expected features are present @@ -267,24 +297,45 @@ show_features_command_fn (vlib_main_t * vm, vnet_feature_main_t *fm = &feature_main; vnet_feature_arc_registration_t *areg; vnet_feature_registration_t *freg; + vnet_feature_registration_t *feature_regs = 0; + int verbose = 0; + + if (unformat (input, "verbose")) + verbose = 1; vlib_cli_output (vm, "Available feature paths"); areg = fm->next_arc; while (areg) { - vlib_cli_output (vm, "%s:", areg->arc_name); + if (verbose) + vlib_cli_output (vm, "[%2d] %s:", areg->feature_arc_index, + areg->arc_name); + else + vlib_cli_output (vm, "%s:", areg->arc_name); + freg = fm->next_feature_by_arc[areg->feature_arc_index]; while (freg) { - vlib_cli_output (vm, " %s\n", freg->node_name); - freg = freg->next; + vec_add1 (feature_regs, freg[0]); + freg = freg->next_in_arc; } + vec_sort_with_function (feature_regs, feature_cmp); + vec_foreach (freg, feature_regs) + { + if (verbose) + vlib_cli_output (vm, " [%2d]: %s\n", freg->feature_index, + freg->node_name); + else + vlib_cli_output (vm, " %s\n", freg->node_name); + } + vec_reset_length (feature_regs); /* next */ areg = areg->next; } + vec_free (feature_regs); return 0; } @@ -294,7 +345,7 @@ show_features_command_fn (vlib_main_t * vm, * * @cliexpar * Example: - * @cliexcmd{show ip features} + * @cliexcmd{show features [verbose]} * @cliexend * @endparblock ?*/ @@ -311,7 +362,7 @@ VLIB_CLI_COMMAND (show_features_command, static) = { */ void -vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index) +vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index, int verbose) { vnet_feature_main_t *fm = &feature_main; u32 node_index, current_config_index; @@ -325,7 +376,7 @@ vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index) vlib_node_t *n; int i; - vlib_cli_output (vm, "Driver feature paths configured on %U...", + vlib_cli_output (vm, "Feature paths configured on %U...", format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index); @@ -366,7 +417,10 @@ vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index) feat = cfg->features + i; node_index = feat->node_index; n = vlib_get_node (vm, node_index); - vlib_cli_output (vm, " %v", n->name); + if (verbose) + vlib_cli_output (vm, " [%2d] %v", feat->feature_index, n->name); + else + vlib_cli_output (vm, " %v", n->name); } } } @@ -387,7 +441,7 @@ set_interface_features_command_fn (vlib_main_t * vm, /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) - goto done; + return 0; while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { @@ -401,6 +455,8 @@ set_interface_features_command_fn (vlib_main_t * vm, enable = 0; else { + if (feature_name && arc_name) + break; error = unformat_parse_error (line_input); goto done; } @@ -450,7 +506,8 @@ done: /* *INDENT-OFF* */ VLIB_CLI_COMMAND (set_interface_feature_command, static) = { .path = "set interface feature", - .short_help = "set interface feature arc ", + .short_help = "set interface feature arc " + "[disable]", .function = set_interface_features_command_fn, }; /* *INDENT-ON* */