feature: API/CLI to enable/disable feature per interface
Change-Id: I91d5f5648189143903eb973fdc60de9880fd47c2 Signed-off-by: Pavel Kotucek <pkotucek@cisco.com>
This commit is contained in:
Pavel Kotucek
committed by
Damjan Marion
parent
999bbc4a20
commit
7490a75281
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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,
|
||||
|
@ -3575,7 +3575,8 @@ _(ip_source_and_port_range_check_add_del_reply) \
|
||||
_(ip_source_and_port_range_check_interface_add_del_reply)\
|
||||
_(delete_subif_reply) \
|
||||
_(l2_interface_pbb_tag_rewrite_reply) \
|
||||
_(punt_reply)
|
||||
_(punt_reply) \
|
||||
_(feature_enable_disable_reply)
|
||||
|
||||
#define _(n) \
|
||||
static void vl_api_##n##_t_handler \
|
||||
@ -3817,7 +3818,8 @@ _(DELETE_SUBIF_REPLY, delete_subif_reply) \
|
||||
_(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
|
||||
_(PUNT_REPLY, punt_reply) \
|
||||
_(IP_FIB_DETAILS, ip_fib_details) \
|
||||
_(IP6_FIB_DETAILS, ip6_fib_details)
|
||||
_(IP6_FIB_DETAILS, ip6_fib_details) \
|
||||
_(FEATURE_ENABLE_DISABLE_REPLY, feature_enable_disable_reply)
|
||||
|
||||
/* M: construct, but don't yet send a message */
|
||||
|
||||
@ -16279,6 +16281,72 @@ api_flow_classify_dump (vat_main_t * vam)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
api_feature_enable_disable (vat_main_t * vam)
|
||||
{
|
||||
unformat_input_t *i = vam->input;
|
||||
vl_api_feature_enable_disable_t *mp;
|
||||
f64 timeout;
|
||||
u8 *arc_name = 0;
|
||||
u8 *feature_name = 0;
|
||||
u32 sw_if_index = ~0;
|
||||
u8 enable = 1;
|
||||
|
||||
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (i, "arc_name %s", &arc_name))
|
||||
;
|
||||
else if (unformat (i, "feature_name %s", &feature_name))
|
||||
;
|
||||
else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
|
||||
;
|
||||
else if (unformat (i, "sw_if_index %d", &sw_if_index))
|
||||
;
|
||||
else if (unformat (i, "disable"))
|
||||
enable = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (arc_name == 0)
|
||||
{
|
||||
errmsg ("missing arc name\n");
|
||||
return -99;
|
||||
}
|
||||
if (vec_len (arc_name) > 63)
|
||||
{
|
||||
errmsg ("arc name too long\n");
|
||||
}
|
||||
|
||||
if (feature_name == 0)
|
||||
{
|
||||
errmsg ("missing feature name\n");
|
||||
return -99;
|
||||
}
|
||||
if (vec_len (feature_name) > 63)
|
||||
{
|
||||
errmsg ("feature name too long\n");
|
||||
}
|
||||
|
||||
if (sw_if_index == ~0)
|
||||
{
|
||||
errmsg ("missing interface name or sw_if_index\n");
|
||||
return -99;
|
||||
}
|
||||
|
||||
/* Construct the API message */
|
||||
M (FEATURE_ENABLE_DISABLE, feature_enable_disable);
|
||||
mp->sw_if_index = ntohl (sw_if_index);
|
||||
mp->enable = enable;
|
||||
clib_memcpy (mp->arc_name, arc_name, vec_len (arc_name));
|
||||
clib_memcpy (mp->feature_name, feature_name, vec_len (feature_name));
|
||||
vec_free (arc_name);
|
||||
vec_free (feature_name);
|
||||
|
||||
S;
|
||||
W;
|
||||
}
|
||||
|
||||
static int
|
||||
q_or_quit (vat_main_t * vam)
|
||||
{
|
||||
@ -16889,7 +16957,9 @@ _(flow_classify_set_interface, \
|
||||
"<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>] [del]") \
|
||||
_(flow_classify_dump, "type [ip4|ip6]") \
|
||||
_(ip_fib_dump, "") \
|
||||
_(ip6_fib_dump, "")
|
||||
_(ip6_fib_dump, "") \
|
||||
_(feature_enable_disable, "arc_name <arc_name> " \
|
||||
"feature_name <feature_name> <intfc> | sw_if_index <nn> [disable]")
|
||||
|
||||
/* List of command functions, CLI names map directly to functions */
|
||||
#define foreach_cli_function \
|
||||
|
@ -89,6 +89,7 @@
|
||||
#include <vnet/ipsec-gre/ipsec_gre.h>
|
||||
#include <vnet/flow/flow_report_classify.h>
|
||||
#include <vnet/ip/punt.h>
|
||||
#include <vnet/feature/feature.h>
|
||||
|
||||
#undef BIHASH_TYPE
|
||||
#undef __included_bihash_template_h__
|
||||
@ -466,7 +467,8 @@ _(IPSEC_SPD_DUMP, ipsec_spd_dump) \
|
||||
_(IP_FIB_DUMP, ip_fib_dump) \
|
||||
_(IP_FIB_DETAILS, ip_fib_details) \
|
||||
_(IP6_FIB_DUMP, ip6_fib_dump) \
|
||||
_(IP6_FIB_DETAILS, ip6_fib_details)
|
||||
_(IP6_FIB_DETAILS, ip6_fib_details) \
|
||||
_(FEATURE_ENABLE_DISABLE, feature_enable_disable)
|
||||
|
||||
#define QUOTE_(x) #x
|
||||
#define QUOTE(x) QUOTE_(x)
|
||||
@ -9174,6 +9176,45 @@ vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp)
|
||||
{
|
||||
vl_api_feature_enable_disable_reply_t *rmp;
|
||||
int rv = 0;
|
||||
|
||||
u8 *arc_name = format (0, "%s%c", mp->arc_name, 0);
|
||||
u8 *feature_name = format (0, "%s%c", mp->feature_name, 0);
|
||||
u32 sw_if_index = ntohl (mp->sw_if_index);
|
||||
|
||||
vnet_feature_registration_t *reg;
|
||||
reg =
|
||||
vnet_get_feature_reg ((const char *) arc_name,
|
||||
(const char *) feature_name);
|
||||
if (reg == 0)
|
||||
rv = VNET_API_ERROR_INVALID_VALUE;
|
||||
else
|
||||
{
|
||||
clib_error_t *error = 0;
|
||||
|
||||
if (reg->enable_disable_cb)
|
||||
error = reg->enable_disable_cb (sw_if_index, mp->enable);
|
||||
if (!error)
|
||||
vnet_feature_enable_disable ((const char *) arc_name,
|
||||
(const char *) feature_name,
|
||||
sw_if_index, mp->enable, 0, 0);
|
||||
else
|
||||
{
|
||||
clib_error_report (error);
|
||||
rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
|
||||
}
|
||||
}
|
||||
|
||||
vec_free (feature_name);
|
||||
vec_free (arc_name);
|
||||
|
||||
REPLY_MACRO (VL_API_FEATURE_ENABLE_DISABLE_REPLY);
|
||||
}
|
||||
|
||||
#define BOUNCE_HANDLER(nn) \
|
||||
static void vl_api_##nn##_t_handler ( \
|
||||
vl_api_##nn##_t *mp) \
|
||||
|
@ -2892,6 +2892,21 @@ static void *vl_api_ioam_disable_t_print
|
||||
FINISH;
|
||||
}
|
||||
|
||||
static void *vl_api_feature_enable_disable_t_print
|
||||
(vl_api_feature_enable_disable_t * mp, void *handle)
|
||||
{
|
||||
u8 *s;
|
||||
|
||||
s = format (0, "SCRIPT: feature_enable_disable ");
|
||||
s = format (s, "arc_name %s ", mp->arc_name);
|
||||
s = format (s, "feature_name %s ", mp->feature_name);
|
||||
s = format (s, "sw_if_index %d ", ntohl (mp->sw_if_index));
|
||||
if (!mp->enable)
|
||||
s = format (s, "disable");
|
||||
|
||||
FINISH;
|
||||
}
|
||||
|
||||
#define foreach_custom_print_no_arg_function \
|
||||
_(lisp_eid_table_vni_dump) \
|
||||
_(lisp_map_resolver_dump) \
|
||||
@ -3062,7 +3077,8 @@ _(GET_FIRST_MSG_ID, get_first_msg_id) \
|
||||
_(IOAM_ENABLE, ioam_enable) \
|
||||
_(IOAM_DISABLE, ioam_disable) \
|
||||
_(IP_FIB_DUMP, ip_fib_dump) \
|
||||
_(IP6_FIB_DUMP, ip6_fib_dump)
|
||||
_(IP6_FIB_DUMP, ip6_fib_dump) \
|
||||
_(FEATURE_ENABLE_DISABLE, feature_enable_disable)
|
||||
void
|
||||
vl_msg_api_custom_dump_configure (api_main_t * am)
|
||||
{
|
||||
|
@ -5495,3 +5495,27 @@ define ipsec_spd_details {
|
||||
u64 packets;
|
||||
};
|
||||
|
||||
/** \brief Feature path enable/disable request
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param sw_if_index - the interface
|
||||
@param enable - 1 = on, 0 = off
|
||||
*/
|
||||
define feature_enable_disable {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 sw_if_index;
|
||||
u8 enable;
|
||||
u8 arc_name[64];
|
||||
u8 feature_name[64];
|
||||
};
|
||||
|
||||
/** \brief Reply to the eature path enable/disable request
|
||||
@param context - sender context which was passed in the request
|
||||
@param retval - return code for the request
|
||||
*/
|
||||
define feature_enable_disable_reply
|
||||
{
|
||||
u32 context;
|
||||
i32 retval;
|
||||
};
|
||||
|
Reference in New Issue
Block a user