char *s;
int i = 0;
areg->feature_arc_index = arc_index;
+ if (areg->arc_index_ptr)
+ *areg->arc_index_ptr = arc_index;
hash_set_mem (fm->arc_index_by_name, areg->arc_name,
pointer_to_uword (areg));
freg = fm->next_feature;
while (freg)
{
+ 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'",
areg = uword_to_pointer (p[0], vnet_feature_arc_registration_t *);
arc_index = areg->feature_arc_index;
- vec_add1 (fm->next_feature_by_arc[arc_index], *freg);
+ next = freg->next;
+ freg->next = fm->next_feature_by_arc[arc_index];
+ fm->next_feature_by_arc[arc_index] = freg;
/* next */
- freg = freg->next;
+ freg = next;
}
+ areg = fm->next_arc;
while (areg)
{
clib_error_t *error;
arc_index++;
}
- fm->device_input_feature_arc_index =
- vnet_get_feature_arc_index ("device-input");
return 0;
}
return reg->feature_arc_index;
}
+vnet_feature_registration_t *
+vnet_get_feature_reg (const char *arc_name, const char *node_name)
+{
+ u8 arc_index;
+
+ arc_index = vnet_get_feature_arc_index (arc_name);
+ if (arc_index == (u8) ~ 0)
+ return 0;
+
+ vnet_feature_main_t *fm = &feature_main;
+ vnet_feature_registration_t *reg;
+ uword *p;
+
+ p = hash_get_mem (fm->next_feature_by_name[arc_index], node_name);
+ if (p == 0)
+ return 0;
+
+ reg = uword_to_pointer (p[0], vnet_feature_registration_t *);
+ return reg;
+}
+
u32
vnet_get_feature_index (u8 arc, const char *s)
{
return ~0;
reg = uword_to_pointer (p[0], vnet_feature_registration_t *);
- return reg->feature_index_u32;
+ return reg->feature_index;
}
-void
-vnet_feature_enable_disable (const char *arc_name, const char *node_name,
- u32 sw_if_index, int enable_disable,
- void *feature_config, u32 n_feature_config_bytes)
+int
+vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,
+ u32 sw_if_index, int enable_disable,
+ void *feature_config,
+ u32 n_feature_config_bytes)
{
vnet_feature_main_t *fm = &feature_main;
vnet_feature_config_main_t *cm;
- u32 feature_index, ci;
- u8 arc_index;
+ u32 ci;
- arc_index = vnet_get_feature_arc_index (arc_name);
+ if (arc_index == (u8) ~ 0)
+ return VNET_API_ERROR_INVALID_VALUE;
- if (arc_index == ~0)
- return;
+ if (feature_index == ~0)
+ return VNET_API_ERROR_INVALID_VALUE_2;
cm = &fm->feature_config_mains[arc_index];
vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0);
- feature_index = vnet_get_feature_index (arc_index, node_name);
- if (feature_index == ~0)
- return;
ci = cm->config_index_by_sw_if_index[sw_if_index];
+ vec_validate (fm->feature_count_by_sw_if_index[arc_index], sw_if_index);
+ if (!enable_disable
+ && fm->feature_count_by_sw_if_index[arc_index][sw_if_index] < 1)
+ return 0;
+
ci = (enable_disable
? vnet_config_add_feature
: vnet_config_del_feature)
vnet_config_update_feature_count (fm, arc_index, sw_if_index,
enable_disable);
+ return 0;
+}
+
+int
+vnet_feature_enable_disable (const char *arc_name, const char *node_name,
+ u32 sw_if_index, int enable_disable,
+ void *feature_config, u32 n_feature_config_bytes)
+{
+ u32 feature_index;
+ u8 arc_index;
+
+ arc_index = vnet_get_feature_arc_index (arc_name);
+
+ if (arc_index == (u8) ~ 0)
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ feature_index = vnet_get_feature_index (arc_index, node_name);
+
+ return vnet_feature_enable_disable_with_index (arc_index, feature_index,
+ sw_if_index, enable_disable,
+ feature_config,
+ n_feature_config_bytes);
}
while (areg)
{
vlib_cli_output (vm, "%s:", areg->arc_name);
- vec_foreach (freg, fm->next_feature_by_arc[areg->feature_arc_index])
- {
- vlib_cli_output (vm, " %s\n", freg->node_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;
+ }
/* next */
}
}
+static clib_error_t *
+set_interface_features_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t *error = 0;
+
+ u8 *arc_name = 0;
+ u8 *feature_name = 0;
+ u32 sw_if_index = ~0;
+ u8 enable = 1;
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ goto done;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat
+ (line_input, "%U %v", unformat_vnet_sw_interface, vnm, &sw_if_index,
+ &feature_name))
+ ;
+ else if (unformat (line_input, "arc %v", &arc_name))
+ ;
+ else if (unformat (line_input, "disable"))
+ enable = 0;
+ else
+ {
+ error = unformat_parse_error (line_input);
+ goto done;
+ }
+ }
+
+ if (sw_if_index == ~0)
+ {
+ error = clib_error_return (0, "Interface not specified...");
+ goto done;
+ }
+
+ vec_add1 (arc_name, 0);
+ vec_add1 (feature_name, 0);
+
+ vnet_feature_registration_t *reg;
+ reg =
+ vnet_get_feature_reg ((const char *) arc_name,
+ (const char *) feature_name);
+ if (reg == 0)
+ {
+ error = clib_error_return (0, "Unknown feature...");
+ goto done;
+ }
+ if (reg->enable_disable_cb)
+ error = reg->enable_disable_cb (sw_if_index, enable);
+ if (!error)
+ vnet_feature_enable_disable ((const char *) arc_name,
+ (const char *) feature_name, sw_if_index,
+ enable, 0, 0);
+
+done:
+ vec_free (feature_name);
+ vec_free (arc_name);
+ return error;
+}
+
+/*?
+ * Set feature for given interface
+ *
+ * @cliexpar
+ * Example:
+ * @cliexcmd{set interface feature GigabitEthernet2/0/0 ip4_flow_classify arc ip4_unicast}
+ * @cliexend
+ * @endparblock
+?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (set_interface_feature_command, static) = {
+ .path = "set interface feature",
+ .short_help = "set interface feature <intfc> <feature_name> arc <arc_name>",
+ .function = set_interface_features_command_fn,
+};
+/* *INDENT-ON* */
+
/*
* fd.io coding-style-patch-verification: ON
*