* [PATCH 0/8] Validate multiqueue configuration in ethdev
@ 2026-10-16 13:05 David Marchand
2026-10-16 13:05 ` [PATCH 1/8] net/bnxt: remove leftover VMDq code in MAC helpers David Marchand
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: David Marchand @ 2026-10-16 13:05 UTC (permalink / raw)
To: dev; +Cc: thomas
We have various checks in drivers about Rx and Tx multiqueue
configuration.
This series is a followup of the VMDq cleanup, finishing the job with
DCB and RSS, and then rejecting invalid multiqueue configuration (useful
from an ABI point of view).
Some drivers misreported their capabilities.
It is important drivers maintainers review carefully those changes.
--
David Marchand
David Marchand (8):
net/bnxt: remove leftover VMDq code in MAC helpers
drivers/net: fix reported VMDq capability
drivers/net: remove check on VMDq modes
devtools: check VMDq capability
ethdev: check DCB availability
drivers/net: fix reported RSS capability
ethdev: check RSS availability
ethdev: check unknown Rx/Tx multi-queue modes
devtools/check-doc-vs-code.sh | 70 ++++++++++++++++++++++-
doc/guides/nics/features/failsafe.ini | 2 +
doc/guides/nics/features/nbl.ini | 1 +
doc/guides/nics/features/netvsc.ini | 1 +
doc/guides/rel_notes/release_26_11.rst | 14 ++++-
drivers/net/atlantic/atl_ethdev.c | 2 -
drivers/net/bnxt/bnxt_ethdev.c | 65 +++++----------------
drivers/net/bnxt/bnxt_rxq.c | 14 +----
drivers/net/cnxk/cnxk_ethdev.c | 11 ----
drivers/net/cnxk/cnxk_rep_ops.c | 16 +-----
drivers/net/cxgbe/cxgbe_ethdev.c | 1 -
drivers/net/dpaa/dpaa_ethdev.c | 1 -
drivers/net/dpaa2/dpaa2_ethdev.c | 1 -
drivers/net/hns3/hns3_dcb.c | 9 ---
drivers/net/intel/cpfl/cpfl_ethdev.c | 19 +-----
drivers/net/intel/cpfl/cpfl_representor.c | 4 +-
drivers/net/intel/e1000/igb_ethdev.c | 21 +------
drivers/net/intel/e1000/igb_rxtx.c | 39 -------------
drivers/net/intel/e1000/igc_ethdev.c | 19 ------
drivers/net/intel/fm10k/fm10k_ethdev.c | 14 +----
drivers/net/intel/i40e/i40e_ethdev.c | 5 --
drivers/net/intel/idpf/idpf_ethdev.c | 9 +--
drivers/net/intel/ixgbe/ixgbe_ethdev.c | 4 --
drivers/net/mvneta/mvneta_ethdev.c | 7 ---
drivers/net/mvpp2/mrvl_ethdev.c | 7 ---
drivers/net/nbl/nbl_dev/nbl_dev.c | 6 --
drivers/net/nfp/nfp_net_common.c | 15 -----
drivers/net/ngbe/ngbe_ethdev_vf.c | 1 -
drivers/net/octeontx/octeontx_ethdev.c | 11 ----
drivers/net/qede/qede_ethdev.c | 5 --
drivers/net/sfc/sfc_repr.c | 16 +-----
drivers/net/sfc/sfc_rx.c | 21 +------
drivers/net/sfc/sfc_tx.c | 9 ---
drivers/net/thunderx/nicvf_ethdev.c | 12 ----
drivers/net/txgbe/txgbe_ethdev_vf.c | 1 -
drivers/net/virtio/virtio_ethdev.c | 14 -----
drivers/net/xsc/xsc_ethdev.c | 2 +
drivers/net/zxdh/zxdh_ethdev.c | 19 ------
lib/ethdev/rte_ethdev.c | 41 +++++++++++++
39 files changed, 155 insertions(+), 374 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/8] net/bnxt: remove leftover VMDq code in MAC helpers
2026-10-16 13:05 [PATCH 0/8] Validate multiqueue configuration in ethdev David Marchand
@ 2026-10-16 13:05 ` David Marchand
2026-10-16 13:05 ` [PATCH 2/8] drivers/net: fix reported VMDq capability David Marchand
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: David Marchand @ 2026-10-16 13:05 UTC (permalink / raw)
To: dev
Cc: thomas, Kishore Padmanabha, Ajit Khaparde, Keegan Freyhof,
Mohammad Shuab Siddique
The VMDq support removal left dead code in MAC address removal and
filter restore functions.
Remove the VMDq flag checks and pool_mask logic that are no longer needed.
At the same time, remove unneeded reset to 0 of VMDq related field in
the dev_info structure.
Fixes: 582f971526da ("net/bnxt: remove VMDq support")
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
drivers/net/bnxt/bnxt_ethdev.c | 65 +++++++---------------------------
1 file changed, 13 insertions(+), 52 deletions(-)
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 23edd94444..e811651413 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1252,12 +1252,6 @@ static int bnxt_dev_info_get_op(struct rte_eth_dev *eth_dev,
* TODO: default_rxconf, default_txconf, rx_desc_lim, and tx_desc_lim
* need further investigation.
*/
- dev_info->max_vmdq_pools = 0;
- dev_info->vmdq_queue_num = 0;
-
- dev_info->vmdq_pool_base = 0;
- dev_info->vmdq_queue_base = 0;
-
dev_info->rx_seg_capa.max_nseg = BNXT_MAX_BUFFER_SPLIT_SEGS;
dev_info->rx_seg_capa.multi_pools = BNXT_MULTI_POOL_BUF_SPLIT_CAP;
dev_info->rx_seg_capa.offset_allowed = BNXT_BUF_SPLIT_OFFSET_CAP;
@@ -1999,39 +1993,23 @@ static void bnxt_mac_addr_remove_op(struct rte_eth_dev *eth_dev,
uint32_t index)
{
struct bnxt *bp = eth_dev->data->dev_private;
- uint64_t pool_mask;
struct bnxt_vnic_info *vnic;
struct bnxt_filter_info *filter, *temp_filter;
- uint32_t i;
if (is_bnxt_in_error(bp))
return;
- if ((eth_dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) == 0)
- pool_mask = 1;
- else
- pool_mask = eth_dev->data->mac_pool_sel[index];
-
- /*
- * Loop through all VNICs from the specified filter flow pools to
- * remove the corresponding MAC addr filter
- */
- for (i = 0; i < bp->nr_vnics; i++) {
- if (!(pool_mask & (1ULL << i)))
- continue;
-
- vnic = &bp->vnic_info[i];
- filter = STAILQ_FIRST(&vnic->filter);
- while (filter) {
- temp_filter = STAILQ_NEXT(filter, next);
- if (filter->mac_index == index) {
- STAILQ_REMOVE(&vnic->filter, filter,
- bnxt_filter_info, next);
- bnxt_hwrm_clear_l2_filter(bp, filter);
- bnxt_free_filter(bp, filter);
- }
- filter = temp_filter;
+ vnic = &bp->vnic_info[0];
+ filter = STAILQ_FIRST(&vnic->filter);
+ while (filter) {
+ temp_filter = STAILQ_NEXT(filter, next);
+ if (filter->mac_index == index) {
+ STAILQ_REMOVE(&vnic->filter, filter,
+ bnxt_filter_info, next);
+ bnxt_hwrm_clear_l2_filter(bp, filter);
+ bnxt_free_filter(bp, filter);
}
+ filter = temp_filter;
}
}
@@ -4528,10 +4506,7 @@ static int bnxt_restore_mac_filters(struct bnxt *bp)
struct rte_eth_dev *dev = bp->eth_dev;
struct rte_eth_dev_info dev_info;
struct rte_ether_addr *addr;
- uint64_t pool_mask;
- uint32_t pool = 0;
uint32_t i;
- bool vmdq;
int rc;
if (BNXT_VF(bp) && !BNXT_VF_IS_TRUSTED(bp))
@@ -4541,8 +4516,6 @@ static int bnxt_restore_mac_filters(struct bnxt *bp)
if (rc)
return rc;
- vmdq = (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) != 0;
-
/* replay MAC address configuration */
for (i = 1; i < dev_info.max_mac_addrs; i++) {
addr = &dev->data->mac_addrs[i];
@@ -4551,21 +4524,9 @@ static int bnxt_restore_mac_filters(struct bnxt *bp)
if (rte_is_zero_ether_addr(addr))
continue;
- pool = 0;
- if (!vmdq)
- pool_mask = 1;
- else
- pool_mask = dev->data->mac_pool_sel[i];
-
- do {
- if (pool_mask & 1ULL) {
- rc = bnxt_mac_addr_add_op(dev, addr, i, pool);
- if (rc)
- return rc;
- }
- pool_mask >>= 1;
- pool++;
- } while (pool_mask);
+ rc = bnxt_mac_addr_add_op(dev, addr, i, 0);
+ if (rc)
+ return rc;
}
return 0;
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/8] drivers/net: fix reported VMDq capability
2026-10-16 13:05 [PATCH 0/8] Validate multiqueue configuration in ethdev David Marchand
2026-10-16 13:05 ` [PATCH 1/8] net/bnxt: remove leftover VMDq code in MAC helpers David Marchand
@ 2026-10-16 13:05 ` David Marchand
2026-10-16 13:05 ` [PATCH 3/8] drivers/net: remove check on VMDq modes David Marchand
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: David Marchand @ 2026-10-16 13:05 UTC (permalink / raw)
To: dev
Cc: thomas, Gaetan Rivet, Igor Russkikh, Potnuri Bharat Teja,
Hemant Agrawal, Sachin Saxena, Anatoly Burakov,
Vladimir Medvedkin, Jiawen Wu, Zaiyu Wang, Jeff Shaw, Jing Chen,
Shreyansh Jain
Some PF drivers (dpaa, dpaa2) and VF drivers (ixgbe, ngbe, txgbe)
are announcing some VMDq capability though this support is not documented,
and no action is taken if the feature is requested.
fm10k announces capability for VF device, but rejects it at configure
time.
Some driver forces a 0 value when ethdev already clears the whole
dev_info structure.
Fixes: fe3a45fd4104 ("ixgbe: add VMDq support")
Fixes: 7e72cbfa320b ("fm10k: add reta query/update")
Fixes: 799db4568c76 ("net/dpaa: support device info and speed capability")
Fixes: 762b275f20f8 ("net/dpaa2: add missing device info fields")
Fixes: 5dec0169554b ("net/txgbe: support VF get information")
Fixes: 66070ca419c1 ("net/ngbe: add hardware configuration for VF device")
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
doc/guides/nics/features/failsafe.ini | 1 +
drivers/net/atlantic/atl_ethdev.c | 2 --
drivers/net/cxgbe/cxgbe_ethdev.c | 1 -
drivers/net/dpaa/dpaa_ethdev.c | 1 -
drivers/net/dpaa2/dpaa2_ethdev.c | 1 -
drivers/net/intel/fm10k/fm10k_ethdev.c | 9 ++-------
drivers/net/intel/ixgbe/ixgbe_ethdev.c | 4 ----
drivers/net/ngbe/ngbe_ethdev_vf.c | 1 -
drivers/net/txgbe/txgbe_ethdev_vf.c | 1 -
9 files changed, 3 insertions(+), 18 deletions(-)
diff --git a/doc/guides/nics/features/failsafe.ini b/doc/guides/nics/features/failsafe.ini
index c7c696fbbd..09afdc1963 100644
--- a/doc/guides/nics/features/failsafe.ini
+++ b/doc/guides/nics/features/failsafe.ini
@@ -13,6 +13,7 @@ MTU update = Y
Promiscuous mode = Y
Allmulticast mode = Y
Unicast MAC filter = Y
+VMDq = P
Multicast MAC filter = Y
VLAN filter = Y
Flow control = Y
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 24184bdb18..44a65d7557 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -1106,8 +1106,6 @@ atl_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
dev_info->max_vfs = pci_dev->max_vfs;
dev_info->max_hash_mac_addrs = 0;
- dev_info->max_vmdq_pools = 0;
- dev_info->vmdq_queue_num = 0;
dev_info->rx_offload_capa = ATL_RX_OFFLOADS;
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index 82e67eeff1..93554f354c 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -129,7 +129,6 @@ int cxgbe_dev_info_get(struct rte_eth_dev *eth_dev,
device_info->max_mac_addrs = 1;
/* XXX: For now we support one MAC/port */
device_info->max_vfs = adapter->params.arch.vfcount;
- device_info->max_vmdq_pools = 0; /* XXX: For now no support for VMDQ */
device_info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 1aaf97f175..7d45386a9d 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -662,7 +662,6 @@ static int dpaa_eth_dev_info(struct rte_eth_dev *dev,
dev_info->max_mac_addrs = DPAA_MAX_MAC_FILTER;
dev_info->max_hash_mac_addrs = 0;
dev_info->max_vfs = 0;
- dev_info->max_vmdq_pools = RTE_ETH_16_POOLS;
dev_info->flow_type_rss_offloads = DPAA_RSS_OFFLOAD_ALL;
if (fif->mac_type == fman_mac_1g) {
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 8ae4fd89c5..07e89d5c39 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -452,7 +452,6 @@ dpaa2_dev_info_get(struct rte_eth_dev *dev,
dev_info->max_hash_mac_addrs = 0;
dev_info->max_vfs = 0;
- dev_info->max_vmdq_pools = RTE_ETH_16_POOLS;
dev_info->flow_type_rss_offloads = DPAA2_RSS_OFFLOAD_ALL;
/* DPAA2 has no software-visible indirection table: incoming packets are
* dispatched to FQs via 'queue_id = hash % dist_size'. We expose the
diff --git a/drivers/net/intel/fm10k/fm10k_ethdev.c b/drivers/net/intel/fm10k/fm10k_ethdev.c
index 3b2daba79e..9b123c0b2c 100644
--- a/drivers/net/intel/fm10k/fm10k_ethdev.c
+++ b/drivers/net/intel/fm10k/fm10k_ethdev.c
@@ -411,7 +411,6 @@ static int
fm10k_check_mq_mode(struct rte_eth_dev *dev)
{
enum rte_eth_rx_mq_mode rx_mq_mode = dev->data->dev_conf.rxmode.mq_mode;
- struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct rte_eth_vmdq_rx_conf *vmdq_conf;
uint16_t nb_rx_q = dev->data->nb_rx_queues;
@@ -425,11 +424,6 @@ fm10k_check_mq_mode(struct rte_eth_dev *dev)
if (!(rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG))
return 0;
- if (hw->mac.type == fm10k_mac_vf) {
- PMD_INIT_LOG(ERR, "VMDQ mode is not supported in VF.");
- return -EINVAL;
- }
-
/* Check VMDQ queue pool number */
if (vmdq_conf->nb_queue_pools >
sizeof(vmdq_conf->pool_map[0].pools) * CHAR_BIT ||
@@ -1386,7 +1380,8 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
dev_info->max_vfs = pdev->max_vfs;
dev_info->vmdq_pool_base = 0;
dev_info->vmdq_queue_base = 0;
- dev_info->max_vmdq_pools = RTE_ETH_32_POOLS;
+ if (hw->mac.type != fm10k_mac_vf)
+ dev_info->max_vmdq_pools = RTE_ETH_32_POOLS;
dev_info->vmdq_queue_num = FM10K_MAX_QUEUES_PF;
dev_info->rx_queue_offload_capa = fm10k_get_rx_queue_offloads_capa(dev);
dev_info->rx_offload_capa = fm10k_get_rx_port_offloads_capa(dev) |
diff --git a/drivers/net/intel/ixgbe/ixgbe_ethdev.c b/drivers/net/intel/ixgbe/ixgbe_ethdev.c
index 44eb932058..50e44484b1 100644
--- a/drivers/net/intel/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/intel/ixgbe/ixgbe_ethdev.c
@@ -4076,10 +4076,6 @@ ixgbevf_dev_info_get(struct rte_eth_dev *dev,
dev_info->max_mac_addrs = hw->mac.num_rar_entries;
dev_info->max_hash_mac_addrs = IXGBE_VMDQ_NUM_UC_MAC;
dev_info->max_vfs = pci_dev->max_vfs;
- if (hw->mac.type == ixgbe_mac_82598EB)
- dev_info->max_vmdq_pools = RTE_ETH_16_POOLS;
- else
- dev_info->max_vmdq_pools = RTE_ETH_64_POOLS;
dev_info->rx_queue_offload_capa = ixgbe_get_rx_queue_offloads(dev);
dev_info->rx_offload_capa = (ixgbe_get_rx_port_offloads(dev) |
dev_info->rx_queue_offload_capa);
diff --git a/drivers/net/ngbe/ngbe_ethdev_vf.c b/drivers/net/ngbe/ngbe_ethdev_vf.c
index c440e02369..55cbffaf2c 100644
--- a/drivers/net/ngbe/ngbe_ethdev_vf.c
+++ b/drivers/net/ngbe/ngbe_ethdev_vf.c
@@ -475,7 +475,6 @@ ngbevf_dev_info_get(struct rte_eth_dev *dev,
dev_info->max_mac_addrs = hw->mac.num_rar_entries;
dev_info->max_hash_mac_addrs = NGBE_VMDQ_NUM_UC_MAC;
dev_info->max_vfs = pci_dev->max_vfs;
- dev_info->max_vmdq_pools = RTE_ETH_64_POOLS;
dev_info->rx_queue_offload_capa = ngbe_get_rx_queue_offloads(dev);
dev_info->rx_offload_capa = (ngbe_get_rx_port_offloads(dev) |
dev_info->rx_queue_offload_capa);
diff --git a/drivers/net/txgbe/txgbe_ethdev_vf.c b/drivers/net/txgbe/txgbe_ethdev_vf.c
index 341f62bc75..3cf33a8bd6 100644
--- a/drivers/net/txgbe/txgbe_ethdev_vf.c
+++ b/drivers/net/txgbe/txgbe_ethdev_vf.c
@@ -575,7 +575,6 @@ txgbevf_dev_info_get(struct rte_eth_dev *dev,
dev_info->max_mac_addrs = hw->mac.num_rar_entries;
dev_info->max_hash_mac_addrs = TXGBE_VMDQ_NUM_UC_MAC;
dev_info->max_vfs = pci_dev->max_vfs;
- dev_info->max_vmdq_pools = RTE_ETH_64_POOLS;
dev_info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
dev_info->rx_queue_offload_capa = txgbe_get_rx_queue_offloads(dev);
dev_info->rx_offload_capa = (txgbe_get_rx_port_offloads(dev) |
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/8] drivers/net: remove check on VMDq modes
2026-10-16 13:05 [PATCH 0/8] Validate multiqueue configuration in ethdev David Marchand
2026-10-16 13:05 ` [PATCH 1/8] net/bnxt: remove leftover VMDq code in MAC helpers David Marchand
2026-10-16 13:05 ` [PATCH 2/8] drivers/net: fix reported VMDq capability David Marchand
@ 2026-10-16 13:05 ` David Marchand
2026-10-16 13:05 ` [PATCH 4/8] devtools: check VMDq capability David Marchand
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: David Marchand @ 2026-10-16 13:05 UTC (permalink / raw)
To: dev; +Cc: thomas, Xingui Yang, Chengwen Feng, Bruce Richardson
ethdev now validates requests for VMDq Rx and Tx modes.
No need to validate again in the driver.
Note:
- for igb, max_vmdq_pools is already 0 for models that do not support
VMDq, so checking the VMDq modes is unneeded,
- for i40e, the FW flag was already checked to populate max_vmdq_pools,
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
drivers/net/hns3/hns3_dcb.c | 9 -------
drivers/net/intel/e1000/igb_rxtx.c | 39 ----------------------------
drivers/net/intel/i40e/i40e_ethdev.c | 5 ----
3 files changed, 53 deletions(-)
diff --git a/drivers/net/hns3/hns3_dcb.c b/drivers/net/hns3/hns3_dcb.c
index 6d2945d9c5..e7912aebb2 100644
--- a/drivers/net/hns3/hns3_dcb.c
+++ b/drivers/net/hns3/hns3_dcb.c
@@ -1840,7 +1840,6 @@ int
hns3_check_dev_mq_mode(struct rte_eth_dev *dev)
{
enum rte_eth_rx_mq_mode rx_mq_mode = dev->data->dev_conf.rxmode.mq_mode;
- enum rte_eth_tx_mq_mode tx_mq_mode = dev->data->dev_conf.txmode.mq_mode;
struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
struct rte_eth_dcb_rx_conf *dcb_rx_conf;
@@ -1849,14 +1848,6 @@ hns3_check_dev_mq_mode(struct rte_eth_dev *dev)
int max_tc = 0;
int i;
- if (((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) ||
- (tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_DCB ||
- tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_ONLY)) {
- hns3_err(hw, "VMDQ is not supported, rx_mq_mode = %d, tx_mq_mode = %d.",
- rx_mq_mode, tx_mq_mode);
- return -EOPNOTSUPP;
- }
-
dcb_rx_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
dcb_tx_conf = &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
if ((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
diff --git a/drivers/net/intel/e1000/igb_rxtx.c b/drivers/net/intel/e1000/igb_rxtx.c
index 4fda5d57a0..ef531f1cd4 100644
--- a/drivers/net/intel/e1000/igb_rxtx.c
+++ b/drivers/net/intel/e1000/igb_rxtx.c
@@ -2113,41 +2113,6 @@ igb_rss_configure(struct rte_eth_dev *dev)
igb_hw_rss_hash_set(hw, &rss_conf);
}
-/*
- * Check if the mac type support VMDq or not.
- * Return 1 if it supports, otherwise, return 0.
- */
-static int
-igb_is_vmdq_supported(const struct rte_eth_dev *dev)
-{
- const struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
- switch (hw->mac.type) {
- case e1000_82576:
- case e1000_82580:
- case e1000_i350:
- return 1;
- case e1000_82540:
- case e1000_82541:
- case e1000_82542:
- case e1000_82543:
- case e1000_82544:
- case e1000_82545:
- case e1000_82546:
- case e1000_82547:
- case e1000_82571:
- case e1000_82572:
- case e1000_82573:
- case e1000_82574:
- case e1000_82583:
- case e1000_i210:
- case e1000_i211:
- default:
- PMD_INIT_LOG(ERR, "Cannot support VMDq feature");
- return 0;
- }
-}
-
static int
igb_vmdq_rx_hw_configure(struct rte_eth_dev *dev)
{
@@ -2161,10 +2126,6 @@ igb_vmdq_rx_hw_configure(struct rte_eth_dev *dev)
hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
cfg = &dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf;
- /* Check if mac type can support VMDq, return value of 0 means NOT support */
- if (igb_is_vmdq_supported(dev) == 0)
- return -1;
-
igb_rss_disable(dev);
/* RCTL: enable VLAN filter */
diff --git a/drivers/net/intel/i40e/i40e_ethdev.c b/drivers/net/intel/i40e/i40e_ethdev.c
index 41d5586403..2405d9e119 100644
--- a/drivers/net/intel/i40e/i40e_ethdev.c
+++ b/drivers/net/intel/i40e/i40e_ethdev.c
@@ -6655,11 +6655,6 @@ i40e_vmdq_setup(struct rte_eth_dev *dev)
*/
i40e_pf_disable_irq0(hw);
- if ((pf->flags & I40E_FLAG_VMDQ) == 0) {
- PMD_INIT_LOG(ERR, "FW doesn't support VMDQ");
- return -ENOTSUP;
- }
-
conf_vsis = conf->rx_adv_conf.vmdq_rx_conf.nb_queue_pools;
if (conf_vsis > pf->max_nb_vmdq_vsi) {
PMD_INIT_LOG(ERR, "VMDQ config: %u, max support:%u",
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/8] devtools: check VMDq capability
2026-10-16 13:05 [PATCH 0/8] Validate multiqueue configuration in ethdev David Marchand
` (2 preceding siblings ...)
2026-10-16 13:05 ` [PATCH 3/8] drivers/net: remove check on VMDq modes David Marchand
@ 2026-10-16 13:05 ` David Marchand
2026-10-16 13:05 ` [PATCH 5/8] ethdev: check DCB availability David Marchand
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: David Marchand @ 2026-10-16 13:05 UTC (permalink / raw)
To: dev; +Cc: thomas
Let's check that the code and the documentation are aligned for VMDq
capability.
Note: some driver directory hosts multiple drivers that have multiple
corresponding entry in doc/guides/features/. For this case, only try to
detect a discrepancy if all docs agree.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
devtools/check-doc-vs-code.sh | 46 ++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/devtools/check-doc-vs-code.sh b/devtools/check-doc-vs-code.sh
index c58c239c87..7936f8b69f 100755
--- a/devtools/check-doc-vs-code.sh
+++ b/devtools/check-doc-vs-code.sh
@@ -28,7 +28,7 @@ changed_files()
has_code_change() # <pattern>
{
- test -n "$(git log --format='%h' -S"$1" $trusted_commit..)"
+ test -n "$(git log --format='%h' -G"$1" $trusted_commit..)"
}
has_file_change() # <pattern>
@@ -53,6 +53,43 @@ all_net_drivers()
sort
}
+has_doc_feature() # <ini_file> <feature>
+{
+ grep -q "^$2[[:space:]]*=[[:space:]]*[YP]" "$1"
+}
+
+all_docs_agree() # <driver> <feature>
+{
+ first=""
+ for d in "$rootdir/doc/guides/nics/features/${1}"*.ini; do
+ [ -f "$d" ] || return 1
+ has_doc_feature "$d" "$2" && val=true || val=false
+ [ -n "$first" ] || first=$val
+ [ "$first" = "$val" ] || return 1
+ done
+ return 0
+}
+
+check_mq_caps() # <driver>
+{
+ code=$rootdir/drivers/net/$1
+ doc=$rootdir/doc/guides/nics/features/$1.ini
+ [ -d $code ] || return 0
+ [ -f $doc ] || return 0
+
+ if all_docs_agree $1 "VMDq"; then
+ if has_doc_feature "$doc" "VMDq"; then
+ git grep -qE 'max_vmdq_pools[[:space:]]*=' -- "$code" ||
+ error "VMDq documented but max_vmdq_pools not set for $1"
+ else
+ ! git grep -qE 'max_vmdq_pools[[:space:]]*=' -- "$code" ||
+ error "max_vmdq_pools set but VMDq not documented for $1"
+ ! git grep -qE 'RTE_ETH_MQ_(RX|TX).*VMDQ' -- "$code" ||
+ error "VMDq mq_mode referenced but VMDq not documented for $1"
+ fi
+ fi
+}
+
check_rte_flow() # <driver>
{
code=$rootdir/drivers/net/$1
@@ -70,6 +107,7 @@ if [ -z "$trusted_commit" ]; then
# check all
for driver in $(all_net_drivers); do
check_rte_flow $driver
+ check_mq_caps $driver
done
exit $result
fi
@@ -81,4 +119,10 @@ if has_code_change 'RTE_FLOW_.*_TYPE_' ||
check_rte_flow $driver
done
fi
+if has_code_change 'max_vmdq_pools\|RTE_ETH_MQ_.*VMDQ' ||
+ has_file_change 'doc/guides/nics/features'; then
+ for driver in $(changed_net_drivers); do
+ check_mq_caps $driver
+ done
+fi
exit $result
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/8] ethdev: check DCB availability
2026-10-16 13:05 [PATCH 0/8] Validate multiqueue configuration in ethdev David Marchand
` (3 preceding siblings ...)
2026-10-16 13:05 ` [PATCH 4/8] devtools: check VMDq capability David Marchand
@ 2026-10-16 13:05 ` David Marchand
2026-10-16 13:05 ` [PATCH 6/8] drivers/net: fix reported RSS capability David Marchand
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: David Marchand @ 2026-10-16 13:05 UTC (permalink / raw)
To: dev; +Cc: thomas, Andrew Rybchenko
Add DCB capability check in rte_eth_dev_configure() using
dev->dev_ops->get_dcb_info.
When NULL, reject Rx modes with RTE_ETH_MQ_RX_DCB_FLAG and
Tx modes RTE_ETH_MQ_TX_DCB and RTE_ETH_MQ_TX_VMDQ_DCB.
Remove redundant DCB checks from drivers.
Check that documentation is aligned with driver code.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
devtools/check-doc-vs-code.sh | 14 +++++++++++++-
doc/guides/rel_notes/release_26_11.rst | 11 ++++++++---
drivers/net/intel/e1000/igb_ethdev.c | 6 ------
drivers/net/intel/fm10k/fm10k_ethdev.c | 5 -----
lib/ethdev/rte_ethdev.c | 16 ++++++++++++++++
5 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/devtools/check-doc-vs-code.sh b/devtools/check-doc-vs-code.sh
index 7936f8b69f..81c9713f5a 100755
--- a/devtools/check-doc-vs-code.sh
+++ b/devtools/check-doc-vs-code.sh
@@ -77,6 +77,18 @@ check_mq_caps() # <driver>
[ -d $code ] || return 0
[ -f $doc ] || return 0
+ if all_docs_agree $1 "DCB"; then
+ if has_doc_feature "$doc" "DCB"; then
+ git grep -q '\.get_dcb_info[[:space:]]*=' -- "$code" ||
+ error "DCB documented but no get_dcb_info callback for $1"
+ else
+ ! git grep -q '\.get_dcb_info[[:space:]]*=' -- "$code" ||
+ error "get_dcb_info callback but DCB not documented for $1"
+ ! git grep -qE 'RTE_ETH_MQ_(RX|TX).*DCB' -- "$code" ||
+ error "DCB mq_mode referenced but DCB not documented for $1"
+ fi
+ fi
+
if all_docs_agree $1 "VMDq"; then
if has_doc_feature "$doc" "VMDq"; then
git grep -qE 'max_vmdq_pools[[:space:]]*=' -- "$code" ||
@@ -119,7 +131,7 @@ if has_code_change 'RTE_FLOW_.*_TYPE_' ||
check_rte_flow $driver
done
fi
-if has_code_change 'max_vmdq_pools\|RTE_ETH_MQ_.*VMDQ' ||
+if has_code_change 'get_dcb_info\|max_vmdq_pools\|RTE_ETH_MQ_.*DCB\|RTE_ETH_MQ_.*VMDQ' ||
has_file_change 'doc/guides/nics/features'; then
for driver in $(changed_net_drivers); do
check_mq_caps $driver
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index be758a0c02..9341769c32 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -424,11 +424,16 @@ API Changes
* Removed the ``unused`` field.
* Changed the ``objs`` array from fixed size to variable size.
+* ethdev: Updated multi-queue mode validation at port configuration time:
+
+ * DCB modes (Rx ``RTE_ETH_MQ_RX_DCB_FLAG``, Tx ``RTE_ETH_MQ_TX_DCB``/``RTE_ETH_MQ_TX_VMDQ_DCB``)
+ are rejected if the driver has no ``get_dcb_info`` callback.
+ * VMDq modes (Rx ``RTE_ETH_MQ_RX_VMDQ_FLAG``,
+ Tx ``RTE_ETH_MQ_TX_VMDQ_DCB``/``RTE_ETH_MQ_TX_VMDQ_ONLY``) are rejected
+ if the driver reports no VMDq pool.
+
* ethdev: Updated VMDq related API.
- * At port configuration time, the number of VMDq pools advertised by a driver
- is now used to validate VMDq related Rx and Tx modes
- (``RTE_ETH_MQ_RX_VMDQ_FLAG``, ``RTE_ETH_MQ_TX_VMDQ_DCB``, ``RTE_ETH_MQ_TX_VMDQ_ONLY``).
* A check was added in ``rte_eth_dev_mac_addr_add`` to validate that
the ``pool`` parameter is 0 when VMDq is not configured.
* The ``RTE_ETH_NUM_RECEIVE_MAC_ADDR`` and ``RTE_ETH_VMDQ_NUM_UC_HASH_ARRAY`` macros
diff --git a/drivers/net/intel/e1000/igb_ethdev.c b/drivers/net/intel/e1000/igb_ethdev.c
index 524c030be6..181af58169 100644
--- a/drivers/net/intel/e1000/igb_ethdev.c
+++ b/drivers/net/intel/e1000/igb_ethdev.c
@@ -1144,12 +1144,6 @@ igb_check_mq_mode(struct rte_eth_dev *dev)
uint16_t nb_rx_q = dev->data->nb_rx_queues;
uint16_t nb_tx_q = dev->data->nb_tx_queues;
- if ((rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) ||
- tx_mq_mode == RTE_ETH_MQ_TX_DCB ||
- tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_DCB) {
- PMD_INIT_LOG(ERR, "DCB mode is not supported.");
- return -EINVAL;
- }
if (RTE_ETH_DEV_SRIOV(dev).active != 0) {
/* Check multi-queue mode.
* To no break software we accept RTE_ETH_MQ_RX_NONE as this might
diff --git a/drivers/net/intel/fm10k/fm10k_ethdev.c b/drivers/net/intel/fm10k/fm10k_ethdev.c
index 9b123c0b2c..5aa15a8dba 100644
--- a/drivers/net/intel/fm10k/fm10k_ethdev.c
+++ b/drivers/net/intel/fm10k/fm10k_ethdev.c
@@ -416,11 +416,6 @@ fm10k_check_mq_mode(struct rte_eth_dev *dev)
vmdq_conf = &dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf;
- if (rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
- PMD_INIT_LOG(ERR, "DCB mode is not supported.");
- return -EINVAL;
- }
-
if (!(rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG))
return 0;
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index f843e8808a..39a895c9e4 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -1573,6 +1573,22 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
goto rollback;
}
+ if (dev->dev_ops->get_dcb_info == NULL) {
+ if ((dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) != 0) {
+ RTE_ETHDEV_LOG_LINE(ERR, "Ethdev port_id=%u does not support DCB rx mode",
+ port_id);
+ ret = -EINVAL;
+ goto rollback;
+ }
+ if (dev_conf->txmode.mq_mode == RTE_ETH_MQ_TX_DCB ||
+ dev_conf->txmode.mq_mode == RTE_ETH_MQ_TX_VMDQ_DCB) {
+ RTE_ETHDEV_LOG_LINE(ERR, "Ethdev port_id=%u does not support DCB tx mode",
+ port_id);
+ ret = -EINVAL;
+ goto rollback;
+ }
+ }
+
if (dev_info.max_vmdq_pools == 0) {
if ((dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) != 0) {
RTE_ETHDEV_LOG_LINE(ERR, "Ethdev port_id=%u does not support VMDq rx mode",
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 6/8] drivers/net: fix reported RSS capability
2026-10-16 13:05 [PATCH 0/8] Validate multiqueue configuration in ethdev David Marchand
` (4 preceding siblings ...)
2026-10-16 13:05 ` [PATCH 5/8] ethdev: check DCB availability David Marchand
@ 2026-10-16 13:05 ` David Marchand
2026-10-16 13:05 ` [PATCH 7/8] ethdev: check RSS availability David Marchand
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: David Marchand @ 2026-10-16 13:05 UTC (permalink / raw)
To: dev
Cc: thomas, Gaetan Rivet, Dimon Zhao, Leon Yu, Sam Chen, Wei Hu,
Praveen Shetty, Jingjing Wu, Renyong Wan, Na Na, Rong Qian,
Xiaoxiong Zhang, Dongwei Xu, Beilei Xing, Xiaoyun Li, Junfeng Guo,
Mingxia Liu
Some drivers (idpf, cpfl) report RSS support even if lacking HW support.
On the other hand, some driver do have support but do not advertise it
(either in dev_info, or in the documentation).
Fixes: 70675bcc3a57 ("net/idpf: support RSS")
Fixes: cfbc66551a14 ("net/cpfl: support RSS")
Fixes: 5fb899f4b225 ("net/xsc: support RSS configuration")
Fixes: ff8db3711b29 ("net/nbl: support infos query")
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
doc/guides/nics/features/failsafe.ini | 1 +
doc/guides/nics/features/nbl.ini | 1 +
doc/guides/nics/features/netvsc.ini | 1 +
drivers/net/intel/cpfl/cpfl_ethdev.c | 3 ++-
drivers/net/intel/cpfl/cpfl_representor.c | 4 +++-
drivers/net/intel/idpf/idpf_ethdev.c | 3 ++-
drivers/net/xsc/xsc_ethdev.c | 2 ++
7 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/doc/guides/nics/features/failsafe.ini b/doc/guides/nics/features/failsafe.ini
index 09afdc1963..b778a40be6 100644
--- a/doc/guides/nics/features/failsafe.ini
+++ b/doc/guides/nics/features/failsafe.ini
@@ -18,6 +18,7 @@ Multicast MAC filter = Y
VLAN filter = Y
Flow control = Y
Packet type parsing = Y
+RSS hash = P
Stats per queue = Y
ARMv7 = Y
ARMv8 = Y
diff --git a/doc/guides/nics/features/nbl.ini b/doc/guides/nics/features/nbl.ini
index 5935092a49..e799840e40 100644
--- a/doc/guides/nics/features/nbl.ini
+++ b/doc/guides/nics/features/nbl.ini
@@ -9,6 +9,7 @@ MTU update = Y
Scattered Rx = Y
Promiscuous mode = Y
Unicast MAC filter = Y
+RSS hash = Y
VLAN offload = P
Extended stats = Y
Stats per queue = Y
diff --git a/doc/guides/nics/features/netvsc.ini b/doc/guides/nics/features/netvsc.ini
index fa8c2ac132..7bc7148f95 100644
--- a/doc/guides/nics/features/netvsc.ini
+++ b/doc/guides/nics/features/netvsc.ini
@@ -8,6 +8,7 @@ Speed capabilities = P
Free Tx mbuf on demand = Y
Scattered Rx = Y
Promiscuous mode = Y
+RSS hash = Y
Allmulticast mode = Y
Stats per queue = Y
Extended stats = Y
diff --git a/drivers/net/intel/cpfl/cpfl_ethdev.c b/drivers/net/intel/cpfl/cpfl_ethdev.c
index 32e0f81d99..0863043a2e 100644
--- a/drivers/net/intel/cpfl/cpfl_ethdev.c
+++ b/drivers/net/intel/cpfl/cpfl_ethdev.c
@@ -212,7 +212,8 @@ cpfl_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
dev_info->hash_key_size = vport->rss_key_size;
dev_info->reta_size = vport->rss_lut_size;
- dev_info->flow_type_rss_offloads = CPFL_RSS_OFFLOAD_ALL;
+ if (base->caps.rss_caps != 0)
+ dev_info->flow_type_rss_offloads = CPFL_RSS_OFFLOAD_ALL;
dev_info->rx_offload_capa =
RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
diff --git a/drivers/net/intel/cpfl/cpfl_representor.c b/drivers/net/intel/cpfl/cpfl_representor.c
index 60b72b5ec1..bb28c0b989 100644
--- a/drivers/net/intel/cpfl/cpfl_representor.c
+++ b/drivers/net/intel/cpfl/cpfl_representor.c
@@ -195,6 +195,7 @@ cpfl_repr_dev_info_get(struct rte_eth_dev *ethdev,
struct rte_eth_dev_info *dev_info)
{
struct cpfl_repr *repr = CPFL_DEV_TO_REPR(ethdev);
+ struct cpfl_adapter_ext *adapter = repr->itf.adapter;
dev_info->device = ethdev->device;
dev_info->max_mac_addrs = 1;
@@ -203,7 +204,8 @@ cpfl_repr_dev_info_get(struct rte_eth_dev *ethdev,
dev_info->min_rx_bufsize = CPFL_MIN_BUF_SIZE;
dev_info->max_rx_pktlen = CPFL_MAX_FRAME_SIZE;
- dev_info->flow_type_rss_offloads = CPFL_RSS_OFFLOAD_ALL;
+ if (adapter->base.caps.rss_caps != 0)
+ dev_info->flow_type_rss_offloads = CPFL_RSS_OFFLOAD_ALL;
dev_info->rx_offload_capa =
RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
diff --git a/drivers/net/intel/idpf/idpf_ethdev.c b/drivers/net/intel/idpf/idpf_ethdev.c
index e9e9781fdd..5a8c783013 100644
--- a/drivers/net/intel/idpf/idpf_ethdev.c
+++ b/drivers/net/intel/idpf/idpf_ethdev.c
@@ -169,7 +169,8 @@ idpf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
dev_info->hash_key_size = vport->rss_key_size;
dev_info->reta_size = vport->rss_lut_size;
- dev_info->flow_type_rss_offloads = IDPF_RSS_OFFLOAD_ALL;
+ if (adapter->caps.rss_caps != 0)
+ dev_info->flow_type_rss_offloads = IDPF_RSS_OFFLOAD_ALL;
dev_info->rx_offload_capa =
RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index 5fbe68782e..8ac7fecd3a 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -469,6 +469,8 @@ xsc_ethdev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
info->if_index = priv->ifindex;
info->speed_capa = priv->xdev->link_speed_capa;
info->hash_key_size = XSC_RSS_HASH_KEY_LEN;
+ info->flow_type_rss_offloads = RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP |
+ RTE_ETH_RSS_TCP;
info->tx_desc_lim.nb_seg_max = 8;
info->tx_desc_lim.nb_mtu_seg_max = 8;
info->switch_info.name = dev->data->name;
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 7/8] ethdev: check RSS availability
2026-10-16 13:05 [PATCH 0/8] Validate multiqueue configuration in ethdev David Marchand
` (5 preceding siblings ...)
2026-10-16 13:05 ` [PATCH 6/8] drivers/net: fix reported RSS capability David Marchand
@ 2026-10-16 13:05 ` David Marchand
2026-10-16 13:05 ` [PATCH 8/8] ethdev: check unknown Rx/Tx multi-queue modes David Marchand
2026-10-16 16:44 ` [PATCH 0/8] Validate multiqueue configuration in ethdev Stephen Hemminger
8 siblings, 0 replies; 10+ messages in thread
From: David Marchand @ 2026-10-16 13:05 UTC (permalink / raw)
To: dev; +Cc: thomas, Praveen Shetty, Harman Kalra, Andrew Rybchenko
Add RSS capability check in rte_eth_dev_configure() using
dev_info.flow_type_rss_offloads.
When zero, reject Rx modes with RTE_ETH_MQ_RX_RSS_FLAG.
Remove redundant RSS checks from drivers.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
devtools/check-doc-vs-code.sh | 14 +++++++++++++-
doc/guides/rel_notes/release_26_11.rst | 2 ++
drivers/net/intel/cpfl/cpfl_ethdev.c | 3 ---
drivers/net/nfp/nfp_net_common.c | 7 -------
drivers/net/octeontx/octeontx_ethdev.c | 3 +--
drivers/net/sfc/sfc_rx.c | 9 +--------
lib/ethdev/rte_ethdev.c | 8 ++++++++
7 files changed, 25 insertions(+), 21 deletions(-)
diff --git a/devtools/check-doc-vs-code.sh b/devtools/check-doc-vs-code.sh
index 81c9713f5a..da8398bfa4 100755
--- a/devtools/check-doc-vs-code.sh
+++ b/devtools/check-doc-vs-code.sh
@@ -89,6 +89,18 @@ check_mq_caps() # <driver>
fi
fi
+ if all_docs_agree $1 "RSS hash"; then
+ if has_doc_feature "$doc" "RSS hash"; then
+ git grep -qE 'flow_type_rss_offloads[[:space:]]*\|?=' -- "$code" ||
+ error "RSS documented but flow_type_rss_offloads not set for $1"
+ else
+ ! git grep -qE 'flow_type_rss_offloads[[:space:]]*\|?=' -- "$code" ||
+ error "flow_type_rss_offloads set but RSS not documented for $1"
+ ! git grep -qE 'RTE_ETH_MQ_RX.*RSS' -- "$code" ||
+ error "RSS mq_mode referenced but RSS not documented for $1"
+ fi
+ fi
+
if all_docs_agree $1 "VMDq"; then
if has_doc_feature "$doc" "VMDq"; then
git grep -qE 'max_vmdq_pools[[:space:]]*=' -- "$code" ||
@@ -131,7 +143,7 @@ if has_code_change 'RTE_FLOW_.*_TYPE_' ||
check_rte_flow $driver
done
fi
-if has_code_change 'get_dcb_info\|max_vmdq_pools\|RTE_ETH_MQ_.*DCB\|RTE_ETH_MQ_.*VMDQ' ||
+if has_code_change 'get_dcb_info\|flow_type_rss_offloads\|max_vmdq_pools\|RTE_ETH_MQ_' ||
has_file_change 'doc/guides/nics/features'; then
for driver in $(changed_net_drivers); do
check_mq_caps $driver
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 9341769c32..caffd2a611 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -428,6 +428,8 @@ API Changes
* DCB modes (Rx ``RTE_ETH_MQ_RX_DCB_FLAG``, Tx ``RTE_ETH_MQ_TX_DCB``/``RTE_ETH_MQ_TX_VMDQ_DCB``)
are rejected if the driver has no ``get_dcb_info`` callback.
+ * RSS mode (Rx ``RTE_ETH_MQ_RX_RSS_FLAG``) is rejected if the driver reports no
+ ``flow_type_rss_offloads``.
* VMDq modes (Rx ``RTE_ETH_MQ_RX_VMDQ_FLAG``,
Tx ``RTE_ETH_MQ_TX_VMDQ_DCB``/``RTE_ETH_MQ_TX_VMDQ_ONLY``) are rejected
if the driver reports no VMDq pool.
diff --git a/drivers/net/intel/cpfl/cpfl_ethdev.c b/drivers/net/intel/cpfl/cpfl_ethdev.c
index 0863043a2e..f425181bf2 100644
--- a/drivers/net/intel/cpfl/cpfl_ethdev.c
+++ b/drivers/net/intel/cpfl/cpfl_ethdev.c
@@ -752,9 +752,6 @@ cpfl_dev_configure(struct rte_eth_dev *dev)
PMD_INIT_LOG(ERR, "Failed to init rss");
return ret;
}
- } else if (conf->rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) {
- PMD_INIT_LOG(ERR, "RSS is not supported.");
- return -ENOTSUP;
}
vport->max_pkt_len =
diff --git a/drivers/net/nfp/nfp_net_common.c b/drivers/net/nfp/nfp_net_common.c
index afa0bc0faf..f9957086d2 100644
--- a/drivers/net/nfp/nfp_net_common.c
+++ b/drivers/net/nfp/nfp_net_common.c
@@ -373,13 +373,6 @@ nfp_net_configure(struct rte_eth_dev *dev)
return -EINVAL;
}
- /* Checking RX mode */
- if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0 &&
- (hw->super.cap & NFP_NET_CFG_CTRL_RSS_ANY) == 0) {
- PMD_DRV_LOG(ERR, "RSS not supported.");
- return -EINVAL;
- }
-
/* Checking MTU set */
if (rxmode->mtu > hw->max_mtu + NFP_ETH_OVERHEAD) {
PMD_DRV_LOG(ERR, "MTU (%u) larger than the maximum possible frame size (%u).",
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index e173535d29..e0df23049c 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -499,8 +499,7 @@ octeontx_dev_configure(struct rte_eth_dev *dev)
return -EINVAL;
}
- if (rxmode->mq_mode != RTE_ETH_MQ_RX_NONE &&
- rxmode->mq_mode != RTE_ETH_MQ_RX_RSS) {
+ if (rxmode->mq_mode != RTE_ETH_MQ_RX_NONE) {
octeontx_log_err("unsupported rx qmode %d", rxmode->mq_mode);
return -EINVAL;
}
diff --git a/drivers/net/sfc/sfc_rx.c b/drivers/net/sfc/sfc_rx.c
index 1d4101b9e9..aa59931f06 100644
--- a/drivers/net/sfc/sfc_rx.c
+++ b/drivers/net/sfc/sfc_rx.c
@@ -1668,21 +1668,14 @@ sfc_rx_qinit_info(struct sfc_adapter *sa, sfc_sw_index_t sw_index,
static int
sfc_rx_check_mode(struct sfc_adapter *sa, struct rte_eth_rxmode *rxmode)
{
- struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
uint64_t offloads_supported = sfc_rx_get_dev_offload_caps(sa) |
sfc_rx_get_queue_offload_caps(sa);
- struct sfc_rss *rss = &sas->rss;
int rc = 0;
switch (rxmode->mq_mode) {
case RTE_ETH_MQ_RX_NONE:
- /* No special checks are required */
- break;
case RTE_ETH_MQ_RX_RSS:
- if (rss->context_type == EFX_RX_SCALE_UNAVAILABLE) {
- sfc_err(sa, "RSS is not available");
- rc = EINVAL;
- }
+ /* No special checks are required */
break;
default:
sfc_err(sa, "Rx multi-queue mode %u not supported",
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index 39a895c9e4..44b20697ae 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -1526,6 +1526,14 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
goto rollback;
}
+ if (dev_info.flow_type_rss_offloads == 0 &&
+ (dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0) {
+ RTE_ETHDEV_LOG_LINE(ERR, "Ethdev port_id=%u does not support RSS rx mode",
+ port_id);
+ ret = -EINVAL;
+ goto rollback;
+ }
+
dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf =
rte_eth_rss_hf_refine(dev_conf->rx_adv_conf.rss_conf.rss_hf);
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 8/8] ethdev: check unknown Rx/Tx multi-queue modes
2026-10-16 13:05 [PATCH 0/8] Validate multiqueue configuration in ethdev David Marchand
` (6 preceding siblings ...)
2026-10-16 13:05 ` [PATCH 7/8] ethdev: check RSS availability David Marchand
@ 2026-10-16 13:05 ` David Marchand
2026-10-16 16:44 ` [PATCH 0/8] Validate multiqueue configuration in ethdev Stephen Hemminger
8 siblings, 0 replies; 10+ messages in thread
From: David Marchand @ 2026-10-16 13:05 UTC (permalink / raw)
To: dev
Cc: thomas, Kishore Padmanabha, Ajit Khaparde, Nithin Dabilpuram,
Kiran Kumar K, Sunil Kumar Kori, Satha Rao, Harman Kalra,
Praveen Shetty, Jingjing Wu, Zyta Szpak, Liron Himi, Dimon Zhao,
Leon Yu, Sam Chen, Devendra Singh Rawat, Alok Prasad,
Andrew Rybchenko, Jerin Jacob, Maciej Czekaj, Maxime Coquelin,
Chenbo Xia, Junlong Wang, Ming Ran
Add validation in rte_eth_dev_configure() to reject invalid multi-queue
mode values early, before passing them to drivers.
If we do not enforce valid values are passed by an application,
this application might face issues in the future when we add more modes.
For Rx mq_mode, reject any bits outside the defined RSS, DCB, and VMDq
flags.
For Tx mq_mode, reject values greater than RTE_ETH_MQ_TX_VMDQ_ONLY.
Thanks to this, many drivers can stop caring about unexpected modes.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
doc/guides/rel_notes/release_26_11.rst | 1 +
drivers/net/bnxt/bnxt_rxq.c | 14 ++------------
drivers/net/cnxk/cnxk_ethdev.c | 11 -----------
drivers/net/cnxk/cnxk_rep_ops.c | 16 +---------------
drivers/net/intel/cpfl/cpfl_ethdev.c | 13 -------------
drivers/net/intel/e1000/igb_ethdev.c | 15 +--------------
drivers/net/intel/e1000/igc_ethdev.c | 19 -------------------
drivers/net/intel/idpf/idpf_ethdev.c | 6 ------
drivers/net/mvneta/mvneta_ethdev.c | 7 -------
drivers/net/mvpp2/mrvl_ethdev.c | 7 -------
drivers/net/nbl/nbl_dev/nbl_dev.c | 6 ------
drivers/net/nfp/nfp_net_common.c | 8 --------
drivers/net/octeontx/octeontx_ethdev.c | 10 ----------
drivers/net/qede/qede_ethdev.c | 5 -----
drivers/net/sfc/sfc_repr.c | 16 +---------------
drivers/net/sfc/sfc_rx.c | 14 +-------------
drivers/net/sfc/sfc_tx.c | 9 ---------
drivers/net/thunderx/nicvf_ethdev.c | 12 ------------
drivers/net/virtio/virtio_ethdev.c | 14 --------------
drivers/net/zxdh/zxdh_ethdev.c | 19 -------------------
lib/ethdev/rte_ethdev.c | 17 +++++++++++++++++
21 files changed, 24 insertions(+), 215 deletions(-)
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index caffd2a611..4c00f51d89 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -433,6 +433,7 @@ API Changes
* VMDq modes (Rx ``RTE_ETH_MQ_RX_VMDQ_FLAG``,
Tx ``RTE_ETH_MQ_TX_VMDQ_DCB``/``RTE_ETH_MQ_TX_VMDQ_ONLY``) are rejected
if the driver reports no VMDq pool.
+ * Unknown Rx and Tx modes are rejected.
* ethdev: Updated VMDq related API.
diff --git a/drivers/net/bnxt/bnxt_rxq.c b/drivers/net/bnxt/bnxt_rxq.c
index 9743296b39..11115db1fd 100644
--- a/drivers/net/bnxt/bnxt_rxq.c
+++ b/drivers/net/bnxt/bnxt_rxq.c
@@ -85,18 +85,8 @@ int bnxt_mq_rx_configure(struct bnxt *bp)
bp->nr_vnics = 0;
- /* Multi-queue mode */
- switch (dev_conf->rxmode.mq_mode) {
- case RTE_ETH_MQ_RX_NONE:
- case RTE_ETH_MQ_RX_RSS:
- pools = bp->rx_cosq_cnt ? bp->rx_cosq_cnt : pools;
- break;
- default:
- PMD_DRV_LOG_LINE(ERR, "Unsupported mq_mode %d",
- dev_conf->rxmode.mq_mode);
- return -EINVAL;
- }
-
+ if (bp->rx_cosq_cnt)
+ pools = bp->rx_cosq_cnt;
pools = RTE_MIN(pools, bp->rx_cp_nr_rings);
nb_q_per_grp = bp->rx_cp_nr_rings / pools;
PMD_DRV_LOG_LINE(DEBUG, "pools = %u nb_q_per_grp = %u",
diff --git a/drivers/net/cnxk/cnxk_ethdev.c b/drivers/net/cnxk/cnxk_ethdev.c
index 9a4da870cd..0bd0302d6a 100644
--- a/drivers/net/cnxk/cnxk_ethdev.c
+++ b/drivers/net/cnxk/cnxk_ethdev.c
@@ -1485,17 +1485,6 @@ cnxk_nix_configure(struct rte_eth_dev *eth_dev)
goto fail_configure;
}
- if (rxmode->mq_mode != RTE_ETH_MQ_RX_NONE &&
- rxmode->mq_mode != RTE_ETH_MQ_RX_RSS) {
- plt_err("Unsupported mq rx mode %d", rxmode->mq_mode);
- goto fail_configure;
- }
-
- if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
- plt_err("Unsupported mq tx mode %d", txmode->mq_mode);
- goto fail_configure;
- }
-
/* Free the resources allocated from the previous configure */
if (dev->configured == 1) {
/* Unregister queue irq's */
diff --git a/drivers/net/cnxk/cnxk_rep_ops.c b/drivers/net/cnxk/cnxk_rep_ops.c
index 4a9c027bf5..da7ebd9c26 100644
--- a/drivers/net/cnxk/cnxk_rep_ops.c
+++ b/drivers/net/cnxk/cnxk_rep_ops.c
@@ -143,12 +143,10 @@ rep_eth_conf_chk(const struct rte_eth_conf *conf, uint16_t nb_rx_queues)
ret = -EINVAL;
}
- switch (conf->rxmode.mq_mode) {
- case RTE_ETH_MQ_RX_RSS:
+ if (conf->rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) {
if (nb_rx_queues != 1) {
plt_err("Rx RSS is not supported with %u queues", nb_rx_queues);
ret = -EINVAL;
- break;
}
rss_conf = &conf->rx_adv_conf.rss_conf;
@@ -157,18 +155,6 @@ rep_eth_conf_chk(const struct rte_eth_conf *conf, uint16_t nb_rx_queues)
plt_err("Rx RSS configuration is not supported");
ret = -EINVAL;
}
- break;
- case RTE_ETH_MQ_RX_NONE:
- break;
- default:
- plt_err("Rx mode MQ modes other than RSS not supported");
- ret = -EINVAL;
- break;
- }
-
- if (conf->txmode.mq_mode != RTE_ETH_MQ_TX_NONE) {
- plt_err("Tx mode MQ modes not supported");
- ret = -EINVAL;
}
if (conf->lpbk_mode != 0) {
diff --git a/drivers/net/intel/cpfl/cpfl_ethdev.c b/drivers/net/intel/cpfl/cpfl_ethdev.c
index f425181bf2..71f0b73936 100644
--- a/drivers/net/intel/cpfl/cpfl_ethdev.c
+++ b/drivers/net/intel/cpfl/cpfl_ethdev.c
@@ -707,12 +707,6 @@ cpfl_dev_configure(struct rte_eth_dev *dev)
return -ENOTSUP;
}
- if (conf->txmode.mq_mode != RTE_ETH_MQ_TX_NONE) {
- PMD_INIT_LOG(ERR, "Multi-queue TX mode %d is not supported",
- conf->txmode.mq_mode);
- return -ENOTSUP;
- }
-
if (conf->lpbk_mode != 0) {
PMD_INIT_LOG(ERR, "Loopback operation mode %d is not supported",
conf->lpbk_mode);
@@ -739,13 +733,6 @@ cpfl_dev_configure(struct rte_eth_dev *dev)
return -ENOTSUP;
}
- if (conf->rxmode.mq_mode != RTE_ETH_MQ_RX_RSS &&
- conf->rxmode.mq_mode != RTE_ETH_MQ_RX_NONE) {
- PMD_INIT_LOG(ERR, "RX mode %d is not supported.",
- conf->rxmode.mq_mode);
- return -EINVAL;
- }
-
if (base->caps.rss_caps != 0 && dev->data->nb_rx_queues != 0) {
ret = cpfl_init_rss(vport);
if (ret != 0) {
diff --git a/drivers/net/intel/e1000/igb_ethdev.c b/drivers/net/intel/e1000/igb_ethdev.c
index 181af58169..c65a468b26 100644
--- a/drivers/net/intel/e1000/igb_ethdev.c
+++ b/drivers/net/intel/e1000/igb_ethdev.c
@@ -1179,25 +1179,12 @@ igb_check_mq_mode(struct rte_eth_dev *dev)
return -EINVAL;
}
} else {
- /* To no break software that set invalid mode, only display
- * warning if invalid mode is used.
- */
- if (rx_mq_mode != RTE_ETH_MQ_RX_NONE &&
- rx_mq_mode != RTE_ETH_MQ_RX_VMDQ_ONLY &&
- rx_mq_mode != RTE_ETH_MQ_RX_RSS) {
+ if (rx_mq_mode == RTE_ETH_MQ_RX_VMDQ_RSS) {
/* RSS together with VMDq not supported*/
PMD_INIT_LOG(ERR, "RX mode %d is not supported.",
rx_mq_mode);
return -EINVAL;
}
-
- if (tx_mq_mode != RTE_ETH_MQ_TX_NONE &&
- tx_mq_mode != RTE_ETH_MQ_TX_VMDQ_ONLY) {
- PMD_INIT_LOG(WARNING, "TX mode %d is not supported."
- " Due to txmode is meaningless in this"
- " driver, just ignore.",
- tx_mq_mode);
- }
}
return 0;
}
diff --git a/drivers/net/intel/e1000/igc_ethdev.c b/drivers/net/intel/e1000/igc_ethdev.c
index 73dd5dd1a3..2c8ff57e6b 100644
--- a/drivers/net/intel/e1000/igc_ethdev.c
+++ b/drivers/net/intel/e1000/igc_ethdev.c
@@ -344,30 +344,11 @@ static const struct eth_dev_ops eth_igc_ops = {
static int
igc_check_mq_mode(struct rte_eth_dev *dev)
{
- enum rte_eth_rx_mq_mode rx_mq_mode = dev->data->dev_conf.rxmode.mq_mode;
- enum rte_eth_tx_mq_mode tx_mq_mode = dev->data->dev_conf.txmode.mq_mode;
-
if (RTE_ETH_DEV_SRIOV(dev).active != 0) {
PMD_INIT_LOG(ERR, "SRIOV is not supported.");
return -EINVAL;
}
- if (rx_mq_mode != RTE_ETH_MQ_RX_NONE &&
- rx_mq_mode != RTE_ETH_MQ_RX_RSS) {
- /* RSS together with VMDq not supported*/
- PMD_INIT_LOG(ERR, "RX mode %d is not supported.",
- rx_mq_mode);
- return -EINVAL;
- }
-
- /* To no break software that set invalid mode, only display
- * warning if invalid mode is used.
- */
- if (tx_mq_mode != RTE_ETH_MQ_TX_NONE)
- PMD_INIT_LOG(WARNING,
- "TX mode %d is not supported. Due to meaningless in this driver, just ignore",
- tx_mq_mode);
-
return 0;
}
diff --git a/drivers/net/intel/idpf/idpf_ethdev.c b/drivers/net/intel/idpf/idpf_ethdev.c
index 5a8c783013..f3115d2369 100644
--- a/drivers/net/intel/idpf/idpf_ethdev.c
+++ b/drivers/net/intel/idpf/idpf_ethdev.c
@@ -650,12 +650,6 @@ idpf_dev_configure(struct rte_eth_dev *dev)
return -ENOTSUP;
}
- if (conf->txmode.mq_mode != RTE_ETH_MQ_TX_NONE) {
- PMD_INIT_LOG(ERR, "Multi-queue TX mode %d is not supported",
- conf->txmode.mq_mode);
- return -ENOTSUP;
- }
-
if (conf->lpbk_mode != 0) {
PMD_INIT_LOG(ERR, "Loopback operation mode %d is not supported",
conf->lpbk_mode);
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index eef9758224..975d3da81e 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -120,13 +120,6 @@ mvneta_dev_configure(struct rte_eth_dev *dev)
struct mvneta_priv *priv = dev->data->dev_private;
struct neta_ppio_params *ppio_params;
- if (dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_NONE) {
- MVNETA_LOG(INFO, "Unsupported RSS and rx multi queue mode %d",
- dev->data->dev_conf.rxmode.mq_mode);
- if (dev->data->nb_rx_queues > 1)
- return -EINVAL;
- }
-
if (dev->data->dev_conf.txmode.offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
priv->multiseg = 1;
diff --git a/drivers/net/mvpp2/mrvl_ethdev.c b/drivers/net/mvpp2/mrvl_ethdev.c
index 2df3a77e7f..9be3e5a92d 100644
--- a/drivers/net/mvpp2/mrvl_ethdev.c
+++ b/drivers/net/mvpp2/mrvl_ethdev.c
@@ -483,13 +483,6 @@ mrvl_dev_configure(struct rte_eth_dev *dev)
return -EINVAL;
}
- if (dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_NONE &&
- dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_RSS) {
- MRVL_LOG(INFO, "Unsupported rx multi queue mode %d",
- dev->data->dev_conf.rxmode.mq_mode);
- return -EINVAL;
- }
-
if (dev->data->dev_conf.rxmode.mtu > priv->max_mtu) {
MRVL_LOG(ERR, "MTU %u is larger than max_mtu %u",
dev->data->dev_conf.rxmode.mtu,
diff --git a/drivers/net/nbl/nbl_dev/nbl_dev.c b/drivers/net/nbl/nbl_dev/nbl_dev.c
index e41732ccd3..d28eea082f 100644
--- a/drivers/net/nbl/nbl_dev/nbl_dev.c
+++ b/drivers/net/nbl/nbl_dev/nbl_dev.c
@@ -14,7 +14,6 @@ static int nbl_dev_port_configure(struct nbl_adapter *adapter)
int nbl_dev_configure(struct rte_eth_dev *eth_dev)
{
struct rte_eth_dev_data *dev_data = eth_dev->data;
- enum rte_eth_rx_mq_mode rx_mq_mode = eth_dev->data->dev_conf.rxmode.mq_mode;
struct nbl_adapter *adapter = ETH_DEV_TO_NBL_DEV_PF_PRIV(eth_dev);
int ret;
@@ -23,11 +22,6 @@ int nbl_dev_configure(struct rte_eth_dev *eth_dev)
NBL_LOG(DEBUG, "Begin to configure the device, state: %d", adapter->state);
- if (rx_mq_mode != RTE_ETH_MQ_RX_NONE && rx_mq_mode != RTE_ETH_MQ_RX_RSS) {
- NBL_LOG(ERR, "Rx mq mode %d is not supported", rx_mq_mode);
- return -ENOTSUP;
- }
-
dev_data->dev_conf.intr_conf.lsc = 0;
switch (adapter->state) {
diff --git a/drivers/net/nfp/nfp_net_common.c b/drivers/net/nfp/nfp_net_common.c
index f9957086d2..97841c00b5 100644
--- a/drivers/net/nfp/nfp_net_common.c
+++ b/drivers/net/nfp/nfp_net_common.c
@@ -357,22 +357,14 @@ nfp_net_configure(struct rte_eth_dev *dev)
struct nfp_net_hw *hw;
struct rte_eth_conf *dev_conf;
struct rte_eth_rxmode *rxmode;
- struct rte_eth_txmode *txmode;
hw = nfp_net_get_hw(dev);
dev_conf = &dev->data->dev_conf;
rxmode = &dev_conf->rxmode;
- txmode = &dev_conf->txmode;
if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0)
rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
- /* Checking TX mode */
- if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
- PMD_DRV_LOG(ERR, "TX mq_mode DCB and VMDq not supported.");
- return -EINVAL;
- }
-
/* Checking MTU set */
if (rxmode->mtu > hw->max_mtu + NFP_ETH_OVERHEAD) {
PMD_DRV_LOG(ERR, "MTU (%u) larger than the maximum possible frame size (%u).",
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index e0df23049c..bde4c2c615 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -494,16 +494,6 @@ octeontx_dev_configure(struct rte_eth_dev *dev)
return -EINVAL;
}
- if (txmode->mq_mode) {
- octeontx_log_err("tx mq_mode DCB or VMDq not supported");
- return -EINVAL;
- }
-
- if (rxmode->mq_mode != RTE_ETH_MQ_RX_NONE) {
- octeontx_log_err("unsupported rx qmode %d", rxmode->mq_mode);
- return -EINVAL;
- }
-
if (!(txmode->offloads & RTE_ETH_TX_OFFLOAD_MT_LOCKFREE)) {
PMD_INIT_LOG(NOTICE, "cant disable lockfree tx");
txmode->offloads |= RTE_ETH_TX_OFFLOAD_MT_LOCKFREE;
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index c41177b86a..93fc75ad0a 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -1289,11 +1289,6 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
DP_NOTICE(edev, false,
"Invalid devargs supplied, requested change will not take effect\n");
- if (!(rxmode->mq_mode == RTE_ETH_MQ_RX_NONE ||
- rxmode->mq_mode == RTE_ETH_MQ_RX_RSS)) {
- DP_ERR(edev, "Unsupported multi-queue mode\n");
- return -ENOTSUP;
- }
/* Flow director mode check */
if (qede_check_fdir_support(eth_dev))
return -ENOTSUP;
diff --git a/drivers/net/sfc/sfc_repr.c b/drivers/net/sfc/sfc_repr.c
index 2be17d3c8f..73d7d9bbc6 100644
--- a/drivers/net/sfc/sfc_repr.c
+++ b/drivers/net/sfc/sfc_repr.c
@@ -391,13 +391,11 @@ sfc_repr_check_conf(struct sfc_repr *sr, uint16_t nb_rx_queues,
ret = -EINVAL;
}
- switch (conf->rxmode.mq_mode) {
- case RTE_ETH_MQ_RX_RSS:
+ if (conf->rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) {
if (nb_rx_queues != 1) {
sfcr_err(sr, "Rx RSS is not supported with %u queues",
nb_rx_queues);
ret = -EINVAL;
- break;
}
rss_conf = &conf->rx_adv_conf.rss_conf;
@@ -406,18 +404,6 @@ sfc_repr_check_conf(struct sfc_repr *sr, uint16_t nb_rx_queues,
sfcr_err(sr, "Rx RSS configuration is not supported");
ret = -EINVAL;
}
- break;
- case RTE_ETH_MQ_RX_NONE:
- break;
- default:
- sfcr_err(sr, "Rx mode MQ modes other than RSS not supported");
- ret = -EINVAL;
- break;
- }
-
- if (conf->txmode.mq_mode != RTE_ETH_MQ_TX_NONE) {
- sfcr_err(sr, "Tx mode MQ modes not supported");
- ret = -EINVAL;
}
if (conf->lpbk_mode != 0) {
diff --git a/drivers/net/sfc/sfc_rx.c b/drivers/net/sfc/sfc_rx.c
index aa59931f06..789507f78e 100644
--- a/drivers/net/sfc/sfc_rx.c
+++ b/drivers/net/sfc/sfc_rx.c
@@ -1670,18 +1670,6 @@ sfc_rx_check_mode(struct sfc_adapter *sa, struct rte_eth_rxmode *rxmode)
{
uint64_t offloads_supported = sfc_rx_get_dev_offload_caps(sa) |
sfc_rx_get_queue_offload_caps(sa);
- int rc = 0;
-
- switch (rxmode->mq_mode) {
- case RTE_ETH_MQ_RX_NONE:
- case RTE_ETH_MQ_RX_RSS:
- /* No special checks are required */
- break;
- default:
- sfc_err(sa, "Rx multi-queue mode %u not supported",
- rxmode->mq_mode);
- rc = EINVAL;
- }
/*
* Requested offloads are validated against supported by ethdev,
@@ -1700,7 +1688,7 @@ sfc_rx_check_mode(struct sfc_adapter *sa, struct rte_eth_rxmode *rxmode)
rxmode->offloads |= RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM;
}
- return rc;
+ return 0;
}
/**
diff --git a/drivers/net/sfc/sfc_tx.c b/drivers/net/sfc/sfc_tx.c
index fac56cb27c..a860265c6a 100644
--- a/drivers/net/sfc/sfc_tx.c
+++ b/drivers/net/sfc/sfc_tx.c
@@ -314,15 +314,6 @@ sfc_tx_check_mode(struct sfc_adapter *sa, const struct rte_eth_txmode *txmode)
uint64_t dev_tx_offload_cap = sfc_tx_get_dev_offload_caps(sa);
int rc = 0;
- switch (txmode->mq_mode) {
- case RTE_ETH_MQ_TX_NONE:
- break;
- default:
- sfc_err(sa, "Tx multi-queue mode %u not supported",
- txmode->mq_mode);
- rc = EINVAL;
- }
-
if ((dev_tx_offload_cap & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) != 0 &&
(txmode->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) == 0) {
sfc_err(sa, "There is no FAST_FREE flag in the attempted Tx mode configuration");
diff --git a/drivers/net/thunderx/nicvf_ethdev.c b/drivers/net/thunderx/nicvf_ethdev.c
index 30d03f4db9..0f7b754e8a 100644
--- a/drivers/net/thunderx/nicvf_ethdev.c
+++ b/drivers/net/thunderx/nicvf_ethdev.c
@@ -1990,7 +1990,6 @@ nicvf_dev_configure(struct rte_eth_dev *dev)
struct rte_eth_dev_data *data = dev->data;
struct rte_eth_conf *conf = &data->dev_conf;
struct rte_eth_rxmode *rxmode = &conf->rxmode;
- struct rte_eth_txmode *txmode = &conf->txmode;
struct nicvf *nic = nicvf_pmd_priv(dev);
uint8_t cqcount;
@@ -2004,17 +2003,6 @@ nicvf_dev_configure(struct rte_eth_dev *dev)
return -EINVAL;
}
- if (txmode->mq_mode) {
- PMD_INIT_LOG(INFO, "Tx mq_mode DCB or VMDq not supported");
- return -EINVAL;
- }
-
- if (rxmode->mq_mode != RTE_ETH_MQ_RX_NONE &&
- rxmode->mq_mode != RTE_ETH_MQ_RX_RSS) {
- PMD_INIT_LOG(INFO, "Unsupported rx qmode %d", rxmode->mq_mode);
- return -EINVAL;
- }
-
if (conf->dcb_capability_en) {
PMD_INIT_LOG(INFO, "DCB enable not supported");
return -EINVAL;
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index a6fe4f3023..e6ad2de4ba 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -2241,20 +2241,6 @@ virtio_dev_configure(struct rte_eth_dev *dev)
PMD_INIT_LOG(DEBUG, "configure");
req_features = VIRTIO_PMD_DEFAULT_GUEST_FEATURES;
- if (rxmode->mq_mode != RTE_ETH_MQ_RX_NONE && rxmode->mq_mode != RTE_ETH_MQ_RX_RSS) {
- PMD_DRV_LOG(ERR,
- "Unsupported Rx multi queue mode %d",
- rxmode->mq_mode);
- return -EINVAL;
- }
-
- if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
- PMD_DRV_LOG(ERR,
- "Unsupported Tx multi queue mode %d",
- txmode->mq_mode);
- return -EINVAL;
- }
-
if (dev->data->dev_conf.intr_conf.rxq) {
ret = virtio_init_device(dev, hw->req_guest_features);
if (ret < 0)
diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c
index 7c2f894642..f3efc927b2 100644
--- a/drivers/net/zxdh/zxdh_ethdev.c
+++ b/drivers/net/zxdh/zxdh_ethdev.c
@@ -1038,25 +1038,6 @@ zxdh_dev_configure(struct rte_eth_dev *dev)
return -EINVAL;
}
- if (rxmode->mq_mode != RTE_ETH_MQ_RX_RSS && rxmode->mq_mode != RTE_ETH_MQ_RX_NONE) {
- PMD_DRV_LOG(ERR, "Unsupported Rx multi queue mode %d", rxmode->mq_mode);
- return -EINVAL;
- }
-
- if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
- PMD_DRV_LOG(ERR, "Unsupported Tx multi queue mode %d", txmode->mq_mode);
- return -EINVAL;
- }
- if (rxmode->mq_mode != RTE_ETH_MQ_RX_RSS && rxmode->mq_mode != RTE_ETH_MQ_RX_NONE) {
- PMD_DRV_LOG(ERR, "Unsupported Rx multi queue mode %d", rxmode->mq_mode);
- return -EINVAL;
- }
-
- if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
- PMD_DRV_LOG(ERR, "Unsupported Tx multi queue mode %d", txmode->mq_mode);
- return -EINVAL;
- }
-
ret = zxdh_features_update(hw, rxmode, txmode);
if (ret < 0)
return ret;
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index 44b20697ae..5b99562f37 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -1526,6 +1526,23 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
goto rollback;
}
+#define RX_MQ_MODE_KNOWN_FLAGS \
+ (RTE_ETH_MQ_RX_RSS_FLAG | RTE_ETH_MQ_RX_DCB_FLAG | RTE_ETH_MQ_RX_VMDQ_FLAG)
+
+ if ((dev_conf->rxmode.mq_mode & ~RX_MQ_MODE_KNOWN_FLAGS) != 0) {
+ RTE_ETHDEV_LOG_LINE(ERR, "Ethdev port_id=%u invalid rx mq_mode 0x%x",
+ port_id, dev_conf->rxmode.mq_mode);
+ ret = -EINVAL;
+ goto rollback;
+ }
+
+ if (dev_conf->txmode.mq_mode > RTE_ETH_MQ_TX_VMDQ_ONLY) {
+ RTE_ETHDEV_LOG_LINE(ERR, "Ethdev port_id=%u invalid tx mq_mode %u",
+ port_id, dev_conf->txmode.mq_mode);
+ ret = -EINVAL;
+ goto rollback;
+ }
+
if (dev_info.flow_type_rss_offloads == 0 &&
(dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0) {
RTE_ETHDEV_LOG_LINE(ERR, "Ethdev port_id=%u does not support RSS rx mode",
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 0/8] Validate multiqueue configuration in ethdev
2026-10-16 13:05 [PATCH 0/8] Validate multiqueue configuration in ethdev David Marchand
` (7 preceding siblings ...)
2026-10-16 13:05 ` [PATCH 8/8] ethdev: check unknown Rx/Tx multi-queue modes David Marchand
@ 2026-10-16 16:44 ` Stephen Hemminger
8 siblings, 0 replies; 10+ messages in thread
From: Stephen Hemminger @ 2026-10-16 16:44 UTC (permalink / raw)
To: David Marchand; +Cc: dev, thomas
On Fri, 16 Oct 2026 15:05:46 +0200
David Marchand <david.marchand@redhat.com> wrote:
> We have various checks in drivers about Rx and Tx multiqueue
> configuration.
> This series is a followup of the VMDq cleanup, finishing the job with
> DCB and RSS, and then rejecting invalid multiqueue configuration (useful
> from an ABI point of view).
>
> Some drivers misreported their capabilities.
> It is important drivers maintainers review carefully those changes.
Thanks, eventually the whole features matrix needs to be auto generated
but that requires lots more work.
First pass of semi-manual AI review found issues
Review: [PATCH 0/8] ethdev multi-queue mode validation (David Marchand)
Applied cleanly on main (v26.11-rc1). Every commit builds with
-Dwerror=true for all touched drivers except mvneta/mvpp2 (no musdk).
All Fixes: hashes resolve.
Main problems: 7/8 rejects RSS mode on ports without RSS, which breaks
in-tree examples and drivers that deliberately tolerated it; and the
devtools trigger added in 4/8 never fires on code changes.
Patch 4/8 devtools: check VMDq capability
Error: has_code_change patterns use '\|' for alternation. git -G
compiles the pattern as ERE, where '\|' is a literal pipe, so it never
matches. On this series:
git log -G'max_vmdq_pools\|RTE_ETH_MQ_.*VMDQ' HEAD~8.. -> 0 commits
git log -G'max_vmdq_pools|RTE_ETH_MQ_.*VMDQ' HEAD~8.. -> 7 commits
So incremental mode only runs check_mq_caps when a features .ini
changes. Use ERE alternation here and in the patterns extended by 5/8
and 7/8:
if has_code_change 'max_vmdq_pools|RTE_ETH_MQ_.*VMDQ' ||
Warning: drivers under drivers/net/intel/ are never checked.
all_net_drivers and changed_net_drivers only yield "intel", there is no
intel.ini, so check_mq_caps returns early for ixgbe, i40e, igb, ice,
fm10k, ipn3ke, idpf and cpfl, i.e. most VMDq/DCB users. Running the
check over the intel subdirectories reports:
DCB documented but no get_dcb_info callback for ipn3ke
RSS documented but flow_type_rss_offloads not set for ipn3ke
VMDq documented but max_vmdq_pools not set for ipn3ke
e1000 also needs a dir to doc mapping (em/igb/igc share a directory).
igb.ini claims DCB = Y, but igb has no get_dcb_info and 5/8 removes
its "DCB mode is not supported" check. Fix igb.ini and ipn3ke.ini in
this series, and walk drivers/net/intel/*/ in the script.
Info: -S to -G also changes the existing rte_flow trigger.
-S'RTE_FLOW_.*_TYPE_' was a literal match and never fired before.
Mention it in the commit message.
Patch 7/8 ethdev: check RSS availability
Error: rejecting RTE_ETH_MQ_RX_RSS_FLAG when flow_type_rss_offloads is
0 breaks configurations that work today. Applications set RSS mode
statically and only mask rss_hf with flow_type_rss_offloads. In tree:
l3fwd, l3fwd-power, l3fwd-graph, ip_reassembly, distributor, ntb, dma,
eventdev_pipeline, multi_process mp_server, app/graph, test-eventdev.
l3fwd only clears mq_mode for disable_rss or max_rx_queues == 1, so it
now fails rte_eth_dev_configure() on virtio without VIRTIO_NET_F_RSS,
vhost, memif, af_xdp, af_packet, ring and pcap. mp_server uses one Rx
queue with RSS and fails on any port without RSS.
Drivers deliberately accepted this: mvneta (failed only with more than
one Rx queue), octeontx, sfc_repr and cnxk_rep (RSS with one queue and
no hash config). After this patch the RSS branches left in
sfc_repr_check_conf() and rep_eth_conf_chk() are unreachable.
Only reject what cannot work:
if (dev_info.flow_type_rss_offloads == 0 &&
(dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0 &&
nb_rx_q > 1) {
and fix the examples to drop RSS when the port has none, e.g. l3fwd:
if (disable_rss == 1 || dev_info.max_rx_queues == 1 ||
dev_info.flow_type_rss_offloads == 0)
local_port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE;
Update the release note wording to match.
Patch 2/8 drivers/net: fix reported VMDq capability
Warning: Fixes: targets are in released versions but there is no
Cc: stable@dpdk.org. If it goes to stable, the fm10k hunk cannot be
taken as is: it drops the VF configure check and relies on the ethdev
VMDq validation, which stable does not have.
Info: failsafe.ini VMDq = P is not mentioned in the commit message.
Patch 6/8 drivers/net: fix reported RSS capability
Warning: Fixes: targets are in released versions but there is no
Cc: stable@dpdk.org.
Warning: xsc_np.c handles L3/L4 SRC_ONLY/DST_ONLY and LEVEL_INNERMOST,
but only IP|UDP|TCP are advertised, so ethdev rejects those bits in
configure and rss_hash_update. Advertise what the driver implements:
info->flow_type_rss_offloads = RTE_ETH_RSS_IP |
RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP |
RTE_ETH_RSS_L3_SRC_ONLY | RTE_ETH_RSS_L3_DST_ONLY |
RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY |
RTE_ETH_RSS_LEVEL_INNERMOST;
Info: idpf, cpfl and cpfl representor still report hash_key_size and
reta_size when rss_caps == 0. Move them under the same condition.
Patch 1/8 net/bnxt: remove leftover VMDq code in MAC helpers
Info: bnxt_mac_addr_add_op() still range-checks pool and indexes
bp->vnic_info[pool]. With ethdev forcing pool 0 when VMDq is not
configured, it can use vnic_info[0] like the remove path.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-10-16 16:44 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 13:05 [PATCH 0/8] Validate multiqueue configuration in ethdev David Marchand
2026-10-16 13:05 ` [PATCH 1/8] net/bnxt: remove leftover VMDq code in MAC helpers David Marchand
2026-10-16 13:05 ` [PATCH 2/8] drivers/net: fix reported VMDq capability David Marchand
2026-10-16 13:05 ` [PATCH 3/8] drivers/net: remove check on VMDq modes David Marchand
2026-10-16 13:05 ` [PATCH 4/8] devtools: check VMDq capability David Marchand
2026-10-16 13:05 ` [PATCH 5/8] ethdev: check DCB availability David Marchand
2026-10-16 13:05 ` [PATCH 6/8] drivers/net: fix reported RSS capability David Marchand
2026-10-16 13:05 ` [PATCH 7/8] ethdev: check RSS availability David Marchand
2026-10-16 13:05 ` [PATCH 8/8] ethdev: check unknown Rx/Tx multi-queue modes David Marchand
2026-10-16 16:44 ` [PATCH 0/8] Validate multiqueue configuration in ethdev Stephen Hemminger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox