aboutsummaryrefslogtreecommitdiffstats
path: root/vnet
diff options
context:
space:
mode:
authorPavel Kotucek <pkotucek@cisco.com>2016-11-15 09:19:11 +0100
committerDamjan Marion <dmarion.lists@gmail.com>2016-11-17 21:03:25 +0000
commit7490a752814187ed03c0deca4d836b0dca09fb4b (patch)
tree64296629669dba3ba87b580d37bc838c679d546e /vnet
parent999bbc4a2088c532d75e401703bd9205cf217c84 (diff)
feature: API/CLI to enable/disable feature per interface
Change-Id: I91d5f5648189143903eb973fdc60de9880fd47c2 Signed-off-by: Pavel Kotucek <pkotucek@cisco.com>
Diffstat (limited to 'vnet')
-rw-r--r--vnet/vnet/api_errno.h3
-rw-r--r--vnet/vnet/feature/feature.c104
-rw-r--r--vnet/vnet/feature/feature.h10
3 files changed, 116 insertions, 1 deletions
diff --git a/vnet/vnet/api_errno.h b/vnet/vnet/api_errno.h
index baf3c615974..50d6f731035 100644
--- a/vnet/vnet/api_errno.h
+++ b/vnet/vnet/api_errno.h
@@ -89,7 +89,8 @@ _(EXCEEDED_NUMBER_OF_RANGES_CAPACITY, -95, "Operation would exceed configured ca
_(EXCEEDED_NUMBER_OF_PORTS_CAPACITY, -96, "Operation would exceed capacity of number of ports") \
_(INVALID_ADDRESS_FAMILY, -97, "Invalid address family") \
_(INVALID_SUB_SW_IF_INDEX, -98, "Invalid sub-interface sw_if_index") \
-_(TABLE_TOO_BIG, -99, "Table too big")
+_(TABLE_TOO_BIG, -99, "Table too big") \
+_(CANNOT_ENABLE_DISABLE_FEATURE, -100, "Cannot enable/disable feature")
typedef enum
{
diff --git a/vnet/vnet/feature/feature.c b/vnet/vnet/feature/feature.c
index c8cde360814..e1d172e5707 100644
--- a/vnet/vnet/feature/feature.c
+++ b/vnet/vnet/feature/feature.c
@@ -152,6 +152,27 @@ vnet_get_feature_arc_index (const char *s)
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)
{
@@ -342,6 +363,89 @@ vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index)
}
}
+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
*
diff --git a/vnet/vnet/feature/feature.h b/vnet/vnet/feature/feature.h
index 667c5e36b62..96d573b69f6 100644
--- a/vnet/vnet/feature/feature.h
+++ b/vnet/vnet/feature/feature.h
@@ -34,6 +34,10 @@ typedef struct _vnet_feature_arc_registration
u8 *arc_index_ptr;
} vnet_feature_arc_registration_t;
+/* Enable feature callback. */
+typedef clib_error_t *(vnet_feature_enable_disable_function_t)
+ (u32 sw_if_index, int enable_disable);
+
/** feature registration object */
typedef struct _vnet_feature_registration
{
@@ -50,6 +54,9 @@ typedef struct _vnet_feature_registration
char **runs_before;
/** Constraints of the form "this feature runs after Y" */
char **runs_after;
+
+ /** Function to enable/disable feature **/
+ vnet_feature_enable_disable_function_t *enable_disable_cb;
} vnet_feature_registration_t;
typedef struct vnet_feature_config_main_t_
@@ -121,6 +128,9 @@ vnet_config_update_feature_count (vnet_feature_main_t * fm, u8 arc,
u32 vnet_get_feature_index (u8 arc, const char *s);
u8 vnet_get_feature_arc_index (const char *s);
+vnet_feature_registration_t *vnet_get_feature_reg (const char *arc_name,
+ const char *node_name);
+
int
vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,