From: Damjan Marion Date: Mon, 15 Sep 2025 17:35:48 +0000 (+0200) Subject: dev: add support for changing RSS key X-Git-Tag: v26.02-rc0~25 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=0f66f9ed9eeffa51072081394cd9d24194f8d995;p=vpp.git dev: add support for changing RSS key Type: improvement Change-Id: I40350be4c362d20f60b94c82faf564f06d8e86f6 Signed-off-by: Damjan Marion --- diff --git a/src/vnet/dev/api.c b/src/vnet/dev/api.c index 55c3de3b4ca..5787fe2a81c 100644 --- a/src/vnet/dev/api.c +++ b/src/vnet/dev/api.c @@ -344,3 +344,43 @@ vnet_dev_api_port_del_sec_if (vlib_main_t *vm, 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; +} diff --git a/src/vnet/dev/api.h b/src/vnet/dev/api.h index 3e552e4326e..24f24239739 100644 --- a/src/vnet/dev/api.h +++ b/src/vnet/dev/api.h @@ -88,4 +88,15 @@ vnet_dev_rv_t 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_ */ diff --git a/src/vnet/dev/args.c b/src/vnet/dev/args.c index e302517cc61..07d10787618 100644 --- a/src/vnet/dev/args.c +++ b/src/vnet/dev/args.c @@ -82,7 +82,7 @@ vnet_dev_arg_parse (vlib_main_t *vm, vnet_dev_t *dev, vnet_dev_arg_t *args, 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 " diff --git a/src/vnet/dev/cli.c b/src/vnet/dev/cli.c index 6002a2f0dee..90014f888b4 100644 --- a/src/vnet/dev/cli.c +++ b/src/vnet/dev/cli.c @@ -418,3 +418,70 @@ VLIB_CLI_COMMAND (show_device_counters_cmd, static) = { .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 [] [port ] [dev " + "] [key ]", + .function = device_set_rss_key_cmd_fn, + .is_mp_safe = 1, +}; diff --git a/src/vnet/dev/config.c b/src/vnet/dev/config.c index 1e428a544c7..9cb8e946835 100644 --- a/src/vnet/dev/config.c +++ b/src/vnet/dev/config.c @@ -15,34 +15,44 @@ VLIB_REGISTER_LOG_CLASS (dev_log, static) = { .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 { @@ -112,7 +122,6 @@ vnet_dev_config_driver_args (vlib_main_t *vm, unformat_input_t *input, return err; } - static clib_error_t * vnet_dev_config_one_device (vlib_main_t *vm, unformat_input_t *input, char *device_id) @@ -120,7 +129,7 @@ vnet_dev_config_one_device (vlib_main_t *vm, unformat_input_t *input, 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) { @@ -139,10 +148,9 @@ vnet_dev_config_one_device (vlib_main_t *vm, unformat_input_t *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; @@ -165,12 +173,21 @@ vnet_dev_config_one_device (vlib_main_t *vm, unformat_input_t *input, 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; + } } } @@ -179,7 +196,7 @@ vnet_dev_config_one_device (vlib_main_t *vm, unformat_input_t *input, format_vnet_dev_rv, rv, device_id); } - vec_free (if_args_vec); + vec_free (ports); return err; } diff --git a/src/vnet/dev/dev.h b/src/vnet/dev/dev.h index 2a72cb2898d..d70d174b384 100644 --- a/src/vnet/dev/dev.h +++ b/src/vnet/dev/dev.h @@ -158,7 +158,8 @@ typedef struct _ (ADD_RX_FLOW) \ _ (DEL_RX_FLOW) \ _ (GET_RX_FLOW_COUNTER) \ - _ (RESET_RX_FLOW_COUNTER) + _ (RESET_RX_FLOW_COUNTER) \ + _ (SET_RSS_KEY) typedef enum { @@ -180,6 +181,7 @@ typedef struct vnet_dev_port_cfg_change_req 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; @@ -393,6 +395,7 @@ typedef struct vnet_dev_port 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[]; @@ -528,6 +531,7 @@ typedef struct 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; @@ -755,6 +759,7 @@ format_function_t format_vnet_dev_tx_queue_info; 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 { diff --git a/src/vnet/dev/format.c b/src/vnet/dev/format.c index ffc4a3a70b4..eda1c7cb859 100644 --- a/src/vnet/dev/format.c +++ b/src/vnet/dev/format.c @@ -125,6 +125,10 @@ format_vnet_dev_port_info (u8 *s, va_list *args) 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); @@ -522,3 +526,25 @@ format_vnet_dev_flow (u8 *s, va_list *args) 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; +} diff --git a/src/vnet/dev/port.c b/src/vnet/dev/port.c index c03a56086af..a2169e9d2ef 100644 --- a/src/vnet/dev/port.c +++ b/src/vnet/dev/port.c @@ -280,6 +280,9 @@ vnet_dev_port_add (vlib_main_t *vm, vnet_dev_t *dev, vnet_dev_port_id_t id, 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); @@ -356,6 +359,11 @@ vnet_dev_port_cfg_change_req_validate (vlib_main_t *vm, vnet_dev_port_t *port, 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; } @@ -472,6 +480,10 @@ vnet_dev_port_cfg_change (vlib_main_t *vm, vnet_dev_port_t *port, } break; + case VNET_DEV_PORT_CFG_SET_RSS_KEY: + port->rss_key = req->rss_key; + break; + default: break; } diff --git a/src/vnet/dev/types.h b/src/vnet/dev/types.h index 0562b3a49e8..443d595bda0 100644 --- a/src/vnet/dev/types.h +++ b/src/vnet/dev/types.h @@ -17,6 +17,11 @@ typedef struct vnet_dev vnet_dev_t; 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 {