summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorChenmin Sun <chenmin.sun@intel.com>2020-07-06 08:20:39 +0800
committerDamjan Marion <dmarion@me.com>2020-09-09 10:12:06 +0000
commitc4665093cdb0a8122d9640b6f5b3acd627918f32 (patch)
tree08a3babefc4f126dec07740628d094fd24413e36 /src/plugins
parent765008670bec75cab679c4f549c5dac744842887 (diff)
interface: support configuring RSS steering queues
This patch adds the RSS steering queues set interface, and it's implementation in DPDK device: /* Interface to set rss queues of the interface */ typedef clib_error_t *(vnet_interface_rss_queues_set_t) (struct vnet_main_t * vnm, struct vnet_hw_interface_t * hi, clib_bitmap_t *bitmap); This patch also introduces a command line to set the RSS queues: set interface rss queues <interface> <list <queue-list>> To display the rss queues, use "show hardware-interfaces" Below is the example to configure rss queues for interface Gig0: vpp# set interface rss queues Gig0 list 0,2,4-7 vpp# show hardware-interfaces brief Name Idx Link Hardware VirtualFunctionEthernet18/1/0 1 down VirtualFunctionEthernet18/1/0 Link speed: unknown RSS queues: 0 2 4 5 6 7 local0 0 down local0 Link speed: unknown vpp# Users can also configure the rss queues on a dpdk interface in startup.conf: dpdk { dev 0000:18:01.0 { rss-queues 0,2,5-7 } } Type: feature Signed-off-by: Chenmin Sun <chenmin.sun@intel.com> Change-Id: I1835595a1c54016a84eabee9fd62ce137935385d
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/dpdk/device/device.c104
-rw-r--r--src/plugins/dpdk/device/dpdk.h2
-rw-r--r--src/plugins/dpdk/device/init.c82
3 files changed, 154 insertions, 34 deletions
diff --git a/src/plugins/dpdk/device/device.c b/src/plugins/dpdk/device/device.c
index 09a1c2f2fdf..e58dd6f4228 100644
--- a/src/plugins/dpdk/device/device.c
+++ b/src/plugins/dpdk/device/device.c
@@ -584,6 +584,109 @@ done:
return err;
}
+static clib_error_t *
+dpdk_interface_set_rss_queues (struct vnet_main_t *vnm,
+ struct vnet_hw_interface_t *hi,
+ clib_bitmap_t * bitmap)
+{
+ dpdk_main_t *xm = &dpdk_main;
+ u32 hw_if_index = hi->hw_if_index;
+ vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
+ dpdk_device_t *xd = vec_elt_at_index (xm->devices, hw->dev_instance);
+ clib_error_t *err = 0;
+ struct rte_eth_rss_reta_entry64 *reta_conf = NULL;
+ struct rte_eth_dev_info dev_info;
+ u16 *reta = NULL;
+ u16 *valid_queue = NULL;
+ u16 valid_queue_count = 0;
+ uint32_t i, j;
+ uint32_t ret;
+
+ rte_eth_dev_info_get (xd->port_id, &dev_info);
+
+ /* parameter check */
+ if (clib_bitmap_count_set_bits (bitmap) == 0)
+ {
+ err = clib_error_return (0, "must assign at least one valid rss queue");
+ goto done;
+ }
+
+ if (clib_bitmap_count_set_bits (bitmap) > dev_info.nb_rx_queues)
+ {
+ err = clib_error_return (0, "too many rss queues");
+ goto done;
+ }
+
+ /* new RETA */
+ reta = clib_mem_alloc (dev_info.reta_size * sizeof (*reta));
+ if (reta == NULL)
+ {
+ err = clib_error_return (0, "clib_mem_alloc failed");
+ goto done;
+ }
+
+ clib_memset (reta, 0, dev_info.reta_size * sizeof (*reta));
+
+ valid_queue_count = 0;
+ /* *INDENT-OFF* */
+ clib_bitmap_foreach (i, bitmap, ({
+ if (i >= dev_info.nb_rx_queues)
+ {
+ err = clib_error_return (0, "illegal queue number");
+ goto done;
+ }
+ reta[valid_queue_count++] = i;
+ }));
+ /* *INDENT-ON* */
+
+ valid_queue = reta;
+ for (i = valid_queue_count, j = 0; i < dev_info.reta_size; i++, j++)
+ {
+ j = j % valid_queue_count;
+ reta[i] = valid_queue[j];
+ }
+
+ /* update reta table */
+ reta_conf =
+ (struct rte_eth_rss_reta_entry64 *) clib_mem_alloc (dev_info.reta_size /
+ RTE_RETA_GROUP_SIZE *
+ sizeof (*reta_conf));
+ if (reta_conf == NULL)
+ {
+ err = clib_error_return (0, "clib_mem_alloc failed");
+ goto done;
+ }
+
+ clib_memset (reta_conf, 0,
+ dev_info.reta_size / RTE_RETA_GROUP_SIZE *
+ sizeof (*reta_conf));
+
+ for (i = 0; i < dev_info.reta_size; i++)
+ {
+ uint32_t reta_id = i / RTE_RETA_GROUP_SIZE;
+ uint32_t reta_pos = i % RTE_RETA_GROUP_SIZE;
+
+ reta_conf[reta_id].mask = UINT64_MAX;
+ reta_conf[reta_id].reta[reta_pos] = reta[i];
+ }
+
+ ret =
+ rte_eth_dev_rss_reta_update (xd->port_id, reta_conf, dev_info.reta_size);
+ if (ret)
+ {
+ err = clib_error_return (0, "rte_eth_dev_rss_reta_update err %d", ret);
+ goto done;
+ }
+
+done:
+ if (reta)
+ clib_mem_free (reta);
+ if (reta_conf)
+ clib_mem_free (reta_conf);
+
+ return err;
+}
+
/* *INDENT-OFF* */
VNET_DEVICE_CLASS (dpdk_device_class) = {
.name = "dpdk",
@@ -600,6 +703,7 @@ VNET_DEVICE_CLASS (dpdk_device_class) = {
.mac_addr_add_del_function = dpdk_add_del_mac_address,
.format_flow = format_dpdk_flow,
.flow_ops_function = dpdk_flow_ops_fn,
+ .set_rss_queues_function = dpdk_interface_set_rss_queues,
};
/* *INDENT-ON* */
diff --git a/src/plugins/dpdk/device/dpdk.h b/src/plugins/dpdk/device/dpdk.h
index 963bc811ee1..40f9dce0c05 100644
--- a/src/plugins/dpdk/device/dpdk.h
+++ b/src/plugins/dpdk/device/dpdk.h
@@ -260,6 +260,7 @@ typedef struct
clib_bitmap_t * workers;
u8 tso;
u8 *devargs;
+ clib_bitmap_t *rss_queues;
#define DPDK_DEVICE_TSO_DEFAULT 0
#define DPDK_DEVICE_TSO_OFF 1
@@ -373,7 +374,6 @@ typedef struct
void dpdk_device_setup (dpdk_device_t * xd);
void dpdk_device_start (dpdk_device_t * xd);
void dpdk_device_stop (dpdk_device_t * xd);
-
int dpdk_port_state_callback (dpdk_portid_t port_id,
enum rte_eth_event_type type,
void *param, void *ret_param);
diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c
index 9d4aeed6924..81803ab1cb4 100644
--- a/src/plugins/dpdk/device/init.c
+++ b/src/plugins/dpdk/device/init.c
@@ -616,7 +616,6 @@ dpdk_lib_init (dpdk_main_t * dm)
/* assign interface to input thread */
int q;
-
error = ethernet_register_interface
(dm->vnet_main, dpdk_device_class.index, xd->device_index,
/* ethernet address */ addr,
@@ -759,10 +758,20 @@ dpdk_lib_init (dpdk_main_t * dm)
dpdk_device_setup (xd);
+ /* rss queues should be configured after dpdk_device_setup() */
+ if (devconf->rss_queues != NULL)
+ {
+ if (vnet_hw_interface_set_rss_queues
+ (vnet_get_main (), hi, devconf->rss_queues))
+ {
+ clib_warning ("%s: Failed to set rss queues", hi->name);
+ }
+ }
+
if (vec_len (xd->errors))
- dpdk_log_err ("setup failed for device %U. Errors:\n %U",
- format_dpdk_device_name, i,
- format_dpdk_device_errors, xd);
+ dpdk_log_err ("setup failed for device %U. Errors:\n %U",
+ format_dpdk_device_name, i,
+ format_dpdk_device_errors, xd);
/*
* A note on Cisco VIC (PMD_ENIC) and VLAN:
@@ -789,38 +798,39 @@ dpdk_lib_init (dpdk_main_t * dm)
* otherwise in the startup config.
*/
- vlan_off = rte_eth_dev_get_vlan_offload (xd->port_id);
- if (devconf->vlan_strip_offload == DPDK_DEVICE_VLAN_STRIP_ON)
- {
- vlan_off |= ETH_VLAN_STRIP_OFFLOAD;
- if (rte_eth_dev_set_vlan_offload (xd->port_id, vlan_off) >= 0)
- dpdk_log_info ("VLAN strip enabled for interface\n");
- else
- dpdk_log_warn ("VLAN strip cannot be supported by interface\n");
- xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
- }
- else
- {
- if (vlan_off & ETH_VLAN_STRIP_OFFLOAD)
- {
- vlan_off &= ~ETH_VLAN_STRIP_OFFLOAD;
- if (rte_eth_dev_set_vlan_offload (xd->port_id, vlan_off) >= 0)
- dpdk_log_warn ("set VLAN offload failed\n");
- }
- xd->port_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
- }
+ vlan_off = rte_eth_dev_get_vlan_offload (xd->port_id);
+ if (devconf->vlan_strip_offload == DPDK_DEVICE_VLAN_STRIP_ON)
+ {
+ vlan_off |= ETH_VLAN_STRIP_OFFLOAD;
+ if (rte_eth_dev_set_vlan_offload (xd->port_id, vlan_off) >= 0)
+ dpdk_log_info ("VLAN strip enabled for interface\n");
+ else
+ dpdk_log_warn ("VLAN strip cannot be supported by interface\n");
+ xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
+ }
+ else
+ {
+ if (vlan_off & ETH_VLAN_STRIP_OFFLOAD)
+ {
+ vlan_off &= ~ETH_VLAN_STRIP_OFFLOAD;
+ if (rte_eth_dev_set_vlan_offload (xd->port_id, vlan_off) >= 0)
+ dpdk_log_warn ("set VLAN offload failed\n");
+ }
+ xd->port_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
+ }
- if (hi)
- hi->max_packet_bytes = xd->port_conf.rxmode.max_rx_pkt_len
- - sizeof (ethernet_header_t);
- else
- dpdk_log_warn ("hi NULL");
+ if (hi)
+ hi->max_packet_bytes = xd->port_conf.rxmode.max_rx_pkt_len
+ - sizeof (ethernet_header_t);
+ else
+ dpdk_log_warn ("hi NULL");
- if (dm->conf->no_multi_seg)
- mtu = mtu > ETHER_MAX_LEN ? ETHER_MAX_LEN : mtu;
+ if (dm->conf->no_multi_seg)
+ mtu = mtu > ETHER_MAX_LEN ? ETHER_MAX_LEN : mtu;
+
+ rte_eth_dev_set_mtu (xd->port_id, mtu);
+}
- rte_eth_dev_set_mtu (xd->port_id, mtu);
- }
/* *INDENT-ON* */
return 0;
@@ -1094,6 +1104,9 @@ dpdk_device_config (dpdk_config_main_t * conf, vlib_pci_addr_t pci_addr,
}
else if (unformat (input, "devargs %s", &devconf->devargs))
;
+ else if (unformat (input, "rss-queues %U",
+ unformat_bitmap_list, &devconf->rss_queues))
+ ;
else
{
error = clib_error_return (0, "unknown input `%U'",
@@ -1416,6 +1429,9 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
/* copy tso config from default device */
_(devargs)
+ /* copy rss_queues config from default device */
+ _(rss_queues)
+
/* add DPDK EAL whitelist/blacklist entry */
if (num_whitelisted > 0 && devconf->is_blacklisted == 0)
{