vm, port, vnet_dev_port_del_sec_if,
&(vnet_dev_port_del_sec_if_args_t){ .sw_if_index = args->sw_if_index });
}
+
+vnet_dev_rv_t
+vnet_dev_api_port_set_rss_key (vlib_main_t *vm,
+ vnet_dev_api_port_set_rss_key_args_t *args)
+{
+ vnet_dev_port_t *port = 0;
+ vnet_dev_t *dev = vnet_dev_by_index (args->dev_index);
+ vnet_dev_rv_t rv = VNET_DEV_OK;
+ vnet_dev_port_cfg_change_req_t req = {
+ .type = VNET_DEV_PORT_CFG_SET_RSS_KEY,
+ .rss_key = args->rss_key,
+ };
+
+ if (!dev)
+ return VNET_DEV_ERR_UNKNOWN_DEVICE;
+
+ log_debug (dev, "port %u rss_key %U", args->port_id,
+ format_hex_bytes_no_wrap, args->rss_key.key,
+ args->rss_key.length);
+
+ port = vnet_dev_get_port_by_id (dev, args->port_id);
+ if (!port)
+ return VNET_DEV_ERR_UNKNOWN_DEVICE;
+
+ rv = vnet_dev_port_cfg_change_req_validate (vm, port, &req);
+ if (rv != VNET_DEV_OK)
+ {
+ log_err (dev, "RSS key cannot be set");
+ return rv;
+ }
+
+ rv = vnet_dev_process_port_cfg_change_req (vm, port, &req);
+ if (rv != VNET_DEV_OK)
+ {
+ log_err (dev, "device failed to set RSS key");
+ return rv;
+ }
+
+ return rv;
+}
vnet_dev_api_port_del_sec_if (vlib_main_t *,
vnet_dev_api_port_del_sec_if_args_t *);
+typedef struct
+{
+ u32 dev_index;
+ vnet_dev_port_id_t port_id;
+ vnet_dev_rss_key_t rss_key;
+} vnet_dev_api_port_set_rss_key_args_t;
+
+vnet_dev_rv_t
+vnet_dev_api_port_set_rss_key (vlib_main_t *,
+ vnet_dev_api_port_set_rss_key_args_t *);
+
#endif /* _VNET_DEV_API_H_ */
else if (a->type == VNET_DEV_ARG_TYPE_UINT32)
{
u32 val, min = 0, max = CLIB_U32_MAX;
- if (!unformat (&in, "%u", &val))
+ if (!unformat (&in, "0x%x", &val) && !unformat (&in, "%u", &val))
{
err = format (0,
"unsigned integer in range %u - %u expected for "
.function = show_device_counters_cmd_fn,
.is_mp_safe = 1,
};
+
+static clib_error_t *
+device_set_rss_key_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
+{
+ vnet_dev_api_port_set_rss_key_args_t a = {};
+ vnet_dev_rv_t rv;
+ int device_id_set = 0;
+ int sw_if_index_set = 0;
+ vnet_dev_device_id_t device_id = {};
+ uint32_t sw_if_index, n;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "port %u", &n))
+ a.port_id = n;
+ else if (unformat (input, "dev %U", unformat_c_string_array, &device_id,
+ sizeof (device_id)))
+ device_id_set = 1;
+ else if (unformat (input, "key %U", unformat_vnet_dev_rss_key,
+ &a.rss_key))
+ ;
+ else if (unformat (input, "%U", unformat_vnet_sw_interface,
+ vnet_get_main (), &sw_if_index))
+ sw_if_index_set = 1;
+ else
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
+
+ if (sw_if_index_set == device_id_set)
+ return clib_error_return (
+ 0, "please specify either interface name or port id");
+
+ if (sw_if_index_set)
+ {
+ vnet_dev_port_t *port = vnet_dev_get_port_from_sw_if_index (sw_if_index);
+
+ if (port == 0)
+ return clib_error_return (0, "unsupported interface");
+ a.port_id = port->port_id;
+ a.dev_index = port->dev->index;
+ }
+ else
+ {
+ vnet_dev_t *dev = vnet_dev_by_id (device_id);
+ if (!dev)
+ return clib_error_return (0, "please specify valid device id");
+ a.dev_index = dev->index;
+ }
+
+ rv = vnet_dev_api_port_set_rss_key (vm, &a);
+
+ if (rv != VNET_DEV_OK)
+ return clib_error_return (0, "unable to set_rss_key: %U",
+ format_vnet_dev_rv, rv);
+
+ return 0;
+}
+
+VLIB_CLI_COMMAND (device_set_rss_key_cmd, static) = {
+ .path = "device set-rss-key",
+ .short_help = "device set-rss-key [<intf>] [port <port-id>] [dev "
+ "<device-id>] [key <rss-key>]",
+ .function = device_set_rss_key_cmd_fn,
+ .is_mp_safe = 1,
+};
.subclass_name = "config",
};
+typedef struct
+{
+ vnet_dev_api_create_port_if_args_t intf;
+ vnet_dev_api_port_set_rss_key_args_t rss_key_args;
+} port_config_t;
+
static clib_error_t *
vnet_dev_config_one_interface (vlib_main_t *vm, unformat_input_t *input,
- vnet_dev_api_create_port_if_args_t *args)
+ port_config_t *args)
{
clib_error_t *err = 0;
- log_debug (0, "port %u %U", args->port_id, format_unformat_input, input);
+ log_debug (0, "port %u %U", args->intf.port_id, format_unformat_input,
+ input);
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
u32 n;
- if (unformat (input, "name %U", unformat_c_string_array, args->intf_name,
- sizeof (args->intf_name)))
+ if (unformat (input, "name %U", unformat_c_string_array,
+ args->intf.intf_name, sizeof (args->intf.intf_name)))
;
else if (unformat (input, "num-rx-queues %u", &n))
- args->num_rx_queues = n;
+ args->intf.num_rx_queues = n;
else if (unformat (input, "num-tx-queues %u", &n))
- args->num_tx_queues = n;
+ args->intf.num_tx_queues = n;
else if (unformat (input, "rx-queue-size %u", &n))
- args->rx_queue_size = n;
+ args->intf.rx_queue_size = n;
else if (unformat (input, "tx-queue-size %u", &n))
- args->tx_queue_size = n;
+ args->intf.tx_queue_size = n;
+ else if (unformat (input, "rss-key %U", unformat_vnet_dev_rss_key,
+ &args->rss_key_args.rss_key))
+ ;
else if (unformat (input, "flags %U", unformat_vnet_dev_port_flags,
- &args->flags))
+ &args->intf.flags))
;
else if (unformat (input, "args %U", unformat_single_quoted_string,
- &args->args))
+ &args->intf.args))
;
else
{
return err;
}
-
static clib_error_t *
vnet_dev_config_one_device (vlib_main_t *vm, unformat_input_t *input,
char *device_id)
log_debug (0, "device %s %U", device_id, format_unformat_input, input);
clib_error_t *err = 0;
vnet_dev_api_attach_args_t args = {};
- vnet_dev_api_create_port_if_args_t *if_args_vec = 0, *if_args;
+ port_config_t *ports = 0, *p;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
else if (unformat (input, "port %u %U", &n, unformat_vlib_cli_sub_input,
&sub_input))
{
- vnet_dev_api_create_port_if_args_t *if_args;
- vec_add2 (if_args_vec, if_args, 1);
- if_args->port_id = n;
- err = vnet_dev_config_one_interface (vm, &sub_input, if_args);
+ vec_add2 (ports, p, 1);
+ p->intf.port_id = n;
+ err = vnet_dev_config_one_interface (vm, &sub_input, p);
unformat_free (&sub_input);
if (err)
break;
if (rv == VNET_DEV_OK)
{
- vec_foreach (if_args, if_args_vec)
+ vec_foreach (p, ports)
{
- if_args->dev_index = args.dev_index;
- rv = vnet_dev_api_create_port_if (vm, if_args);
+ p->intf.dev_index = args.dev_index;
+ rv = vnet_dev_api_create_port_if (vm, &p->intf);
if (rv != VNET_DEV_OK)
break;
+ if (p->rss_key_args.rss_key.length)
+ {
+ vnet_dev_api_port_set_rss_key_args_t *rka = &p->rss_key_args;
+ rka->port_id = p->intf.port_id;
+ rka->dev_index = p->intf.dev_index;
+ rv = vnet_dev_api_port_set_rss_key (vm, rka);
+ if (rv != VNET_DEV_OK)
+ break;
+ }
}
}
format_vnet_dev_rv, rv, device_id);
}
- vec_free (if_args_vec);
+ vec_free (ports);
return err;
}
_ (ADD_RX_FLOW) \
_ (DEL_RX_FLOW) \
_ (GET_RX_FLOW_COUNTER) \
- _ (RESET_RX_FLOW_COUNTER)
+ _ (RESET_RX_FLOW_COUNTER) \
+ _ (SET_RSS_KEY)
typedef enum
{
vnet_dev_hw_addr_t addr;
u16 max_rx_frame_size;
vnet_dev_queue_id_t queue_id;
+ vnet_dev_rss_key_t rss_key;
struct
{
u32 flow_index;
vnet_dev_node_t rx_node;
vnet_dev_node_t tx_node;
vnet_dev_port_interfaces_t *interfaces;
+ vnet_dev_rss_key_t rss_key;
CLIB_CACHE_LINE_ALIGN_MARK (data0);
u8 data[];
vnet_dev_arg_t *sec_if_args;
u16 data_size;
void *initial_data;
+ vnet_dev_rss_key_t default_rss_key;
} port;
vnet_dev_node_t *rx_node;
format_function_t format_vnet_dev_flow;
unformat_function_t unformat_vnet_dev_flags;
unformat_function_t unformat_vnet_dev_port_flags;
+unformat_function_t unformat_vnet_dev_rss_key;
typedef struct
{
s = format (s, " %U", format_vnet_dev_hw_addr, a);
}
}
+ if (port->rss_key.length)
+ s = format (s, "\n%URSS Key is %U", format_white_space, indent,
+ format_hex_bytes_no_wrap, port->rss_key.key,
+ port->rss_key.length);
s = format (s, "\n%UMax RX frame size is %u (max supported %u)",
format_white_space, indent, port->max_rx_frame_size,
port->attr.max_supported_rx_frame_size);
return s;
}
+
+uword
+unformat_vnet_dev_rss_key (unformat_input_t *input, va_list *args)
+{
+ vnet_dev_rss_key_t *k = va_arg (*args, vnet_dev_rss_key_t *);
+ u8 *v;
+ u32 len;
+
+ if (!(unformat_user (input, unformat_hex_string, &v)))
+ return 0;
+
+ len = vec_len (v);
+ if (len > sizeof (k->key))
+ {
+ vec_free (v);
+ return 0;
+ }
+
+ clib_memcpy (k->key, v, len);
+ k->length = len;
+ return 1;
+}
port->rx_node = *args->rx_node;
port->tx_node = *args->tx_node;
+ if (port->attr.caps.rss && args->port.default_rss_key.length)
+ port->rss_key = args->port.default_rss_key;
+
if (args->port.args)
for (vnet_dev_arg_t *a = args->port.args; a->type != VNET_DEV_ARG_END; a++)
vec_add1 (port->args, *a);
return VNET_DEV_ERR_NO_SUCH_ENTRY;
break;
+ case VNET_DEV_PORT_CFG_SET_RSS_KEY:
+ if (!port->attr.caps.rss)
+ return VNET_DEV_ERR_NOT_SUPPORTED;
+ break;
+
default:
break;
}
}
break;
+ case VNET_DEV_PORT_CFG_SET_RSS_KEY:
+ port->rss_key = req->rss_key;
+ break;
+
default:
break;
}
typedef struct vnet_dev_port vnet_dev_port_t;
typedef struct vnet_dev_rx_queue vnet_dev_rx_queue_t;
typedef struct vnet_dev_tx_queue vnet_dev_tx_queue_t;
+typedef struct
+{
+ u8 key[48];
+ u8 length;
+} vnet_dev_rss_key_t;
typedef enum
{