* [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API
@ 2025-08-30 17:17 Vladimir Medvedkin
2025-08-30 17:17 ` [RFC PATCH 1/6] ethdev: extend and refactor DCB configuration Vladimir Medvedkin
` (6 more replies)
0 siblings, 7 replies; 18+ messages in thread
From: Vladimir Medvedkin @ 2025-08-30 17:17 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko, stephen
Hi all,
This series reworks the ethdev API related to advanced queueing configuration,
specifically Data Center Bridging (DCB) and Virtual Machine Device Queues
(VMDq). The existing API was designed years ago around ixgbe hardware
assumptions, which makes it difficult to properly support modern NICs and their
more flexible capabilities.
The main goals of this refactoring are:
Unify duplicated DCB configuration structures for Tx and Rx.
Extend the API to better align with the DCB specification (e.g., TSA, per-TC
bandwidth allocation).
Decouple VMDq and DCB configuration so they can be used independently.
Enable explicit configuration of queue mappings instead of relying on
driver-specific behavior.
Clean up legacy or redundant fields that were artifacts of early
implementations.
Place multi-queue mode settings in a more consistent location within the
configuration API.
Overall, this makes the API more expressive, more consistent, and more
future-proof for modern hardware, while simplifying driver implementations.
Patch summary:
ethdev: extend and refactor DCB configuration
Introduce a common structure for Rx/Tx DCB configuration and extend it with missing DCB spec features.
ethdev: remove nb_tcs from rte_eth_dcb_conf structure
Drop legacy traffic class count field which drivers can derive from config.
ethdev: decouple VMDq and DCB configuration
Remove unnecessary coupling and redundant structures
ethdev: extend VMDq/DCB configuration with queue mapping
Allow explicit queue mapping configuration in API.
ethdev: remove dcb_capability_en from rte_eth_conf
Drop unused or misused DCB capability flags in favor of per-TC PFC API.
ethdev: move mq_mode to [r,t]x_adv_conf
Relocate mq_mode to advanced config, and make it a flag field.
This is an API-breaking series, but it is expected to make the interface cleaner
and more aligned with modern NIC capabilities. Feedback on both the design
direction and implementation details is very welcome.
Note: This RFC series reflects changes only for ice PMD and testpmd app
(no other drivers or examples apps was changed) and depends on:
https://patches.dpdk.org/project/dpdk/list/?series=35948
thus configure your build like:
meson setup -Denable_drivers=net/intel/ice
Vladimir Medvedkin (6):
ethdev: extend and refactor DCB configuration
ethdev: remove nb_tcs from rte_eth_dcb_conf structure
ethdev: decouple VMDq and DCB cofiguration
ethdev: extend VMDq/DCB configuration with queue mapping
ethdev: remove dcb_capability_en from rte_eth_conf
ethdev: move mq_mode to [r,t]x_adv_conf
app/graph/ethdev.c | 6 +-
app/test-eventdev/test_perf_common.c | 4 +-
app/test-eventdev/test_pipeline_common.c | 4 +-
app/test-pipeline/init.c | 2 +-
app/test-pmd/cmdline.c | 27 +---
app/test-pmd/parameters.c | 4 +-
app/test-pmd/testpmd.c | 153 +++++++++++---------
app/test-pmd/testpmd.h | 5 +-
app/test/test_event_eth_rx_adapter.c | 4 +-
app/test/test_link_bonding.c | 4 +-
app/test/test_link_bonding_rssconf.c | 8 +-
app/test/test_pmd_perf.c | 4 +-
app/test/test_security_inline_macsec.c | 12 +-
app/test/test_security_inline_proto.c | 12 +-
drivers/net/intel/ice/ice_dcf.c | 2 +-
drivers/net/intel/ice/ice_dcf_ethdev.c | 2 +-
drivers/net/intel/ice/ice_ethdev.c | 137 ++++++++++--------
drivers/net/intel/ice/ice_rxtx.c | 27 ++--
lib/ethdev/ethdev_trace.h | 4 +-
lib/ethdev/rte_ethdev.c | 10 +-
lib/ethdev/rte_ethdev.h | 169 ++++++++---------------
21 files changed, 294 insertions(+), 306 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFC PATCH 1/6] ethdev: extend and refactor DCB configuration
2025-08-30 17:17 [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Vladimir Medvedkin
@ 2025-08-30 17:17 ` Vladimir Medvedkin
2025-08-30 19:52 ` Ivan Malov
2025-08-30 19:57 ` Ivan Malov
2025-08-30 17:17 ` [RFC PATCH 2/6] ethdev: remove nb_tcs from rte_eth_dcb_conf structure Vladimir Medvedkin
` (5 subsequent siblings)
6 siblings, 2 replies; 18+ messages in thread
From: Vladimir Medvedkin @ 2025-08-30 17:17 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko, stephen
Currently there are two structutes defined for DCB configuration, one for
RX and one for TX. They do have slight semantic difference, but in terms
of their structure they are identical. Refactor DCB configuration API to
use common structute for both TX and RX.
Additionally, current structure do not reflect everything that is
required by the DCB specification, such as per Traffic Class bandwidth
allocation and Traffic Selection Algorithm (TSA). Extend rte_eth_dcb_conf
with additional DCB settings
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
app/test-pmd/testpmd.c | 19 ++++++-
drivers/net/intel/ice/ice_ethdev.c | 80 ++++++++++++++++++++----------
lib/ethdev/rte_ethdev.h | 25 ++++++----
3 files changed, 85 insertions(+), 39 deletions(-)
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index bb88555328..d64a7dcac5 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -4134,9 +4134,9 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
(rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_DCB);
eth_conf->txmode.mq_mode = RTE_ETH_MQ_TX_VMDQ_DCB;
} else {
- struct rte_eth_dcb_rx_conf *rx_conf =
+ struct rte_eth_dcb_conf *rx_conf =
ð_conf->rx_adv_conf.dcb_rx_conf;
- struct rte_eth_dcb_tx_conf *tx_conf =
+ struct rte_eth_dcb_conf *tx_conf =
ð_conf->tx_adv_conf.dcb_tx_conf;
rx_conf->nb_tcs = num_tcs;
@@ -4148,6 +4148,21 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
tx_conf->dcb_tc[i] = dcb_tc_val;
}
+ const int bw_share_percent = 100 / num_tcs;
+ const int bw_share_left = 100 - bw_share_percent * num_tcs;
+ for (i = 0; i < num_tcs; i++) {
+ rx_conf->dcb_tc_bw[i] = bw_share_percent;
+ tx_conf->dcb_tc_bw[i] = bw_share_percent;
+
+ rx_conf->dcb_tsa[i] = RTE_ETH_DCB_TSA_ETS;
+ tx_conf->dcb_tsa[i] = RTE_ETH_DCB_TSA_ETS;
+ }
+
+ for (i = 0; i < bw_share_left; i++) {
+ rx_conf->dcb_tc_bw[i]++;
+ tx_conf->dcb_tc_bw[i]++;
+ }
+
eth_conf->rxmode.mq_mode =
(enum rte_eth_rx_mq_mode)
(rx_mq_mode & RTE_ETH_MQ_RX_DCB_RSS);
diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index 8ab0da3549..7ba25049d7 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -3760,10 +3760,13 @@ static int ice_init_rss(struct ice_pf *pf)
}
static int
-check_dcb_conf(int is_8_ports, struct rte_eth_dcb_rx_conf *dcb_conf)
+check_dcb_conf(int is_8_ports, struct rte_eth_dcb_conf *dcb_conf)
{
uint32_t tc_map = 0;
int i;
+ int total_bw_allocated = 0;
+ bool ets_seen = false;
+ int nb_tc_used;
enum rte_eth_nb_tcs nb_tcs = dcb_conf->nb_tcs;
if (nb_tcs != RTE_ETH_4_TCS && is_8_ports) {
@@ -3784,7 +3787,31 @@ check_dcb_conf(int is_8_ports, struct rte_eth_dcb_rx_conf *dcb_conf)
return -1;
}
- return rte_popcount32(tc_map);
+ nb_tc_used = rte_popcount32(tc_map);
+
+ /* calculate total ETS Bandwidth allocation */
+ for (i = 0; i < nb_tc_used; i++) {
+ if (dcb_conf->dcb_tsa[i] == RTE_ETH_DCB_TSA_ETS) {
+ if (dcb_conf->dcb_tc_bw[i] == 0) {
+ PMD_DRV_LOG(ERR,
+ "Bad ETS BW configuration, can not allocate 0%%");
+ return -1;
+ }
+ total_bw_allocated += dcb_conf->dcb_tc_bw[i];
+ ets_seen = true;
+ } else if (dcb_conf->dcb_tsa[i] != RTE_ETH_DCB_TSA_STRICT) {
+ PMD_DRV_LOG(ERR, "Invalid TC TSA setting - only Strict and ETS are supported");
+ return -1;
+ }
+ }
+
+ /* total ETS BW allocation must add up to 100% */
+ if (ets_seen && total_bw_allocated != 100) {
+ PMD_DRV_LOG(ERR, "Invalid TC Bandwidth allocation configuration");
+ return -1;
+ }
+
+ return nb_tc_used;
}
static int
@@ -3819,15 +3846,22 @@ ice_dev_configure(struct rte_eth_dev *dev)
struct ice_qos_cfg *qos_cfg = &port_info->qos_cfg;
struct ice_dcbx_cfg *local_dcb_conf = &qos_cfg->local_dcbx_cfg;
struct ice_vsi_ctx ctxt;
- struct rte_eth_dcb_rx_conf *dcb_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
+ struct rte_eth_dcb_conf *rx_dcb_conf =
+ &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
+ struct rte_eth_dcb_conf *tx_dcb_conf =
+ &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
int i;
- enum rte_eth_nb_tcs nb_tcs = dcb_conf->nb_tcs;
- int nb_tc_used, queues_per_tc;
+ enum rte_eth_nb_tcs nb_tcs = rx_dcb_conf->nb_tcs;
+ int nb_tc_used_rx, nb_tc_used_tx, queues_per_tc;
uint16_t total_q_nb;
- nb_tc_used = check_dcb_conf(ice_get_port_max_cgd(hw) == ICE_4_CGD_PER_PORT,
- dcb_conf);
- if (nb_tc_used < 0)
+ nb_tc_used_rx = check_dcb_conf(ice_get_port_max_cgd(hw) == ICE_4_CGD_PER_PORT,
+ rx_dcb_conf);
+ if (nb_tc_used_rx < 0)
+ return -EINVAL;
+ nb_tc_used_tx = check_dcb_conf(ice_get_port_max_cgd(hw) == ICE_4_CGD_PER_PORT,
+ tx_dcb_conf);
+ if (nb_tc_used_tx < 0)
return -EINVAL;
ctxt.info = vsi->info;
@@ -3837,8 +3871,8 @@ ice_dev_configure(struct rte_eth_dev *dev)
}
total_q_nb = dev->data->nb_rx_queues;
- queues_per_tc = total_q_nb / nb_tc_used;
- if (total_q_nb % nb_tc_used != 0) {
+ queues_per_tc = total_q_nb / nb_tc_used_rx;
+ if (total_q_nb % nb_tc_used_rx != 0) {
PMD_DRV_LOG(ERR, "For DCB, number of queues must be evenly divisble by number of used TCs");
return -EINVAL;
} else if (!rte_is_power_of_2(queues_per_tc)) {
@@ -3846,7 +3880,7 @@ ice_dev_configure(struct rte_eth_dev *dev)
return -EINVAL;
}
- for (i = 0; i < nb_tc_used; i++) {
+ for (i = 0; i < nb_tc_used_rx; i++) {
ctxt.info.tc_mapping[i] =
rte_cpu_to_le_16(((i * queues_per_tc) << ICE_AQ_VSI_TC_Q_OFFSET_S) |
(rte_log2_u32(queues_per_tc) << ICE_AQ_VSI_TC_Q_NUM_S));
@@ -3858,29 +3892,21 @@ ice_dev_configure(struct rte_eth_dev *dev)
/* Associate each VLAN UP with particular TC */
for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
- local_dcb_conf->etscfg.prio_table[i] = dcb_conf->dcb_tc[i];
- local_dcb_conf->etsrec.prio_table[i] = dcb_conf->dcb_tc[i];
+ local_dcb_conf->etscfg.prio_table[i] = rx_dcb_conf->dcb_tc[i];
+ local_dcb_conf->etsrec.prio_table[i] = tx_dcb_conf->dcb_tc[i];
}
- /*
- * Since current API does not support setting ETS BW Share and Scheduler
- * configure all TC as ETS and evenly share load across all existing TC
- **/
- const int bw_share_percent = 100 / nb_tc_used;
- const int bw_share_left = 100 - bw_share_percent * nb_tc_used;
- for (i = 0; i < nb_tc_used; i++) {
+ for (i = 0; i < nb_tc_used_rx; i++) {
/* Per TC bandwidth table (all valued must add up to 100%), valid on ETS */
- local_dcb_conf->etscfg.tcbwtable[i] = bw_share_percent;
- local_dcb_conf->etsrec.tcbwtable[i] = bw_share_percent;
+ local_dcb_conf->etscfg.tcbwtable[i] = rx_dcb_conf->dcb_tc_bw[i];
/**< Transmission Selection Algorithm. 0 - Strict prio, 2 - ETS */
- local_dcb_conf->etscfg.tsatable[i] = 2;
- local_dcb_conf->etsrec.tsatable[i] = 2;
+ local_dcb_conf->etscfg.tsatable[i] = rx_dcb_conf->dcb_tsa[i];
}
- for (i = 0; i < bw_share_left; i++) {
- local_dcb_conf->etscfg.tcbwtable[i]++;
- local_dcb_conf->etsrec.tcbwtable[i]++;
+ for (i = 0; i < nb_tc_used_tx; i++) {
+ local_dcb_conf->etsrec.tcbwtable[i] = tx_dcb_conf->dcb_tc_bw[i];
+ local_dcb_conf->etsrec.tsatable[i] = tx_dcb_conf->dcb_tsa[i];
}
local_dcb_conf->pfc.pfccap = nb_tcs;
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index f9fb6ae549..13b1a41d3b 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -853,6 +853,7 @@ rte_eth_rss_hf_refine(uint64_t rss_hf)
/**@{@name VMDq and DCB maximums */
#define RTE_ETH_VMDQ_MAX_VLAN_FILTERS 64 /**< Maximum nb. of VMDq VLAN filters. */
#define RTE_ETH_DCB_NUM_USER_PRIORITIES 8 /**< Maximum nb. of DCB priorities. */
+#define RTE_ETH_DCB_NUM_TCS 8 /**< Maximum nb. of DCB traffic classes. */
#define RTE_ETH_VMDQ_DCB_NUM_QUEUES 128 /**< Maximum nb. of VMDq DCB queues. */
#define RTE_ETH_DCB_NUM_QUEUES 128 /**< Maximum nb. of DCB queues. */
/**@}*/
@@ -929,11 +930,21 @@ enum rte_eth_nb_pools {
RTE_ETH_64_POOLS = 64 /**< 64 VMDq pools. */
};
+#define RTE_ETH_DCB_TSA_STRICT 0
+#define RTE_ETH_DCB_TSA_ETS 2
+
/* This structure may be extended in future. */
-struct rte_eth_dcb_rx_conf {
+struct rte_eth_dcb_conf {
enum rte_eth_nb_tcs nb_tcs; /**< Possible DCB TCs, 4 or 8 TCs */
- /** Traffic class each UP mapped to. */
+ /** Traffic class each UP mapped to.
+ * Rx packets VLAN UP for Rx configuration
+ * Rx PFC Pause frames UP for Tx configuration
+ */
uint8_t dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
+ /** Traffic class selector algorithm */
+ uint8_t dcb_tsa[RTE_ETH_DCB_NUM_TCS];
+ /** Traffic class relative bandwidth in percents */
+ uint8_t dcb_tc_bw[RTE_ETH_DCB_NUM_TCS];
};
struct rte_eth_vmdq_dcb_tx_conf {
@@ -942,12 +953,6 @@ struct rte_eth_vmdq_dcb_tx_conf {
uint8_t dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
};
-struct rte_eth_dcb_tx_conf {
- enum rte_eth_nb_tcs nb_tcs; /**< Possible DCB TCs, 4 or 8 TCs. */
- /** Traffic class each UP mapped to. */
- uint8_t dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
-};
-
struct rte_eth_vmdq_tx_conf {
enum rte_eth_nb_pools nb_queue_pools; /**< VMDq mode, 64 pools. */
};
@@ -1531,7 +1536,7 @@ struct rte_eth_conf {
/** Port VMDq+DCB configuration. */
struct rte_eth_vmdq_dcb_conf vmdq_dcb_conf;
/** Port DCB Rx configuration. */
- struct rte_eth_dcb_rx_conf dcb_rx_conf;
+ struct rte_eth_dcb_conf dcb_rx_conf;
/** Port VMDq Rx configuration. */
struct rte_eth_vmdq_rx_conf vmdq_rx_conf;
} rx_adv_conf; /**< Port Rx filtering configuration. */
@@ -1539,7 +1544,7 @@ struct rte_eth_conf {
/** Port VMDq+DCB Tx configuration. */
struct rte_eth_vmdq_dcb_tx_conf vmdq_dcb_tx_conf;
/** Port DCB Tx configuration. */
- struct rte_eth_dcb_tx_conf dcb_tx_conf;
+ struct rte_eth_dcb_conf dcb_tx_conf;
/** Port VMDq Tx configuration. */
struct rte_eth_vmdq_tx_conf vmdq_tx_conf;
} tx_adv_conf; /**< Port Tx DCB configuration (union). */
--
2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFC PATCH 2/6] ethdev: remove nb_tcs from rte_eth_dcb_conf structure
2025-08-30 17:17 [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Vladimir Medvedkin
2025-08-30 17:17 ` [RFC PATCH 1/6] ethdev: extend and refactor DCB configuration Vladimir Medvedkin
@ 2025-08-30 17:17 ` Vladimir Medvedkin
2025-08-30 17:17 ` [RFC PATCH 3/6] ethdev: decouple VMDq and DCB cofiguration Vladimir Medvedkin
` (4 subsequent siblings)
6 siblings, 0 replies; 18+ messages in thread
From: Vladimir Medvedkin @ 2025-08-30 17:17 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko, stephen
Current DCB API was not changed since the first public release and is
heavily influenced by how DCB works in devices using ixgbe driver.
Specifically, the API assumes that we can only configure either 4 or 8
Traffic Classes per port. While that may be true on some HW, this has
nothing to do with DCB specification and instead is an artifact of how
DCB was implemented back in the day. Moreover, this is actually not
needed because the driver can infer the number of traffic classes from
the DCB configuration data (dcb_tc array).
Remove the unneeded field from DCB configuration structure.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
app/test-pmd/cmdline.c | 8 ++++----
app/test-pmd/testpmd.c | 11 ++++-------
app/test-pmd/testpmd.h | 2 +-
drivers/net/intel/ice/ice_ethdev.c | 18 ++++++------------
lib/ethdev/rte_ethdev.h | 10 ----------
5 files changed, 15 insertions(+), 34 deletions(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 7b4e27eddf..82322f3456 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -3472,7 +3472,7 @@ parse_dcb_token_prio_tc(char *param_str[], int param_num,
return -1;
}
tc = strtoul(end + 1, &end, 10);
- if (tc >= RTE_ETH_8_TCS) {
+ if (tc >= RTE_ETH_DCB_NUM_TCS) {
fprintf(stderr, "Bad Argument: invalid TC %lu\n", tc);
return -1;
}
@@ -3625,7 +3625,7 @@ cmd_config_dcb_parsed(void *parsed_result,
return;
}
- if (res->num_tcs < 1 || res->num_tcs > RTE_ETH_8_TCS) {
+ if (res->num_tcs < 1 || res->num_tcs > RTE_ETH_DCB_NUM_TCS) {
fprintf(stderr,
"The invalid number of traffic class, only 1~8 allowed.\n");
return;
@@ -3651,11 +3651,11 @@ cmd_config_dcb_parsed(void *parsed_result,
/* DCB in VT mode */
if (!strncmp(res->vt_en, "on", 2))
ret = init_port_dcb_config(port_id, DCB_VT_ENABLED,
- (enum rte_eth_nb_tcs)res->num_tcs,
+ (int)res->num_tcs,
pfc_en, prio_tc, prio_tc_en, keep_qnum);
else
ret = init_port_dcb_config(port_id, DCB_ENABLED,
- (enum rte_eth_nb_tcs)res->num_tcs,
+ (int)res->num_tcs,
pfc_en, prio_tc, prio_tc_en, keep_qnum);
if (ret != 0) {
fprintf(stderr, "Cannot initialize network ports.\n");
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index d64a7dcac5..b551140165 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -4093,7 +4093,7 @@ const uint16_t vlan_tags[] = {
static void
get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
- enum rte_eth_nb_tcs num_tcs, uint8_t pfc_en,
+ int num_tcs, uint8_t pfc_en,
uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES], uint8_t prio_tc_en)
{
uint8_t dcb_tc_val, i;
@@ -4112,9 +4112,9 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
vmdq_rx_conf->enable_default_pool = 0;
vmdq_rx_conf->default_pool = 0;
vmdq_rx_conf->nb_queue_pools =
- (num_tcs == RTE_ETH_4_TCS ? RTE_ETH_32_POOLS : RTE_ETH_16_POOLS);
+ (num_tcs <= 4 ? RTE_ETH_32_POOLS : RTE_ETH_16_POOLS);
vmdq_tx_conf->nb_queue_pools =
- (num_tcs == RTE_ETH_4_TCS ? RTE_ETH_32_POOLS : RTE_ETH_16_POOLS);
+ (num_tcs <= 4 ? RTE_ETH_32_POOLS : RTE_ETH_16_POOLS);
vmdq_rx_conf->nb_pool_maps = vmdq_rx_conf->nb_queue_pools;
for (i = 0; i < vmdq_rx_conf->nb_pool_maps; i++) {
@@ -4139,9 +4139,6 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
struct rte_eth_dcb_conf *tx_conf =
ð_conf->tx_adv_conf.dcb_tx_conf;
- rx_conf->nb_tcs = num_tcs;
- tx_conf->nb_tcs = num_tcs;
-
for (i = 0; i < RTE_ETH_DCB_NUM_USER_PRIORITIES; i++) {
dcb_tc_val = prio_tc_en ? prio_tc[i] : i % num_tcs;
rx_conf->dcb_tc[i] = dcb_tc_val;
@@ -4195,7 +4192,7 @@ clear_eth_dcb_conf(portid_t pid, struct rte_eth_conf *eth_conf)
int
init_port_dcb_config(portid_t pid,
enum dcb_mode_enable dcb_mode,
- enum rte_eth_nb_tcs num_tcs,
+ int num_tcs,
uint8_t pfc_en,
uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES],
uint8_t prio_tc_en,
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index e629edaa02..4ff982ed3f 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -1150,7 +1150,7 @@ void clear_port_member_flag(portid_t member_pid);
uint8_t port_is_bonding_member(portid_t member_pid);
int init_port_dcb_config(portid_t pid, enum dcb_mode_enable dcb_mode,
- enum rte_eth_nb_tcs num_tcs,
+ int num_tcs,
uint8_t pfc_en,
uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES],
uint8_t prio_tc_en,
diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index 7ba25049d7..ecde00182f 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -3768,15 +3768,6 @@ check_dcb_conf(int is_8_ports, struct rte_eth_dcb_conf *dcb_conf)
bool ets_seen = false;
int nb_tc_used;
- enum rte_eth_nb_tcs nb_tcs = dcb_conf->nb_tcs;
- if (nb_tcs != RTE_ETH_4_TCS && is_8_ports) {
- PMD_DRV_LOG(ERR, "Invalid num TCs setting - only 4 TCs are supported");
- return -1;
- } else if (nb_tcs != RTE_ETH_4_TCS && nb_tcs != RTE_ETH_8_TCS) {
- PMD_DRV_LOG(ERR, "Invalid num TCs setting - only 8 TCs or 4 TCs are supported");
- return -1;
- }
-
/* Check if associated TC are in continuous range */
for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++)
tc_map |= 1 << (dcb_conf->dcb_tc[i] & 0x7);
@@ -3788,6 +3779,10 @@ check_dcb_conf(int is_8_ports, struct rte_eth_dcb_conf *dcb_conf)
}
nb_tc_used = rte_popcount32(tc_map);
+ if (nb_tc_used > 4 && is_8_ports) {
+ PMD_DRV_LOG(ERR, "Invalid num TCs setting - only 4 TCs are supported");
+ return -1;
+ }
/* calculate total ETS Bandwidth allocation */
for (i = 0; i < nb_tc_used; i++) {
@@ -3851,7 +3846,6 @@ ice_dev_configure(struct rte_eth_dev *dev)
struct rte_eth_dcb_conf *tx_dcb_conf =
&dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
int i;
- enum rte_eth_nb_tcs nb_tcs = rx_dcb_conf->nb_tcs;
int nb_tc_used_rx, nb_tc_used_tx, queues_per_tc;
uint16_t total_q_nb;
@@ -3888,7 +3882,7 @@ ice_dev_configure(struct rte_eth_dev *dev)
memset(local_dcb_conf, 0, sizeof(*local_dcb_conf));
- local_dcb_conf->etscfg.maxtcs = nb_tcs;
+ local_dcb_conf->etscfg.maxtcs = nb_tc_used_rx;
/* Associate each VLAN UP with particular TC */
for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
@@ -3909,7 +3903,7 @@ ice_dev_configure(struct rte_eth_dev *dev)
local_dcb_conf->etsrec.tsatable[i] = tx_dcb_conf->dcb_tsa[i];
}
- local_dcb_conf->pfc.pfccap = nb_tcs;
+ local_dcb_conf->pfc.pfccap = RTE_MAX(nb_tc_used_rx, nb_tc_used_tx);
local_dcb_conf->pfc.pfcena = 0;
ret = ice_set_dcb_cfg(port_info);
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index 13b1a41d3b..1579be5a95 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -910,15 +910,6 @@ struct rte_eth_rss_reta_entry64 {
uint16_t reta[RTE_ETH_RETA_GROUP_SIZE];
};
-/**
- * This enum indicates the possible number of traffic classes
- * in DCB configurations
- */
-enum rte_eth_nb_tcs {
- RTE_ETH_4_TCS = 4, /**< 4 TCs with DCB. */
- RTE_ETH_8_TCS = 8 /**< 8 TCs with DCB. */
-};
-
/**
* This enum indicates the possible number of queue pools
* in VMDq configurations.
@@ -935,7 +926,6 @@ enum rte_eth_nb_pools {
/* This structure may be extended in future. */
struct rte_eth_dcb_conf {
- enum rte_eth_nb_tcs nb_tcs; /**< Possible DCB TCs, 4 or 8 TCs */
/** Traffic class each UP mapped to.
* Rx packets VLAN UP for Rx configuration
* Rx PFC Pause frames UP for Tx configuration
--
2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFC PATCH 3/6] ethdev: decouple VMDq and DCB cofiguration
2025-08-30 17:17 [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Vladimir Medvedkin
2025-08-30 17:17 ` [RFC PATCH 1/6] ethdev: extend and refactor DCB configuration Vladimir Medvedkin
2025-08-30 17:17 ` [RFC PATCH 2/6] ethdev: remove nb_tcs from rte_eth_dcb_conf structure Vladimir Medvedkin
@ 2025-08-30 17:17 ` Vladimir Medvedkin
2025-08-30 17:17 ` [RFC PATCH 4/6] ethdev: extend VMDq/DCB configuration with queue mapping Vladimir Medvedkin
` (3 subsequent siblings)
6 siblings, 0 replies; 18+ messages in thread
From: Vladimir Medvedkin @ 2025-08-30 17:17 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko, stephen
Current API expects that VMDq and DCB configuration are interconnected,
which may be true for some HW, but isn't universal. For one, we have a
VMDq+DCB configuration structure, but it is not needed because we already
have separate VMDq and DCB structures, so remove it.
Additionally, tx_adv_conf is currently a union, which makes the above
structure necessary, but again, it is not needed if we make tx_adv_conf a
structure and use separate VMDQ and DCB configurations.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
app/test-pmd/testpmd.c | 31 +++++++++++++++++++++++++------
lib/ethdev/rte_ethdev.h | 35 +----------------------------------
2 files changed, 26 insertions(+), 40 deletions(-)
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index b551140165..b5a7e7b3ee 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -4103,10 +4103,14 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
* given above, and the number of traffic classes available for use.
*/
if (dcb_mode == DCB_VT_ENABLED) {
- struct rte_eth_vmdq_dcb_conf *vmdq_rx_conf =
- ð_conf->rx_adv_conf.vmdq_dcb_conf;
- struct rte_eth_vmdq_dcb_tx_conf *vmdq_tx_conf =
- ð_conf->tx_adv_conf.vmdq_dcb_tx_conf;
+ struct rte_eth_vmdq_rx_conf *vmdq_rx_conf =
+ ð_conf->rx_adv_conf.vmdq_rx_conf;
+ struct rte_eth_vmdq_tx_conf *vmdq_tx_conf =
+ ð_conf->tx_adv_conf.vmdq_tx_conf;
+ struct rte_eth_dcb_conf *dcb_rx_conf =
+ ð_conf->rx_adv_conf.dcb_rx_conf;
+ struct rte_eth_dcb_conf *dcb_tx_conf =
+ ð_conf->tx_adv_conf.dcb_tx_conf;
/* VMDQ+DCB RX and TX configurations */
vmdq_rx_conf->enable_default_pool = 0;
@@ -4124,8 +4128,23 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
}
for (i = 0; i < RTE_ETH_DCB_NUM_USER_PRIORITIES; i++) {
dcb_tc_val = prio_tc_en ? prio_tc[i] : i % num_tcs;
- vmdq_rx_conf->dcb_tc[i] = dcb_tc_val;
- vmdq_tx_conf->dcb_tc[i] = dcb_tc_val;
+ dcb_rx_conf->dcb_tc[i] = dcb_tc_val;
+ dcb_tx_conf->dcb_tc[i] = dcb_tc_val;
+ }
+
+ const int bw_share_percent = 100 / num_tcs;
+ const int bw_share_left = 100 - bw_share_percent * num_tcs;
+ for (i = 0; i < num_tcs; i++) {
+ dcb_rx_conf->dcb_tc_bw[i] = bw_share_percent;
+ dcb_tx_conf->dcb_tc_bw[i] = bw_share_percent;
+
+ dcb_rx_conf->dcb_tsa[i] = RTE_ETH_DCB_TSA_ETS;
+ dcb_tx_conf->dcb_tsa[i] = RTE_ETH_DCB_TSA_ETS;
+ }
+
+ for (i = 0; i < bw_share_left; i++) {
+ dcb_rx_conf->dcb_tc_bw[i]++;
+ dcb_tx_conf->dcb_tc_bw[i]++;
}
/* set DCB mode of RX and TX of multiple queues */
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index 1579be5a95..c220760043 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -937,39 +937,10 @@ struct rte_eth_dcb_conf {
uint8_t dcb_tc_bw[RTE_ETH_DCB_NUM_TCS];
};
-struct rte_eth_vmdq_dcb_tx_conf {
- enum rte_eth_nb_pools nb_queue_pools; /**< With DCB, 16 or 32 pools. */
- /** Traffic class each UP mapped to. */
- uint8_t dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
-};
-
struct rte_eth_vmdq_tx_conf {
enum rte_eth_nb_pools nb_queue_pools; /**< VMDq mode, 64 pools. */
};
-/**
- * A structure used to configure the VMDq+DCB feature
- * of an Ethernet port.
- *
- * Using this feature, packets are routed to a pool of queues, based
- * on the VLAN ID in the VLAN tag, and then to a specific queue within
- * that pool, using the user priority VLAN tag field.
- *
- * A default pool may be used, if desired, to route all traffic which
- * does not match the VLAN filter rules.
- */
-struct rte_eth_vmdq_dcb_conf {
- enum rte_eth_nb_pools nb_queue_pools; /**< With DCB, 16 or 32 pools */
- uint8_t enable_default_pool; /**< If non-zero, use a default pool */
- uint8_t default_pool; /**< The default pool, if applicable */
- uint8_t nb_pool_maps; /**< We can have up to 64 filters/mappings */
- struct {
- uint16_t vlan_id; /**< The VLAN ID of the received frame */
- uint64_t pools; /**< Bitmask of pools for packet Rx */
- } pool_map[RTE_ETH_VMDQ_MAX_VLAN_FILTERS]; /**< VMDq VLAN pool maps. */
- /** Selects a queue in a pool */
- uint8_t dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
-};
/**
* A structure used to configure the VMDq feature of an Ethernet port when
@@ -1523,16 +1494,12 @@ struct rte_eth_conf {
are defined in implementation of each driver. */
struct {
struct rte_eth_rss_conf rss_conf; /**< Port RSS configuration */
- /** Port VMDq+DCB configuration. */
- struct rte_eth_vmdq_dcb_conf vmdq_dcb_conf;
/** Port DCB Rx configuration. */
struct rte_eth_dcb_conf dcb_rx_conf;
/** Port VMDq Rx configuration. */
struct rte_eth_vmdq_rx_conf vmdq_rx_conf;
} rx_adv_conf; /**< Port Rx filtering configuration. */
- union {
- /** Port VMDq+DCB Tx configuration. */
- struct rte_eth_vmdq_dcb_tx_conf vmdq_dcb_tx_conf;
+ struct {
/** Port DCB Tx configuration. */
struct rte_eth_dcb_conf dcb_tx_conf;
/** Port VMDq Tx configuration. */
--
2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFC PATCH 4/6] ethdev: extend VMDq/DCB configuration with queue mapping
2025-08-30 17:17 [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Vladimir Medvedkin
` (2 preceding siblings ...)
2025-08-30 17:17 ` [RFC PATCH 3/6] ethdev: decouple VMDq and DCB cofiguration Vladimir Medvedkin
@ 2025-08-30 17:17 ` Vladimir Medvedkin
2025-08-30 20:36 ` Ivan Malov
2025-08-30 17:17 ` [RFC PATCH 5/6] ethdev: remove dcb_capability_en from rte_eth_conf Vladimir Medvedkin
` (2 subsequent siblings)
6 siblings, 1 reply; 18+ messages in thread
From: Vladimir Medvedkin @ 2025-08-30 17:17 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko, stephen
Currently DCB Traffic Class queue mapping is only used when calling get
DCB info API, while setting up queue mappings is up to each individual
driver. Use the tc queue mapping structure to enable setting up custom
mapping explicitly.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
app/test-pmd/testpmd.c | 57 ++++++++++++++++++------------
drivers/net/intel/ice/ice_ethdev.c | 39 ++++++++++----------
drivers/net/intel/ice/ice_rxtx.c | 27 +++++++-------
lib/ethdev/rte_ethdev.h | 43 +++++++++++-----------
4 files changed, 92 insertions(+), 74 deletions(-)
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index b5a7e7b3ee..3a55434d44 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -4158,6 +4158,16 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
struct rte_eth_dcb_conf *tx_conf =
ð_conf->tx_adv_conf.dcb_tx_conf;
+ struct rte_eth_dcb_tc_queue_mapping *q_map = ð_conf->q_map;
+ memset(q_map, 0, sizeof(*q_map));
+ int queues_per_tc = nb_rxq / num_tcs;
+ for (i = 0; i < num_tcs; i++) {
+ q_map->tc_rxq[0][i].base = i * queues_per_tc;
+ q_map->tc_txq[0][i].base = i * queues_per_tc;
+ q_map->tc_rxq[0][i].nb_queue = queues_per_tc;
+ q_map->tc_txq[0][i].nb_queue = queues_per_tc;
+ }
+
for (i = 0; i < RTE_ETH_DCB_NUM_USER_PRIORITIES; i++) {
dcb_tc_val = prio_tc_en ? prio_tc[i] : i % num_tcs;
rx_conf->dcb_tc[i] = dcb_tc_val;
@@ -4231,6 +4241,30 @@ init_port_dcb_config(portid_t pid,
/* retain the original device configuration. */
memcpy(&port_conf, &rte_port->dev_conf, sizeof(struct rte_eth_conf));
+ if (num_tcs > 1 && keep_qnum == 0) {
+ /* Assume the ports in testpmd have the same dcb capability
+ * and has the same number of rxq and txq in dcb mode
+ */
+ if (dcb_mode == DCB_VT_ENABLED) {
+ if (rte_port->dev_info.max_vfs > 0) {
+ nb_rxq = rte_port->dev_info.nb_rx_queues;
+ nb_txq = rte_port->dev_info.nb_tx_queues;
+ } else {
+ nb_rxq = rte_port->dev_info.max_rx_queues;
+ nb_txq = rte_port->dev_info.max_tx_queues;
+ }
+ } else {
+ /*if vt is disabled, use all pf queues */
+ if (rte_port->dev_info.vmdq_pool_base == 0) {
+ nb_rxq = rte_port->dev_info.max_rx_queues;
+ nb_txq = rte_port->dev_info.max_tx_queues;
+ } else {
+ nb_rxq = (queueid_t)num_tcs;
+ nb_txq = (queueid_t)num_tcs;
+ }
+ }
+ }
+
if (num_tcs > 1) {
/* set configuration of DCB in vt mode and DCB in non-vt mode */
get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, pfc_en, prio_tc, prio_tc_en);
@@ -4267,29 +4301,6 @@ init_port_dcb_config(portid_t pid,
return -1;
}
- if (num_tcs > 1 && keep_qnum == 0) {
- /* Assume the ports in testpmd have the same dcb capability
- * and has the same number of rxq and txq in dcb mode
- */
- if (dcb_mode == DCB_VT_ENABLED) {
- if (rte_port->dev_info.max_vfs > 0) {
- nb_rxq = rte_port->dev_info.nb_rx_queues;
- nb_txq = rte_port->dev_info.nb_tx_queues;
- } else {
- nb_rxq = rte_port->dev_info.max_rx_queues;
- nb_txq = rte_port->dev_info.max_tx_queues;
- }
- } else {
- /*if vt is disabled, use all pf queues */
- if (rte_port->dev_info.vmdq_pool_base == 0) {
- nb_rxq = rte_port->dev_info.max_rx_queues;
- nb_txq = rte_port->dev_info.max_tx_queues;
- } else {
- nb_rxq = (queueid_t)num_tcs;
- nb_txq = (queueid_t)num_tcs;
- }
- }
- }
rx_free_thresh = 64;
memcpy(&rte_port->dev_conf, &port_conf, sizeof(struct rte_eth_conf));
diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index ecde00182f..27559bbe18 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -3846,7 +3846,7 @@ ice_dev_configure(struct rte_eth_dev *dev)
struct rte_eth_dcb_conf *tx_dcb_conf =
&dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
int i;
- int nb_tc_used_rx, nb_tc_used_tx, queues_per_tc;
+ int nb_tc_used_rx, nb_tc_used_tx;
uint16_t total_q_nb;
nb_tc_used_rx = check_dcb_conf(ice_get_port_max_cgd(hw) == ICE_4_CGD_PER_PORT,
@@ -3865,19 +3865,23 @@ ice_dev_configure(struct rte_eth_dev *dev)
}
total_q_nb = dev->data->nb_rx_queues;
- queues_per_tc = total_q_nb / nb_tc_used_rx;
- if (total_q_nb % nb_tc_used_rx != 0) {
- PMD_DRV_LOG(ERR, "For DCB, number of queues must be evenly divisble by number of used TCs");
- return -EINVAL;
- } else if (!rte_is_power_of_2(queues_per_tc)) {
- PMD_DRV_LOG(ERR, "For DCB, number of queues per TC must be a power of 2");
- return -EINVAL;
- }
-
+ struct rte_eth_dcb_tc_queue_mapping *q_map = &dev->data->dev_conf.q_map;
for (i = 0; i < nb_tc_used_rx; i++) {
+ if (q_map->tc_rxq[0][i].nb_queue != 0 &&
+ !rte_is_power_of_2(q_map->tc_rxq[0][i].nb_queue)) {
+ PMD_DRV_LOG(ERR, "For DCB, number of queues per TC must be a power of 2");
+ return -EINVAL;
+ }
+ if ((q_map->tc_rxq[0][i].base + q_map->tc_rxq[0][i].nb_queue) > total_q_nb) {
+ PMD_DRV_LOG(ERR, "Queue range for TC %d exceeds total number of queues",
+ i);
+ return -EINVAL;
+ }
ctxt.info.tc_mapping[i] =
- rte_cpu_to_le_16(((i * queues_per_tc) << ICE_AQ_VSI_TC_Q_OFFSET_S) |
- (rte_log2_u32(queues_per_tc) << ICE_AQ_VSI_TC_Q_NUM_S));
+ rte_cpu_to_le_16((q_map->tc_rxq[0][i].base <<
+ ICE_AQ_VSI_TC_Q_OFFSET_S) |
+ (rte_log2_u32(q_map->tc_rxq[0][i].nb_queue) <<
+ ICE_AQ_VSI_TC_Q_NUM_S));
}
memset(local_dcb_conf, 0, sizeof(*local_dcb_conf));
@@ -3941,6 +3945,7 @@ ice_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
struct ice_dcbx_cfg *dcb_conf = &qos_cfg->local_dcbx_cfg;
struct ice_vsi *vsi = pf->main_vsi;
struct ice_vsi_ctx ctxt = { 0 };
+ struct rte_eth_dcb_tc_queue_mapping *q_map = &dev->data->dev_conf.q_map;
ctxt.info = vsi->info;
if (rte_le_to_cpu_16(ctxt.info.mapping_flags) == ICE_AQ_VSI_Q_MAP_NONCONTIG) {
@@ -3953,13 +3958,11 @@ ice_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
dcb_info->prio_tc[i] = dcb_conf->etscfg.prio_table[i];
dcb_info->tc_bws[i] = dcb_conf->etscfg.tcbwtable[i];
/* Using VMDQ pool zero since DCB+VMDQ is not supported */
- uint16_t tc_rx_q_map = rte_le_to_cpu_16(ctxt.info.tc_mapping[i]);
- dcb_info->tc_queue.tc_rxq[0][i].base = tc_rx_q_map & ICE_AQ_VSI_TC_Q_OFFSET_M;
- dcb_info->tc_queue.tc_rxq[0][i].nb_queue =
- 1 << ((tc_rx_q_map & ICE_AQ_VSI_TC_Q_NUM_M) >> ICE_AQ_VSI_TC_Q_NUM_S);
+ dcb_info->tc_queue.tc_rxq[0][i].base = q_map->tc_rxq[0][i].base;
+ dcb_info->tc_queue.tc_rxq[0][i].nb_queue = q_map->tc_rxq[0][i].nb_queue;
- dcb_info->tc_queue.tc_txq[0][i].base = dcb_info->tc_queue.tc_rxq[0][i].base;
- dcb_info->tc_queue.tc_txq[0][i].nb_queue = dcb_info->tc_queue.tc_rxq[0][i].nb_queue;
+ dcb_info->tc_queue.tc_txq[0][i].base = q_map->tc_txq[0][i].base;
+ dcb_info->tc_queue.tc_txq[0][i].nb_queue = q_map->tc_txq[0][i].nb_queue;
}
return 0;
diff --git a/drivers/net/intel/ice/ice_rxtx.c b/drivers/net/intel/ice/ice_rxtx.c
index 451816affd..55424e7a23 100644
--- a/drivers/net/intel/ice/ice_rxtx.c
+++ b/drivers/net/intel/ice/ice_rxtx.c
@@ -796,6 +796,7 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
int buf_len;
struct ice_adapter *ad = ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
u16 q_base, q_range, cgd_idx = 0;
+ struct rte_eth_dcb_tc_queue_mapping *q_map = &dev->data->dev_conf.q_map;
PMD_INIT_FUNC_TRACE();
@@ -840,22 +841,22 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
tx_ctx.legacy_int = 1; /* Legacy or Advanced Host Interface */
tx_ctx.tsyn_ena = 1;
- /* Mirror RXQ<->CGD association to TXQ<->CDG */
- for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
- q_base = rte_le_to_cpu_16(vsi->info.tc_mapping[i]) & ICE_AQ_VSI_TC_Q_OFFSET_M;
- q_range = 1 << ((rte_le_to_cpu_16(vsi->info.tc_mapping[i]) &
- ICE_AQ_VSI_TC_Q_NUM_M) >> ICE_AQ_VSI_TC_Q_NUM_S);
+ if (dev->data->dev_conf.txmode.mq_mode == RTE_ETH_MQ_TX_DCB) {
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
+ q_base = q_map->tc_txq[0][i].base;
+ q_range = q_map->tc_txq[0][i].nb_queue;
- if (q_base <= tx_queue_id && tx_queue_id < q_base + q_range)
- break;
+ if (q_base <= tx_queue_id && tx_queue_id < q_base + q_range)
+ break;
- cgd_idx++;
- }
+ cgd_idx++;
+ }
- if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
- PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
- rte_free(txq_elem);
- return -EINVAL;
+ if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
+ PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
+ rte_free(txq_elem);
+ return -EINVAL;
+ }
}
tx_ctx.cgd_num = cgd_idx;
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index c220760043..0bd86e1e7d 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -1472,6 +1472,26 @@ struct rte_eth_intr_conf {
#define rte_intr_conf rte_eth_intr_conf
+#define RTE_ETH_DCB_NUM_TCS 8
+#define RTE_ETH_MAX_VMDQ_POOL 64
+
+/**
+ * A structure used to get the information of queue and
+ * TC mapping on both Tx and Rx paths.
+ */
+struct rte_eth_dcb_tc_queue_mapping {
+ /** Rx queues assigned to tc per Pool */
+ struct {
+ uint16_t base;
+ uint16_t nb_queue;
+ } tc_rxq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
+ /** Rx queues assigned to tc per Pool */
+ struct {
+ uint16_t base;
+ uint16_t nb_queue;
+ } tc_txq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
+};
+
/**
* A structure used to configure an Ethernet port.
* Depending upon the Rx multi-queue mode, extra advanced
@@ -1492,18 +1512,21 @@ struct rte_eth_conf {
Read the datasheet of given Ethernet controller
for details. The possible values of this field
are defined in implementation of each driver. */
+ struct rte_eth_dcb_tc_queue_mapping q_map;
struct {
struct rte_eth_rss_conf rss_conf; /**< Port RSS configuration */
/** Port DCB Rx configuration. */
struct rte_eth_dcb_conf dcb_rx_conf;
/** Port VMDq Rx configuration. */
struct rte_eth_vmdq_rx_conf vmdq_rx_conf;
+ /* VMDQ and DCB Rx queue mapping configuration. */
} rx_adv_conf; /**< Port Rx filtering configuration. */
struct {
/** Port DCB Tx configuration. */
struct rte_eth_dcb_conf dcb_tx_conf;
/** Port VMDq Tx configuration. */
struct rte_eth_vmdq_tx_conf vmdq_tx_conf;
+ /* VMDQ and DCB Tx queue mapping configuration. */
} tx_adv_conf; /**< Port Tx DCB configuration (union). */
/** Currently,Priority Flow Control(PFC) are supported,if DCB with PFC
is needed,and the variable must be set RTE_ETH_DCB_PFC_SUPPORT. */
@@ -1930,26 +1953,6 @@ struct rte_eth_xstat_name {
char name[RTE_ETH_XSTATS_NAME_SIZE]; /**< The statistic name. */
};
-#define RTE_ETH_DCB_NUM_TCS 8
-#define RTE_ETH_MAX_VMDQ_POOL 64
-
-/**
- * A structure used to get the information of queue and
- * TC mapping on both Tx and Rx paths.
- */
-struct rte_eth_dcb_tc_queue_mapping {
- /** Rx queues assigned to tc per Pool */
- struct {
- uint16_t base;
- uint16_t nb_queue;
- } tc_rxq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
- /** Rx queues assigned to tc per Pool */
- struct {
- uint16_t base;
- uint16_t nb_queue;
- } tc_txq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
-};
-
/**
* A structure used to get the information of DCB.
* It includes TC UP mapping and queue TC mapping.
--
2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFC PATCH 5/6] ethdev: remove dcb_capability_en from rte_eth_conf
2025-08-30 17:17 [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Vladimir Medvedkin
` (3 preceding siblings ...)
2025-08-30 17:17 ` [RFC PATCH 4/6] ethdev: extend VMDq/DCB configuration with queue mapping Vladimir Medvedkin
@ 2025-08-30 17:17 ` Vladimir Medvedkin
2025-08-30 20:46 ` Ivan Malov
2025-08-30 20:49 ` Ivan Malov
2025-08-30 17:17 ` [RFC PATCH 6/6] ethdev: move mq_mode to [r,t]x_adv_conf Vladimir Medvedkin
2025-08-30 21:13 ` [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Ivan Malov
6 siblings, 2 replies; 18+ messages in thread
From: Vladimir Medvedkin @ 2025-08-30 17:17 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko, stephen
Currently there are DCB configuration capability flags that are suppose
to enable DCB Priority Groups (aka Traffic Classes), and Priority Flow
Control. The former is not used anywhere at all, while the latter us used
in some drivers, but is used to enable PFC on all existing Traffic
Classes, which feels like a questionable design choice.
It is recommended to use existing API to enable PFC on specific Traffic
Class.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
app/test-pmd/cmdline.c | 19 +++----------------
app/test-pmd/testpmd.c | 12 ++----------
app/test-pmd/testpmd.h | 1 -
lib/ethdev/rte_ethdev.h | 8 --------
4 files changed, 5 insertions(+), 35 deletions(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 82322f3456..346dd7c133 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -3526,7 +3526,6 @@ parse_dcb_token_find(char *split_str[], int split_num, int *param_num)
static int
parse_dcb_token_value(char *token_str,
- uint8_t *pfc_en,
uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES],
uint8_t *prio_tc_en,
uint8_t *keep_qnum)
@@ -3549,17 +3548,6 @@ parse_dcb_token_value(char *token_str,
split_str[split_num++] = token;
} while (1);
- /* parse fixed parameter "pfc-en" first. */
- token = split_str[0];
- if (strcmp(token, "on") == 0)
- *pfc_en = 1;
- else if (strcmp(token, "off") == 0)
- *pfc_en = 0;
- else {
- fprintf(stderr, "Bad Argument: pfc-en must be on or off\n");
- return -EINVAL;
- }
-
if (split_num == 1)
return 0;
@@ -3612,7 +3600,6 @@ cmd_config_dcb_parsed(void *parsed_result,
uint8_t prio_tc_en = 0;
uint8_t keep_qnum = 0;
struct rte_port *port;
- uint8_t pfc_en = 0;
int ret;
if (port_id_is_invalid(port_id, ENABLED_WARN))
@@ -3644,7 +3631,7 @@ cmd_config_dcb_parsed(void *parsed_result,
return;
}
- ret = parse_dcb_token_value(res->token_str, &pfc_en, prio_tc, &prio_tc_en, &keep_qnum);
+ ret = parse_dcb_token_value(res->token_str, prio_tc, &prio_tc_en, &keep_qnum);
if (ret != 0)
return;
@@ -3652,11 +3639,11 @@ cmd_config_dcb_parsed(void *parsed_result,
if (!strncmp(res->vt_en, "on", 2))
ret = init_port_dcb_config(port_id, DCB_VT_ENABLED,
(int)res->num_tcs,
- pfc_en, prio_tc, prio_tc_en, keep_qnum);
+ prio_tc, prio_tc_en, keep_qnum);
else
ret = init_port_dcb_config(port_id, DCB_ENABLED,
(int)res->num_tcs,
- pfc_en, prio_tc, prio_tc_en, keep_qnum);
+ prio_tc, prio_tc_en, keep_qnum);
if (ret != 0) {
fprintf(stderr, "Cannot initialize network ports.\n");
return;
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 3a55434d44..8602781aac 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -4093,8 +4093,7 @@ const uint16_t vlan_tags[] = {
static void
get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
- int num_tcs, uint8_t pfc_en,
- uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES], uint8_t prio_tc_en)
+ int num_tcs, uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES], uint8_t prio_tc_en)
{
uint8_t dcb_tc_val, i;
@@ -4195,11 +4194,6 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
eth_conf->txmode.mq_mode = RTE_ETH_MQ_TX_DCB;
}
- if (pfc_en)
- eth_conf->dcb_capability_en =
- RTE_ETH_DCB_PG_SUPPORT | RTE_ETH_DCB_PFC_SUPPORT;
- else
- eth_conf->dcb_capability_en = RTE_ETH_DCB_PG_SUPPORT;
}
static void
@@ -4209,7 +4203,6 @@ clear_eth_dcb_conf(portid_t pid, struct rte_eth_conf *eth_conf)
eth_conf->rxmode.mq_mode &= ~(RTE_ETH_MQ_RX_DCB | RTE_ETH_MQ_RX_VMDQ_DCB);
eth_conf->txmode.mq_mode = RTE_ETH_MQ_TX_NONE;
- eth_conf->dcb_capability_en = 0;
if (dcb_config) {
/* Unset VLAN filter configuration if already config DCB. */
eth_conf->rxmode.offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
@@ -4222,7 +4215,6 @@ int
init_port_dcb_config(portid_t pid,
enum dcb_mode_enable dcb_mode,
int num_tcs,
- uint8_t pfc_en,
uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES],
uint8_t prio_tc_en,
uint8_t keep_qnum)
@@ -4267,7 +4259,7 @@ init_port_dcb_config(portid_t pid,
if (num_tcs > 1) {
/* set configuration of DCB in vt mode and DCB in non-vt mode */
- get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, pfc_en, prio_tc, prio_tc_en);
+ get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, prio_tc, prio_tc_en);
port_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
/* remove RSS HASH offload for DCB in vt mode */
if (port_conf.rxmode.mq_mode == RTE_ETH_MQ_RX_VMDQ_DCB) {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 4ff982ed3f..bb1aaec918 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -1151,7 +1151,6 @@ uint8_t port_is_bonding_member(portid_t member_pid);
int init_port_dcb_config(portid_t pid, enum dcb_mode_enable dcb_mode,
int num_tcs,
- uint8_t pfc_en,
uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES],
uint8_t prio_tc_en,
uint8_t keep_qnum);
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index 0bd86e1e7d..60532e0155 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -858,11 +858,6 @@ rte_eth_rss_hf_refine(uint64_t rss_hf)
#define RTE_ETH_DCB_NUM_QUEUES 128 /**< Maximum nb. of DCB queues. */
/**@}*/
-/**@{@name DCB capabilities */
-#define RTE_ETH_DCB_PG_SUPPORT RTE_BIT32(0) /**< Priority Group(ETS) support. */
-#define RTE_ETH_DCB_PFC_SUPPORT RTE_BIT32(1) /**< Priority Flow Control support. */
-/**@}*/
-
/**@{@name VLAN offload bits */
#define RTE_ETH_VLAN_STRIP_OFFLOAD 0x0001 /**< VLAN Strip On/Off */
#define RTE_ETH_VLAN_FILTER_OFFLOAD 0x0002 /**< VLAN Filter On/Off */
@@ -1528,9 +1523,6 @@ struct rte_eth_conf {
struct rte_eth_vmdq_tx_conf vmdq_tx_conf;
/* VMDQ and DCB Tx queue mapping configuration. */
} tx_adv_conf; /**< Port Tx DCB configuration (union). */
- /** Currently,Priority Flow Control(PFC) are supported,if DCB with PFC
- is needed,and the variable must be set RTE_ETH_DCB_PFC_SUPPORT. */
- uint32_t dcb_capability_en;
struct rte_eth_intr_conf intr_conf; /**< Interrupt mode configuration. */
};
--
2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFC PATCH 6/6] ethdev: move mq_mode to [r,t]x_adv_conf
2025-08-30 17:17 [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Vladimir Medvedkin
` (4 preceding siblings ...)
2025-08-30 17:17 ` [RFC PATCH 5/6] ethdev: remove dcb_capability_en from rte_eth_conf Vladimir Medvedkin
@ 2025-08-30 17:17 ` Vladimir Medvedkin
2025-08-30 21:13 ` [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Ivan Malov
6 siblings, 0 replies; 18+ messages in thread
From: Vladimir Medvedkin @ 2025-08-30 17:17 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko, stephen
Currently mq_mode for Rx and Tx side is located inside
rte_eth_[r,t]xmode. This seems questionable, because most of the
information in that structure is not related to anything multiqueue, and
advanced Rx/Tx configuration seems like a better place to put it. Also,
change type from enum to uint32_t to make it explicit that VMDq/DCB
configuration can be used independently from each other, which implies a
flag field and not an enum.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
app/graph/ethdev.c | 6 +--
app/test-eventdev/test_perf_common.c | 4 +-
app/test-eventdev/test_pipeline_common.c | 4 +-
app/test-pipeline/init.c | 2 +-
app/test-pmd/parameters.c | 4 +-
app/test-pmd/testpmd.c | 27 ++++++-------
app/test-pmd/testpmd.h | 2 +-
app/test/test_event_eth_rx_adapter.c | 4 +-
app/test/test_link_bonding.c | 4 +-
| 8 ++--
app/test/test_pmd_perf.c | 4 +-
app/test/test_security_inline_macsec.c | 12 ++++--
app/test/test_security_inline_proto.c | 12 ++++--
drivers/net/intel/ice/ice_dcf.c | 2 +-
drivers/net/intel/ice/ice_dcf_ethdev.c | 2 +-
drivers/net/intel/ice/ice_ethdev.c | 8 ++--
lib/ethdev/ethdev_trace.h | 4 +-
lib/ethdev/rte_ethdev.c | 10 ++---
lib/ethdev/rte_ethdev.h | 48 +++++++++---------------
19 files changed, 77 insertions(+), 90 deletions(-)
diff --git a/app/graph/ethdev.c b/app/graph/ethdev.c
index 2f4cf65c96..42739a4267 100644
--- a/app/graph/ethdev.c
+++ b/app/graph/ethdev.c
@@ -44,17 +44,17 @@ cmd_ethdev_forward_help[] = "ethdev forward <tx_dev_name> <rx_dev_name>";
static struct rte_eth_conf port_conf_default = {
.link_speeds = 0,
.rxmode = {
- .mq_mode = RTE_ETH_MQ_RX_NONE,
.mtu = 9000 - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN), /* Jumbo frame MTU */
},
.rx_adv_conf = {
+ .mq_mode = RTE_ETH_MQ_RX_NONE,
.rss_conf = {
.rss_key = NULL,
.rss_key_len = 40,
.rss_hf = 0,
},
},
- .txmode = {
+ .tx_adv_conf = {
.mq_mode = RTE_ETH_MQ_TX_NONE,
},
.lpbk_mode = 0,
@@ -426,7 +426,7 @@ ethdev_process(const char *name, struct ethdev_config *params)
if (rss) {
uint64_t rss_hf = RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP;
- port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS;
+ port_conf.rx_adv_conf.mq_mode = RTE_ETH_MQ_RX_RSS;
port_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf & port_info.flow_type_rss_offloads;
}
diff --git a/app/test-eventdev/test_perf_common.c b/app/test-eventdev/test_perf_common.c
index f77557e765..c79a733cc9 100644
--- a/app/test-eventdev/test_perf_common.c
+++ b/app/test-eventdev/test_perf_common.c
@@ -1884,10 +1884,8 @@ perf_ethdev_setup(struct evt_test *test, struct evt_options *opt)
int ret;
struct test_perf *t = evt_test_priv(test);
struct rte_eth_conf port_conf = {
- .rxmode = {
- .mq_mode = RTE_ETH_MQ_RX_RSS,
- },
.rx_adv_conf = {
+ .mq_mode = RTE_ETH_MQ_RX_RSS,
.rss_conf = {
.rss_key = NULL,
.rss_hf = RTE_ETH_RSS_IP,
diff --git a/app/test-eventdev/test_pipeline_common.c b/app/test-eventdev/test_pipeline_common.c
index c1382ac188..7c2cfdc9de 100644
--- a/app/test-eventdev/test_pipeline_common.c
+++ b/app/test-eventdev/test_pipeline_common.c
@@ -313,10 +313,8 @@ pipeline_ethdev_setup(struct evt_test *test, struct evt_options *opt)
struct test_pipeline *t = evt_test_priv(test);
struct rte_eth_rxconf rx_conf;
struct rte_eth_conf port_conf = {
- .rxmode = {
- .mq_mode = RTE_ETH_MQ_RX_RSS,
- },
.rx_adv_conf = {
+ .mq_mode = RTE_ETH_MQ_RX_RSS,
.rss_conf = {
.rss_key = NULL,
.rss_hf = RTE_ETH_RSS_IP,
diff --git a/app/test-pipeline/init.c b/app/test-pipeline/init.c
index 558f0e428d..35917dec76 100644
--- a/app/test-pipeline/init.c
+++ b/app/test-pipeline/init.c
@@ -76,7 +76,7 @@ static struct rte_eth_conf port_conf = {
.rss_hf = RTE_ETH_RSS_IP,
},
},
- .txmode = {
+ .tx_adv_conf = {
.mq_mode = RTE_ETH_MQ_TX_NONE,
},
};
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 1132972913..4de514ecf7 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -1713,8 +1713,8 @@ launch_args_parse(int argc, char** argv)
char *end = NULL;
n = strtoul(optarg, &end, 16);
- if (n >= 0 && n <= RTE_ETH_MQ_RX_VMDQ_DCB_RSS)
- rx_mq_mode = (enum rte_eth_rx_mq_mode)n;
+ if (n >= 0 && n <= (int)RTE_ETH_MQ_RX_VMDQ_DCB_RSS)
+ rx_mq_mode = n;
else
rte_exit(EXIT_FAILURE,
"rx-mq-mode must be >= 0 and <= %d\n",
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 8602781aac..3f1ab6ce5a 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -544,7 +544,7 @@ uint8_t gro_flush_cycles = GRO_DEFAULT_FLUSH_CYCLES;
/*
* hexadecimal bitmask of RX mq mode can be enabled.
*/
-enum rte_eth_rx_mq_mode rx_mq_mode = RTE_ETH_MQ_RX_VMDQ_DCB_RSS;
+uint32_t rx_mq_mode = RTE_ETH_MQ_RX_VMDQ_DCB_RSS;
/*
* Used to set forced link speed
@@ -4018,11 +4018,10 @@ init_port_config(void)
if (port->dcb_flag == 0) {
if (port->dev_conf.rx_adv_conf.rss_conf.rss_hf != 0) {
- port->dev_conf.rxmode.mq_mode =
- (enum rte_eth_rx_mq_mode)
- (rx_mq_mode & RTE_ETH_MQ_RX_RSS);
+ port->dev_conf.rx_adv_conf.mq_mode =
+ (rx_mq_mode & RTE_ETH_MQ_RX_RSS);
} else {
- port->dev_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE;
+ port->dev_conf.rx_adv_conf.mq_mode = RTE_ETH_MQ_RX_NONE;
port->dev_conf.rxmode.offloads &=
~RTE_ETH_RX_OFFLOAD_RSS_HASH;
@@ -4147,10 +4146,8 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
}
/* set DCB mode of RX and TX of multiple queues */
- eth_conf->rxmode.mq_mode =
- (enum rte_eth_rx_mq_mode)
- (rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_DCB);
- eth_conf->txmode.mq_mode = RTE_ETH_MQ_TX_VMDQ_DCB;
+ eth_conf->rx_adv_conf.mq_mode = (rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_DCB);
+ eth_conf->tx_adv_conf.mq_mode = RTE_ETH_MQ_TX_VMDQ_DCB;
} else {
struct rte_eth_dcb_conf *rx_conf =
ð_conf->rx_adv_conf.dcb_rx_conf;
@@ -4188,10 +4185,8 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
tx_conf->dcb_tc_bw[i]++;
}
- eth_conf->rxmode.mq_mode =
- (enum rte_eth_rx_mq_mode)
- (rx_mq_mode & RTE_ETH_MQ_RX_DCB_RSS);
- eth_conf->txmode.mq_mode = RTE_ETH_MQ_TX_DCB;
+ eth_conf->rx_adv_conf.mq_mode = (rx_mq_mode & RTE_ETH_MQ_RX_DCB_RSS);
+ eth_conf->tx_adv_conf.mq_mode = RTE_ETH_MQ_TX_DCB;
}
}
@@ -4201,8 +4196,8 @@ clear_eth_dcb_conf(portid_t pid, struct rte_eth_conf *eth_conf)
{
uint32_t i;
- eth_conf->rxmode.mq_mode &= ~(RTE_ETH_MQ_RX_DCB | RTE_ETH_MQ_RX_VMDQ_DCB);
- eth_conf->txmode.mq_mode = RTE_ETH_MQ_TX_NONE;
+ eth_conf->rx_adv_conf.mq_mode &= ~(RTE_ETH_MQ_RX_DCB | RTE_ETH_MQ_RX_VMDQ_DCB);
+ eth_conf->tx_adv_conf.mq_mode = RTE_ETH_MQ_TX_NONE;
if (dcb_config) {
/* Unset VLAN filter configuration if already config DCB. */
eth_conf->rxmode.offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
@@ -4262,7 +4257,7 @@ init_port_dcb_config(portid_t pid,
get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, prio_tc, prio_tc_en);
port_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
/* remove RSS HASH offload for DCB in vt mode */
- if (port_conf.rxmode.mq_mode == RTE_ETH_MQ_RX_VMDQ_DCB) {
+ if (port_conf.rx_adv_conf.mq_mode == RTE_ETH_MQ_RX_VMDQ_DCB) {
port_conf.rxmode.offloads &= ~RTE_ETH_RX_OFFLOAD_RSS_HASH;
for (i = 0; i < nb_rxq; i++)
rte_port->rxq[i].conf.offloads &=
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index bb1aaec918..4f87a6147f 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -814,7 +814,7 @@ struct mplsoudp_decap_conf {
};
extern struct mplsoudp_decap_conf mplsoudp_decap_conf;
-extern enum rte_eth_rx_mq_mode rx_mq_mode;
+extern uint32_t rx_mq_mode;
extern struct rte_flow_action_conntrack conntrack_context;
diff --git a/app/test/test_event_eth_rx_adapter.c b/app/test/test_event_eth_rx_adapter.c
index 9f8c8c1b26..f7d94790af 100644
--- a/app/test/test_event_eth_rx_adapter.c
+++ b/app/test/test_event_eth_rx_adapter.c
@@ -123,7 +123,7 @@ static inline int
port_init_rx_intr(uint16_t port, struct rte_mempool *mp)
{
static const struct rte_eth_conf port_conf_default = {
- .rxmode = {
+ .rx_adv_conf = {
.mq_mode = RTE_ETH_MQ_RX_NONE,
},
.intr_conf = {
@@ -138,7 +138,7 @@ static inline int
port_init(uint16_t port, struct rte_mempool *mp)
{
static const struct rte_eth_conf port_conf_default = {
- .rxmode = {
+ .rx_adv_conf = {
.mq_mode = RTE_ETH_MQ_RX_NONE,
},
};
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 19b064771a..50b7e18f0e 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -135,10 +135,10 @@ static uint16_t dst_port_1 = 2024;
static uint16_t vlan_id = 0x100;
static struct rte_eth_conf default_pmd_conf = {
- .rxmode = {
+ .rx_adv_conf = {
.mq_mode = RTE_ETH_MQ_RX_NONE,
},
- .txmode = {
+ .tx_adv_conf = {
.mq_mode = RTE_ETH_MQ_TX_NONE,
},
.lpbk_mode = 0,
--git a/app/test/test_link_bonding_rssconf.c b/app/test/test_link_bonding_rssconf.c
index 2cb689b1de..b16380fb34 100644
--- a/app/test/test_link_bonding_rssconf.c
+++ b/app/test/test_link_bonding_rssconf.c
@@ -79,20 +79,20 @@ static struct link_bonding_rssconf_unittest_params test_params = {
* Default port configuration with RSS turned off
*/
static struct rte_eth_conf default_pmd_conf = {
- .rxmode = {
+ .rx_adv_conf = {
.mq_mode = RTE_ETH_MQ_RX_NONE,
},
- .txmode = {
+ .tx_adv_conf = {
.mq_mode = RTE_ETH_MQ_TX_NONE,
},
.lpbk_mode = 0,
};
static struct rte_eth_conf rss_pmd_conf = {
- .rxmode = {
+ .rx_adv_conf = {
.mq_mode = RTE_ETH_MQ_RX_RSS,
},
- .txmode = {
+ .tx_adv_conf = {
.mq_mode = RTE_ETH_MQ_TX_NONE,
},
.rx_adv_conf = {
diff --git a/app/test/test_pmd_perf.c b/app/test/test_pmd_perf.c
index 995b0a6f20..58943d5294 100644
--- a/app/test/test_pmd_perf.c
+++ b/app/test/test_pmd_perf.c
@@ -60,10 +60,10 @@ static struct rte_mempool *mbufpool[NB_SOCKETS];
static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
static struct rte_eth_conf port_conf = {
- .rxmode = {
+ .rx_adv_conf = {
.mq_mode = RTE_ETH_MQ_RX_NONE,
},
- .txmode = {
+ .tx_adv_conf = {
.mq_mode = RTE_ETH_MQ_TX_NONE,
},
.lpbk_mode = 1, /* enable loopback */
diff --git a/app/test/test_security_inline_macsec.c b/app/test/test_security_inline_macsec.c
index 4043667701..4385343d41 100644
--- a/app/test/test_security_inline_macsec.c
+++ b/app/test/test_security_inline_macsec.c
@@ -78,14 +78,18 @@ struct mcs_test_opts {
static struct rte_eth_conf port_conf = {
.rxmode = {
- .mq_mode = RTE_ETH_MQ_RX_NONE,
.offloads = RTE_ETH_RX_OFFLOAD_CHECKSUM |
- RTE_ETH_RX_OFFLOAD_MACSEC_STRIP,
+ RTE_ETH_RX_OFFLOAD_MACSEC_STRIP,
+ },
+ .rx_adv_conf = {
+ .mq_mode = RTE_ETH_MQ_RX_NONE,
},
.txmode = {
- .mq_mode = RTE_ETH_MQ_TX_NONE,
.offloads = RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
- RTE_ETH_TX_OFFLOAD_MACSEC_INSERT,
+ RTE_ETH_TX_OFFLOAD_MACSEC_INSERT,
+ },
+ .tx_adv_conf = {
+ .mq_mode = RTE_ETH_MQ_TX_NONE,
},
.lpbk_mode = 1, /* enable loopback */
};
diff --git a/app/test/test_security_inline_proto.c b/app/test/test_security_inline_proto.c
index 04ecfd02c6..01e3b0a9cb 100644
--- a/app/test/test_security_inline_proto.c
+++ b/app/test/test_security_inline_proto.c
@@ -88,14 +88,18 @@ static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
static struct rte_eth_conf port_conf = {
.rxmode = {
- .mq_mode = RTE_ETH_MQ_RX_NONE,
.offloads = RTE_ETH_RX_OFFLOAD_CHECKSUM |
- RTE_ETH_RX_OFFLOAD_SECURITY,
+ RTE_ETH_RX_OFFLOAD_SECURITY,
+ },
+ .rx_adv_conf = {
+ .mq_mode = RTE_ETH_MQ_RX_NONE,
},
.txmode = {
- .mq_mode = RTE_ETH_MQ_TX_NONE,
.offloads = RTE_ETH_TX_OFFLOAD_SECURITY |
- RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE,
+ RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE,
+ },
+ .tx_adv_conf = {
+ .mq_mode = RTE_ETH_MQ_TX_NONE,
},
.lpbk_mode = 1, /* enable loopback */
};
diff --git a/drivers/net/intel/ice/ice_dcf.c b/drivers/net/intel/ice/ice_dcf.c
index 51716a4d5b..363d0ed598 100644
--- a/drivers/net/intel/ice/ice_dcf.c
+++ b/drivers/net/intel/ice/ice_dcf.c
@@ -1113,7 +1113,7 @@ ice_dcf_init_rss(struct ice_dcf_hw *hw)
PMD_DRV_LOG(DEBUG, "RSS is not supported");
return -ENOTSUP;
}
- if (dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_RSS) {
+ if (dev->data->dev_conf.rx_adv_conf.mq_mode != RTE_ETH_MQ_RX_RSS) {
PMD_DRV_LOG(WARNING, "RSS is enabled by PF by default");
/* set all lut items to default queue */
memset(hw->rss_lut, 0, hw->vf_res->rss_lut_size);
diff --git a/drivers/net/intel/ice/ice_dcf_ethdev.c b/drivers/net/intel/ice/ice_dcf_ethdev.c
index 499062be40..bd929b9f1f 100644
--- a/drivers/net/intel/ice/ice_dcf_ethdev.c
+++ b/drivers/net/intel/ice/ice_dcf_ethdev.c
@@ -709,7 +709,7 @@ ice_dcf_dev_configure(struct rte_eth_dev *dev)
ad->rx_bulk_alloc_allowed = true;
ad->tx_simple_allowed = true;
- if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
+ if (dev->data->dev_conf.rx_adv_conf.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
return 0;
diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index 27559bbe18..8234b35d10 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -2888,8 +2888,8 @@ ice_deinit_dcb(struct rte_eth_dev *dev)
u8 max_tcs = local_dcb_conf->etscfg.maxtcs;
u8 tc;
- if (!(dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_DCB_FLAG ||
- dev->data->dev_conf.txmode.mq_mode == RTE_ETH_MQ_TX_DCB))
+ if (!(dev->data->dev_conf.rx_adv_conf.mq_mode & RTE_ETH_MQ_RX_DCB_FLAG ||
+ dev->data->dev_conf.tx_adv_conf.mq_mode == RTE_ETH_MQ_TX_DCB))
return;
for (i = 0; i < max_tcs; i++) {
@@ -3823,7 +3823,7 @@ ice_dev_configure(struct rte_eth_dev *dev)
ad->rx_bulk_alloc_allowed = true;
ad->tx_simple_allowed = true;
- if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
+ if (dev->data->dev_conf.rx_adv_conf.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
if (dev->data->nb_rx_queues) {
@@ -3834,7 +3834,7 @@ ice_dev_configure(struct rte_eth_dev *dev)
}
}
- if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
+ if (dev->data->dev_conf.rx_adv_conf.mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
struct ice_hw *hw = ICE_PF_TO_HW(pf);
struct ice_vsi *vsi = pf->main_vsi;
struct ice_port_info *port_info = hw->port_info;
diff --git a/lib/ethdev/ethdev_trace.h b/lib/ethdev/ethdev_trace.h
index 482befc209..305ae4ba58 100644
--- a/lib/ethdev/ethdev_trace.h
+++ b/lib/ethdev/ethdev_trace.h
@@ -30,11 +30,11 @@ RTE_TRACE_POINT(
rte_trace_point_emit_u16(nb_rx_q);
rte_trace_point_emit_u16(nb_tx_q);
rte_trace_point_emit_u32(dev_conf->link_speeds);
- rte_trace_point_emit_u32(dev_conf->rxmode.mq_mode);
+ rte_trace_point_emit_u32(dev_conf->rx_adv_conf.mq_mode);
rte_trace_point_emit_u32(dev_conf->rxmode.mtu);
rte_trace_point_emit_u32(dev_conf->rxmode.max_lro_pkt_size);
rte_trace_point_emit_u64(dev_conf->rxmode.offloads);
- rte_trace_point_emit_u32(dev_conf->txmode.mq_mode);
+ rte_trace_point_emit_u32(dev_conf->tx_adv_conf.mq_mode);
rte_trace_point_emit_u64(dev_conf->txmode.offloads);
rte_trace_point_emit_u32(dev_conf->lpbk_mode);
rte_trace_point_emit_int(rc);
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index dd7c00bc94..3fc8030cd0 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -1547,7 +1547,7 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
}
/* Check if Rx RSS distribution is disabled but RSS hash is enabled. */
- if (((dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) == 0) &&
+ if (((dev_conf->rx_adv_conf.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) == 0) &&
(dev_conf->rxmode.offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH)) {
RTE_ETHDEV_LOG_LINE(ERR,
"Ethdev port_id=%u config invalid Rx mq_mode without RSS but %s offload is requested",
@@ -4916,7 +4916,7 @@ rte_eth_dev_rss_reta_update(uint16_t port_id,
struct rte_eth_rss_reta_entry64 *reta_conf,
uint16_t reta_size)
{
- enum rte_eth_rx_mq_mode mq_mode;
+ uint32_t mq_mode;
struct rte_eth_dev *dev;
int ret;
@@ -4948,7 +4948,7 @@ rte_eth_dev_rss_reta_update(uint16_t port_id,
if (ret < 0)
return ret;
- mq_mode = dev->data->dev_conf.rxmode.mq_mode;
+ mq_mode = dev->data->dev_conf.rx_adv_conf.mq_mode;
if (!(mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)) {
RTE_ETHDEV_LOG_LINE(ERR, "Multi-queue RSS mode isn't enabled.");
return -ENOTSUP;
@@ -5003,7 +5003,7 @@ rte_eth_dev_rss_hash_update(uint16_t port_id,
{
struct rte_eth_dev *dev;
struct rte_eth_dev_info dev_info = { .flow_type_rss_offloads = 0, };
- enum rte_eth_rx_mq_mode mq_mode;
+ uint32_t mq_mode;
int ret;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
@@ -5030,7 +5030,7 @@ rte_eth_dev_rss_hash_update(uint16_t port_id,
return -EINVAL;
}
- mq_mode = dev->data->dev_conf.rxmode.mq_mode;
+ mq_mode = dev->data->dev_conf.rx_adv_conf.mq_mode;
if (!(mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)) {
RTE_ETHDEV_LOG_LINE(ERR, "Multi-queue RSS mode isn't enabled.");
return -ENOTSUP;
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index 60532e0155..ae8cc5e8ba 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -377,7 +377,7 @@ struct rte_eth_thresh {
};
/**@{@name Multi-queue mode
- * @see rte_eth_conf.rxmode.mq_mode.
+ * @see rte_eth_conf.rx_adv_conf.mq_mode.
*/
#define RTE_ETH_MQ_RX_RSS_FLAG RTE_BIT32(0) /**< Enable RSS. @see rte_eth_rss_conf */
#define RTE_ETH_MQ_RX_DCB_FLAG RTE_BIT32(1) /**< Enable DCB. */
@@ -388,45 +388,32 @@ struct rte_eth_thresh {
* A set of values to identify what method is to be used to route
* packets to multiple queues.
*/
-enum rte_eth_rx_mq_mode {
- /** None of DCB, RSS or VMDq mode */
- RTE_ETH_MQ_RX_NONE = 0,
-
- /** For Rx side, only RSS is on */
- RTE_ETH_MQ_RX_RSS = RTE_ETH_MQ_RX_RSS_FLAG,
- /** For Rx side,only DCB is on. */
- RTE_ETH_MQ_RX_DCB = RTE_ETH_MQ_RX_DCB_FLAG,
- /** Both DCB and RSS enable */
- RTE_ETH_MQ_RX_DCB_RSS = RTE_ETH_MQ_RX_RSS_FLAG | RTE_ETH_MQ_RX_DCB_FLAG,
-
- /** Only VMDq, no RSS nor DCB */
- RTE_ETH_MQ_RX_VMDQ_ONLY = RTE_ETH_MQ_RX_VMDQ_FLAG,
- /** RSS mode with VMDq */
- RTE_ETH_MQ_RX_VMDQ_RSS = RTE_ETH_MQ_RX_RSS_FLAG | RTE_ETH_MQ_RX_VMDQ_FLAG,
- /** Use VMDq+DCB to route traffic to queues */
- RTE_ETH_MQ_RX_VMDQ_DCB = RTE_ETH_MQ_RX_VMDQ_FLAG | RTE_ETH_MQ_RX_DCB_FLAG,
- /** Enable both VMDq and DCB in VMDq */
- RTE_ETH_MQ_RX_VMDQ_DCB_RSS = RTE_ETH_MQ_RX_RSS_FLAG | RTE_ETH_MQ_RX_DCB_FLAG |
- RTE_ETH_MQ_RX_VMDQ_FLAG,
-};
+#define RTE_ETH_MQ_RX_NONE 0
+#define RTE_ETH_MQ_RX_RSS (RTE_ETH_MQ_RX_RSS_FLAG)
+#define RTE_ETH_MQ_RX_DCB (RTE_ETH_MQ_RX_DCB_FLAG)
+#define RTE_ETH_MQ_RX_VMDQ_ONLY (RTE_ETH_MQ_RX_VMDQ_FLAG)
+#define RTE_ETH_MQ_RX_DCB_RSS (RTE_ETH_MQ_RX_RSS_FLAG | RTE_ETH_MQ_RX_DCB_FLAG)
+#define RTE_ETH_MQ_RX_VMDQ_RSS (RTE_ETH_MQ_RX_RSS_FLAG | RTE_ETH_MQ_RX_VMDQ_FLAG)
+#define RTE_ETH_MQ_RX_VMDQ_DCB (RTE_ETH_MQ_RX_VMDQ_FLAG | RTE_ETH_MQ_RX_DCB_FLAG)
+#define RTE_ETH_MQ_RX_VMDQ_DCB_RSS (RTE_ETH_MQ_RX_RSS_FLAG|RTE_ETH_MQ_RX_DCB_FLAG| \
+ RTE_ETH_MQ_RX_VMDQ_FLAG)
+#define RTE_ETH_MQ_RX_FLAG_MASK RTE_ETH_MQ_RX_VMDQ_DCB_RSS
/**
* A set of values to identify what method is to be used to transmit
* packets using multi-TCs.
*/
-enum rte_eth_tx_mq_mode {
- RTE_ETH_MQ_TX_NONE = 0, /**< It is in neither DCB nor VT mode. */
- RTE_ETH_MQ_TX_DCB, /**< For Tx side,only DCB is on. */
- RTE_ETH_MQ_TX_VMDQ_DCB, /**< For Tx side,both DCB and VT is on. */
- RTE_ETH_MQ_TX_VMDQ_ONLY, /**< Only VT on, no DCB */
-};
+#define RTE_ETH_MQ_TX_NONE 0
+#define RTE_ETH_MQ_TX_DCB RTE_BIT32(0)
+#define RTE_ETH_MQ_TX_VMDQ RTE_BIT32(1)
+#define RTE_ETH_MQ_TX_VMDQ_DCB (RTE_ETH_MQ_TX_DCB|RTE_ETH_MQ_TX_VMDQ)
+#define RTE_ETH_MQ_TX_FLAG_MASK RTE_ETH_MQ_TX_VMDQ_DCB
/**
* A structure used to configure the Rx features of an Ethernet port.
*/
struct rte_eth_rxmode {
/** The multi-queue packet distribution mode to be used, e.g. RSS. */
- enum rte_eth_rx_mq_mode mq_mode;
uint32_t mtu; /**< Requested MTU. */
/** Maximum allowed size of LRO aggregated packet. */
uint32_t max_lro_pkt_size;
@@ -972,7 +959,6 @@ struct rte_eth_vmdq_rx_conf {
* A structure used to configure the Tx features of an Ethernet port.
*/
struct rte_eth_txmode {
- enum rte_eth_tx_mq_mode mq_mode; /**< Tx multi-queues mode. */
/**
* Per-port Tx offloads to be set using RTE_ETH_TX_OFFLOAD_* flags.
* Only offloads set on tx_offload_capa field on rte_eth_dev_info
@@ -1509,6 +1495,7 @@ struct rte_eth_conf {
are defined in implementation of each driver. */
struct rte_eth_dcb_tc_queue_mapping q_map;
struct {
+ uint32_t mq_mode; /**< Rx multi-queues mode. */
struct rte_eth_rss_conf rss_conf; /**< Port RSS configuration */
/** Port DCB Rx configuration. */
struct rte_eth_dcb_conf dcb_rx_conf;
@@ -1517,6 +1504,7 @@ struct rte_eth_conf {
/* VMDQ and DCB Rx queue mapping configuration. */
} rx_adv_conf; /**< Port Rx filtering configuration. */
struct {
+ uint32_t mq_mode; /**< Tx multi-queues mode. */
/** Port DCB Tx configuration. */
struct rte_eth_dcb_conf dcb_tx_conf;
/** Port VMDq Tx configuration. */
--
2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 1/6] ethdev: extend and refactor DCB configuration
2025-08-30 17:17 ` [RFC PATCH 1/6] ethdev: extend and refactor DCB configuration Vladimir Medvedkin
@ 2025-08-30 19:52 ` Ivan Malov
2025-08-31 15:00 ` Vladimir Medvedkin
2025-08-30 19:57 ` Ivan Malov
1 sibling, 1 reply; 18+ messages in thread
From: Ivan Malov @ 2025-08-30 19:52 UTC (permalink / raw)
To: Vladimir Medvedkin
Cc: dev, bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko,
stephen
Hi Vladimir,
On Sat, 30 Aug 2025, Vladimir Medvedkin wrote:
> Currently there are two structutes defined for DCB configuration, one for
Typo: structuRes.
> RX and one for TX. They do have slight semantic difference, but in terms
> of their structure they are identical. Refactor DCB configuration API to
> use common structute for both TX and RX.
>
> Additionally, current structure do not reflect everything that is
> required by the DCB specification, such as per Traffic Class bandwidth
> allocation and Traffic Selection Algorithm (TSA). Extend rte_eth_dcb_conf
> with additional DCB settings
>
> Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> ---
> app/test-pmd/testpmd.c | 19 ++++++-
> drivers/net/intel/ice/ice_ethdev.c | 80 ++++++++++++++++++++----------
> lib/ethdev/rte_ethdev.h | 25 ++++++----
> 3 files changed, 85 insertions(+), 39 deletions(-)
>
> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> index bb88555328..d64a7dcac5 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -4134,9 +4134,9 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
> (rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_DCB);
> eth_conf->txmode.mq_mode = RTE_ETH_MQ_TX_VMDQ_DCB;
> } else {
> - struct rte_eth_dcb_rx_conf *rx_conf =
> + struct rte_eth_dcb_conf *rx_conf =
> ð_conf->rx_adv_conf.dcb_rx_conf;
> - struct rte_eth_dcb_tx_conf *tx_conf =
> + struct rte_eth_dcb_conf *tx_conf =
> ð_conf->tx_adv_conf.dcb_tx_conf;
>
> rx_conf->nb_tcs = num_tcs;
> @@ -4148,6 +4148,21 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
> tx_conf->dcb_tc[i] = dcb_tc_val;
> }
>
> + const int bw_share_percent = 100 / num_tcs;
> + const int bw_share_left = 100 - bw_share_percent * num_tcs;
> + for (i = 0; i < num_tcs; i++) {
> + rx_conf->dcb_tc_bw[i] = bw_share_percent;
> + tx_conf->dcb_tc_bw[i] = bw_share_percent;
> +
> + rx_conf->dcb_tsa[i] = RTE_ETH_DCB_TSA_ETS;
> + tx_conf->dcb_tsa[i] = RTE_ETH_DCB_TSA_ETS;
> + }
> +
> + for (i = 0; i < bw_share_left; i++) {
> + rx_conf->dcb_tc_bw[i]++;
> + tx_conf->dcb_tc_bw[i]++;
> + }
A brief comment would make the purpose clearer.
> +
> eth_conf->rxmode.mq_mode =
> (enum rte_eth_rx_mq_mode)
> (rx_mq_mode & RTE_ETH_MQ_RX_DCB_RSS);
> diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
> index 8ab0da3549..7ba25049d7 100644
> --- a/drivers/net/intel/ice/ice_ethdev.c
> +++ b/drivers/net/intel/ice/ice_ethdev.c
> @@ -3760,10 +3760,13 @@ static int ice_init_rss(struct ice_pf *pf)
> }
>
> static int
> -check_dcb_conf(int is_8_ports, struct rte_eth_dcb_rx_conf *dcb_conf)
> +check_dcb_conf(int is_8_ports, struct rte_eth_dcb_conf *dcb_conf)
> {
> uint32_t tc_map = 0;
> int i;
> + int total_bw_allocated = 0;
> + bool ets_seen = false;
> + int nb_tc_used;
>
> enum rte_eth_nb_tcs nb_tcs = dcb_conf->nb_tcs;
> if (nb_tcs != RTE_ETH_4_TCS && is_8_ports) {
> @@ -3784,7 +3787,31 @@ check_dcb_conf(int is_8_ports, struct rte_eth_dcb_rx_conf *dcb_conf)
> return -1;
> }
>
> - return rte_popcount32(tc_map);
> + nb_tc_used = rte_popcount32(tc_map);
> +
> + /* calculate total ETS Bandwidth allocation */
> + for (i = 0; i < nb_tc_used; i++) {
> + if (dcb_conf->dcb_tsa[i] == RTE_ETH_DCB_TSA_ETS) {
> + if (dcb_conf->dcb_tc_bw[i] == 0) {
> + PMD_DRV_LOG(ERR,
> + "Bad ETS BW configuration, can not allocate 0%%");
> + return -1;
> + }
> + total_bw_allocated += dcb_conf->dcb_tc_bw[i];
> + ets_seen = true;
> + } else if (dcb_conf->dcb_tsa[i] != RTE_ETH_DCB_TSA_STRICT) {
> + PMD_DRV_LOG(ERR, "Invalid TC TSA setting - only Strict and ETS are supported");
> + return -1;
> + }
> + }
> +
> + /* total ETS BW allocation must add up to 100% */
> + if (ets_seen && total_bw_allocated != 100) {
> + PMD_DRV_LOG(ERR, "Invalid TC Bandwidth allocation configuration");
> + return -1;
> + }
> +
> + return nb_tc_used;
> }
>
> static int
> @@ -3819,15 +3846,22 @@ ice_dev_configure(struct rte_eth_dev *dev)
> struct ice_qos_cfg *qos_cfg = &port_info->qos_cfg;
> struct ice_dcbx_cfg *local_dcb_conf = &qos_cfg->local_dcbx_cfg;
> struct ice_vsi_ctx ctxt;
> - struct rte_eth_dcb_rx_conf *dcb_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
> + struct rte_eth_dcb_conf *rx_dcb_conf =
> + &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
> + struct rte_eth_dcb_conf *tx_dcb_conf =
> + &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
> int i;
> - enum rte_eth_nb_tcs nb_tcs = dcb_conf->nb_tcs;
> - int nb_tc_used, queues_per_tc;
> + enum rte_eth_nb_tcs nb_tcs = rx_dcb_conf->nb_tcs;
> + int nb_tc_used_rx, nb_tc_used_tx, queues_per_tc;
> uint16_t total_q_nb;
>
> - nb_tc_used = check_dcb_conf(ice_get_port_max_cgd(hw) == ICE_4_CGD_PER_PORT,
> - dcb_conf);
> - if (nb_tc_used < 0)
> + nb_tc_used_rx = check_dcb_conf(ice_get_port_max_cgd(hw) == ICE_4_CGD_PER_PORT,
> + rx_dcb_conf);
> + if (nb_tc_used_rx < 0)
> + return -EINVAL;
> + nb_tc_used_tx = check_dcb_conf(ice_get_port_max_cgd(hw) == ICE_4_CGD_PER_PORT,
> + tx_dcb_conf);
> + if (nb_tc_used_tx < 0)
> return -EINVAL;
>
> ctxt.info = vsi->info;
> @@ -3837,8 +3871,8 @@ ice_dev_configure(struct rte_eth_dev *dev)
> }
>
> total_q_nb = dev->data->nb_rx_queues;
> - queues_per_tc = total_q_nb / nb_tc_used;
> - if (total_q_nb % nb_tc_used != 0) {
> + queues_per_tc = total_q_nb / nb_tc_used_rx;
> + if (total_q_nb % nb_tc_used_rx != 0) {
> PMD_DRV_LOG(ERR, "For DCB, number of queues must be evenly divisble by number of used TCs");
> return -EINVAL;
> } else if (!rte_is_power_of_2(queues_per_tc)) {
> @@ -3846,7 +3880,7 @@ ice_dev_configure(struct rte_eth_dev *dev)
> return -EINVAL;
> }
>
> - for (i = 0; i < nb_tc_used; i++) {
> + for (i = 0; i < nb_tc_used_rx; i++) {
> ctxt.info.tc_mapping[i] =
> rte_cpu_to_le_16(((i * queues_per_tc) << ICE_AQ_VSI_TC_Q_OFFSET_S) |
> (rte_log2_u32(queues_per_tc) << ICE_AQ_VSI_TC_Q_NUM_S));
> @@ -3858,29 +3892,21 @@ ice_dev_configure(struct rte_eth_dev *dev)
>
> /* Associate each VLAN UP with particular TC */
> for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
> - local_dcb_conf->etscfg.prio_table[i] = dcb_conf->dcb_tc[i];
> - local_dcb_conf->etsrec.prio_table[i] = dcb_conf->dcb_tc[i];
> + local_dcb_conf->etscfg.prio_table[i] = rx_dcb_conf->dcb_tc[i];
> + local_dcb_conf->etsrec.prio_table[i] = tx_dcb_conf->dcb_tc[i];
> }
>
> - /*
> - * Since current API does not support setting ETS BW Share and Scheduler
> - * configure all TC as ETS and evenly share load across all existing TC
> - **/
> - const int bw_share_percent = 100 / nb_tc_used;
> - const int bw_share_left = 100 - bw_share_percent * nb_tc_used;
> - for (i = 0; i < nb_tc_used; i++) {
> + for (i = 0; i < nb_tc_used_rx; i++) {
> /* Per TC bandwidth table (all valued must add up to 100%), valid on ETS */
> - local_dcb_conf->etscfg.tcbwtable[i] = bw_share_percent;
> - local_dcb_conf->etsrec.tcbwtable[i] = bw_share_percent;
> + local_dcb_conf->etscfg.tcbwtable[i] = rx_dcb_conf->dcb_tc_bw[i];
>
> /**< Transmission Selection Algorithm. 0 - Strict prio, 2 - ETS */
> - local_dcb_conf->etscfg.tsatable[i] = 2;
> - local_dcb_conf->etsrec.tsatable[i] = 2;
> + local_dcb_conf->etscfg.tsatable[i] = rx_dcb_conf->dcb_tsa[i];
> }
>
> - for (i = 0; i < bw_share_left; i++) {
> - local_dcb_conf->etscfg.tcbwtable[i]++;
> - local_dcb_conf->etsrec.tcbwtable[i]++;
> + for (i = 0; i < nb_tc_used_tx; i++) {
> + local_dcb_conf->etsrec.tcbwtable[i] = tx_dcb_conf->dcb_tc_bw[i];
> + local_dcb_conf->etsrec.tsatable[i] = tx_dcb_conf->dcb_tsa[i];
> }
>
> local_dcb_conf->pfc.pfccap = nb_tcs;
> diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> index f9fb6ae549..13b1a41d3b 100644
> --- a/lib/ethdev/rte_ethdev.h
> +++ b/lib/ethdev/rte_ethdev.h
> @@ -853,6 +853,7 @@ rte_eth_rss_hf_refine(uint64_t rss_hf)
> /**@{@name VMDq and DCB maximums */
> #define RTE_ETH_VMDQ_MAX_VLAN_FILTERS 64 /**< Maximum nb. of VMDq VLAN filters. */
> #define RTE_ETH_DCB_NUM_USER_PRIORITIES 8 /**< Maximum nb. of DCB priorities. */
> +#define RTE_ETH_DCB_NUM_TCS 8 /**< Maximum nb. of DCB traffic classes. */
> #define RTE_ETH_VMDQ_DCB_NUM_QUEUES 128 /**< Maximum nb. of VMDq DCB queues. */
> #define RTE_ETH_DCB_NUM_QUEUES 128 /**< Maximum nb. of DCB queues. */
> /**@}*/
> @@ -929,11 +930,21 @@ enum rte_eth_nb_pools {
> RTE_ETH_64_POOLS = 64 /**< 64 VMDq pools. */
> };
>
> +#define RTE_ETH_DCB_TSA_STRICT 0
> +#define RTE_ETH_DCB_TSA_ETS 2
Why not enum?
> +
> /* This structure may be extended in future. */
> -struct rte_eth_dcb_rx_conf {
> +struct rte_eth_dcb_conf {
> enum rte_eth_nb_tcs nb_tcs; /**< Possible DCB TCs, 4 or 8 TCs */
> - /** Traffic class each UP mapped to. */
> + /** Traffic class each UP mapped to.
Perhaps keep '/**' on a separate line in a multi-line comment.
Thank you.
> + * Rx packets VLAN UP for Rx configuration
> + * Rx PFC Pause frames UP for Tx configuration
> + */
> uint8_t dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
> + /** Traffic class selector algorithm */
> + uint8_t dcb_tsa[RTE_ETH_DCB_NUM_TCS];
> + /** Traffic class relative bandwidth in percents */
> + uint8_t dcb_tc_bw[RTE_ETH_DCB_NUM_TCS];
> };
>
> struct rte_eth_vmdq_dcb_tx_conf {
> @@ -942,12 +953,6 @@ struct rte_eth_vmdq_dcb_tx_conf {
> uint8_t dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
> };
>
> -struct rte_eth_dcb_tx_conf {
> - enum rte_eth_nb_tcs nb_tcs; /**< Possible DCB TCs, 4 or 8 TCs. */
> - /** Traffic class each UP mapped to. */
> - uint8_t dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
> -};
> -
> struct rte_eth_vmdq_tx_conf {
> enum rte_eth_nb_pools nb_queue_pools; /**< VMDq mode, 64 pools. */
> };
> @@ -1531,7 +1536,7 @@ struct rte_eth_conf {
> /** Port VMDq+DCB configuration. */
> struct rte_eth_vmdq_dcb_conf vmdq_dcb_conf;
> /** Port DCB Rx configuration. */
> - struct rte_eth_dcb_rx_conf dcb_rx_conf;
> + struct rte_eth_dcb_conf dcb_rx_conf;
> /** Port VMDq Rx configuration. */
> struct rte_eth_vmdq_rx_conf vmdq_rx_conf;
> } rx_adv_conf; /**< Port Rx filtering configuration. */
> @@ -1539,7 +1544,7 @@ struct rte_eth_conf {
> /** Port VMDq+DCB Tx configuration. */
> struct rte_eth_vmdq_dcb_tx_conf vmdq_dcb_tx_conf;
> /** Port DCB Tx configuration. */
> - struct rte_eth_dcb_tx_conf dcb_tx_conf;
> + struct rte_eth_dcb_conf dcb_tx_conf;
> /** Port VMDq Tx configuration. */
> struct rte_eth_vmdq_tx_conf vmdq_tx_conf;
> } tx_adv_conf; /**< Port Tx DCB configuration (union). */
> --
> 2.43.0
>
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 1/6] ethdev: extend and refactor DCB configuration
2025-08-30 17:17 ` [RFC PATCH 1/6] ethdev: extend and refactor DCB configuration Vladimir Medvedkin
2025-08-30 19:52 ` Ivan Malov
@ 2025-08-30 19:57 ` Ivan Malov
2025-08-31 15:01 ` Vladimir Medvedkin
1 sibling, 1 reply; 18+ messages in thread
From: Ivan Malov @ 2025-08-30 19:57 UTC (permalink / raw)
To: Vladimir Medvedkin
Cc: dev, bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko,
stephen
On Sat, 30 Aug 2025, Vladimir Medvedkin wrote:
> + /** Traffic class each UP mapped to.
> + * Rx packets VLAN UP for Rx configuration
> + * Rx PFC Pause frames UP for Tx configuration
Is this confined to VLAN? Can the UP come from other headers of the packet?
I apologise in case my question is wrong.
Thank you.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 4/6] ethdev: extend VMDq/DCB configuration with queue mapping
2025-08-30 17:17 ` [RFC PATCH 4/6] ethdev: extend VMDq/DCB configuration with queue mapping Vladimir Medvedkin
@ 2025-08-30 20:36 ` Ivan Malov
2025-08-31 15:09 ` Vladimir Medvedkin
0 siblings, 1 reply; 18+ messages in thread
From: Ivan Malov @ 2025-08-30 20:36 UTC (permalink / raw)
To: Vladimir Medvedkin
Cc: dev, bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko,
stephen
Hi Vladimir,
On Sat, 30 Aug 2025, Vladimir Medvedkin wrote:
> Currently DCB Traffic Class queue mapping is only used when calling get
> DCB info API, while setting up queue mappings is up to each individual
> driver. Use the tc queue mapping structure to enable setting up custom
> mapping explicitly.
>
> Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> ---
> app/test-pmd/testpmd.c | 57 ++++++++++++++++++------------
> drivers/net/intel/ice/ice_ethdev.c | 39 ++++++++++----------
> drivers/net/intel/ice/ice_rxtx.c | 27 +++++++-------
> lib/ethdev/rte_ethdev.h | 43 +++++++++++-----------
> 4 files changed, 92 insertions(+), 74 deletions(-)
>
> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> index b5a7e7b3ee..3a55434d44 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -4158,6 +4158,16 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
> struct rte_eth_dcb_conf *tx_conf =
> ð_conf->tx_adv_conf.dcb_tx_conf;
>
> + struct rte_eth_dcb_tc_queue_mapping *q_map = ð_conf->q_map;
> + memset(q_map, 0, sizeof(*q_map));
> + int queues_per_tc = nb_rxq / num_tcs;
> + for (i = 0; i < num_tcs; i++) {
> + q_map->tc_rxq[0][i].base = i * queues_per_tc;
> + q_map->tc_txq[0][i].base = i * queues_per_tc;
> + q_map->tc_rxq[0][i].nb_queue = queues_per_tc;
> + q_map->tc_txq[0][i].nb_queue = queues_per_tc;
> + }
> +
> for (i = 0; i < RTE_ETH_DCB_NUM_USER_PRIORITIES; i++) {
> dcb_tc_val = prio_tc_en ? prio_tc[i] : i % num_tcs;
> rx_conf->dcb_tc[i] = dcb_tc_val;
> @@ -4231,6 +4241,30 @@ init_port_dcb_config(portid_t pid,
> /* retain the original device configuration. */
> memcpy(&port_conf, &rte_port->dev_conf, sizeof(struct rte_eth_conf));
>
> + if (num_tcs > 1 && keep_qnum == 0) {
> + /* Assume the ports in testpmd have the same dcb capability
> + * and has the same number of rxq and txq in dcb mode
> + */
> + if (dcb_mode == DCB_VT_ENABLED) {
> + if (rte_port->dev_info.max_vfs > 0) {
> + nb_rxq = rte_port->dev_info.nb_rx_queues;
> + nb_txq = rte_port->dev_info.nb_tx_queues;
> + } else {
> + nb_rxq = rte_port->dev_info.max_rx_queues;
> + nb_txq = rte_port->dev_info.max_tx_queues;
> + }
> + } else {
> + /*if vt is disabled, use all pf queues */
Missing space between '/*' and 'if'.
> + if (rte_port->dev_info.vmdq_pool_base == 0) {
> + nb_rxq = rte_port->dev_info.max_rx_queues;
> + nb_txq = rte_port->dev_info.max_tx_queues;
> + } else {
> + nb_rxq = (queueid_t)num_tcs;
> + nb_txq = (queueid_t)num_tcs;
> + }
> + }
> + }
> +
> if (num_tcs > 1) {
> /* set configuration of DCB in vt mode and DCB in non-vt mode */
> get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, pfc_en, prio_tc, prio_tc_en);
> @@ -4267,29 +4301,6 @@ init_port_dcb_config(portid_t pid,
> return -1;
> }
>
> - if (num_tcs > 1 && keep_qnum == 0) {
> - /* Assume the ports in testpmd have the same dcb capability
> - * and has the same number of rxq and txq in dcb mode
> - */
> - if (dcb_mode == DCB_VT_ENABLED) {
> - if (rte_port->dev_info.max_vfs > 0) {
> - nb_rxq = rte_port->dev_info.nb_rx_queues;
> - nb_txq = rte_port->dev_info.nb_tx_queues;
> - } else {
> - nb_rxq = rte_port->dev_info.max_rx_queues;
> - nb_txq = rte_port->dev_info.max_tx_queues;
> - }
> - } else {
> - /*if vt is disabled, use all pf queues */
> - if (rte_port->dev_info.vmdq_pool_base == 0) {
> - nb_rxq = rte_port->dev_info.max_rx_queues;
> - nb_txq = rte_port->dev_info.max_tx_queues;
> - } else {
> - nb_rxq = (queueid_t)num_tcs;
> - nb_txq = (queueid_t)num_tcs;
> - }
> - }
> - }
> rx_free_thresh = 64;
>
> memcpy(&rte_port->dev_conf, &port_conf, sizeof(struct rte_eth_conf));
> diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
> index ecde00182f..27559bbe18 100644
> --- a/drivers/net/intel/ice/ice_ethdev.c
> +++ b/drivers/net/intel/ice/ice_ethdev.c
> @@ -3846,7 +3846,7 @@ ice_dev_configure(struct rte_eth_dev *dev)
> struct rte_eth_dcb_conf *tx_dcb_conf =
> &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
> int i;
> - int nb_tc_used_rx, nb_tc_used_tx, queues_per_tc;
> + int nb_tc_used_rx, nb_tc_used_tx;
> uint16_t total_q_nb;
>
> nb_tc_used_rx = check_dcb_conf(ice_get_port_max_cgd(hw) == ICE_4_CGD_PER_PORT,
> @@ -3865,19 +3865,23 @@ ice_dev_configure(struct rte_eth_dev *dev)
> }
>
> total_q_nb = dev->data->nb_rx_queues;
> - queues_per_tc = total_q_nb / nb_tc_used_rx;
> - if (total_q_nb % nb_tc_used_rx != 0) {
> - PMD_DRV_LOG(ERR, "For DCB, number of queues must be evenly divisble by number of used TCs");
> - return -EINVAL;
> - } else if (!rte_is_power_of_2(queues_per_tc)) {
> - PMD_DRV_LOG(ERR, "For DCB, number of queues per TC must be a power of 2");
> - return -EINVAL;
> - }
> -
> + struct rte_eth_dcb_tc_queue_mapping *q_map = &dev->data->dev_conf.q_map;
> for (i = 0; i < nb_tc_used_rx; i++) {
> + if (q_map->tc_rxq[0][i].nb_queue != 0 &&
How is 'nb_queue == 0' case handled here and below? Should some driver-default
fill-in be used, similar to code being deleted above?
Or is '(0 << ICE_AQ_VSI_TC_Q_OFFSET_S) | (0 << ICE_AQ_VSI_TC_Q_NUM_S)' legit?
> + !rte_is_power_of_2(q_map->tc_rxq[0][i].nb_queue)) {
> + PMD_DRV_LOG(ERR, "For DCB, number of queues per TC must be a power of 2");
> + return -EINVAL;
> + }
> + if ((q_map->tc_rxq[0][i].base + q_map->tc_rxq[0][i].nb_queue) > total_q_nb) {
> + PMD_DRV_LOG(ERR, "Queue range for TC %d exceeds total number of queues",
> + i);
> + return -EINVAL;
> + }
> ctxt.info.tc_mapping[i] =
> - rte_cpu_to_le_16(((i * queues_per_tc) << ICE_AQ_VSI_TC_Q_OFFSET_S) |
> - (rte_log2_u32(queues_per_tc) << ICE_AQ_VSI_TC_Q_NUM_S));
> + rte_cpu_to_le_16((q_map->tc_rxq[0][i].base <<
> + ICE_AQ_VSI_TC_Q_OFFSET_S) |
> + (rte_log2_u32(q_map->tc_rxq[0][i].nb_queue) <<
> + ICE_AQ_VSI_TC_Q_NUM_S));
This seems to always use pool [0] but does not seem to check if 'nb_queue' in,
say, pool [1] is non-zero, to return an error or something. Or is this unneeded?
> }
>
> memset(local_dcb_conf, 0, sizeof(*local_dcb_conf));
> @@ -3941,6 +3945,7 @@ ice_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
> struct ice_dcbx_cfg *dcb_conf = &qos_cfg->local_dcbx_cfg;
> struct ice_vsi *vsi = pf->main_vsi;
> struct ice_vsi_ctx ctxt = { 0 };
> + struct rte_eth_dcb_tc_queue_mapping *q_map = &dev->data->dev_conf.q_map;
>
> ctxt.info = vsi->info;
> if (rte_le_to_cpu_16(ctxt.info.mapping_flags) == ICE_AQ_VSI_Q_MAP_NONCONTIG) {
> @@ -3953,13 +3958,11 @@ ice_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
> dcb_info->prio_tc[i] = dcb_conf->etscfg.prio_table[i];
> dcb_info->tc_bws[i] = dcb_conf->etscfg.tcbwtable[i];
> /* Using VMDQ pool zero since DCB+VMDQ is not supported */
> - uint16_t tc_rx_q_map = rte_le_to_cpu_16(ctxt.info.tc_mapping[i]);
> - dcb_info->tc_queue.tc_rxq[0][i].base = tc_rx_q_map & ICE_AQ_VSI_TC_Q_OFFSET_M;
> - dcb_info->tc_queue.tc_rxq[0][i].nb_queue =
> - 1 << ((tc_rx_q_map & ICE_AQ_VSI_TC_Q_NUM_M) >> ICE_AQ_VSI_TC_Q_NUM_S);
> + dcb_info->tc_queue.tc_rxq[0][i].base = q_map->tc_rxq[0][i].base;
> + dcb_info->tc_queue.tc_rxq[0][i].nb_queue = q_map->tc_rxq[0][i].nb_queue;
>
> - dcb_info->tc_queue.tc_txq[0][i].base = dcb_info->tc_queue.tc_rxq[0][i].base;
> - dcb_info->tc_queue.tc_txq[0][i].nb_queue = dcb_info->tc_queue.tc_rxq[0][i].nb_queue;
> + dcb_info->tc_queue.tc_txq[0][i].base = q_map->tc_txq[0][i].base;
> + dcb_info->tc_queue.tc_txq[0][i].nb_queue = q_map->tc_txq[0][i].nb_queue;
> }
>
> return 0;
> diff --git a/drivers/net/intel/ice/ice_rxtx.c b/drivers/net/intel/ice/ice_rxtx.c
> index 451816affd..55424e7a23 100644
> --- a/drivers/net/intel/ice/ice_rxtx.c
> +++ b/drivers/net/intel/ice/ice_rxtx.c
> @@ -796,6 +796,7 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
> int buf_len;
> struct ice_adapter *ad = ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
> u16 q_base, q_range, cgd_idx = 0;
> + struct rte_eth_dcb_tc_queue_mapping *q_map = &dev->data->dev_conf.q_map;
>
> PMD_INIT_FUNC_TRACE();
>
> @@ -840,22 +841,22 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
> tx_ctx.legacy_int = 1; /* Legacy or Advanced Host Interface */
> tx_ctx.tsyn_ena = 1;
>
> - /* Mirror RXQ<->CGD association to TXQ<->CDG */
> - for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
> - q_base = rte_le_to_cpu_16(vsi->info.tc_mapping[i]) & ICE_AQ_VSI_TC_Q_OFFSET_M;
> - q_range = 1 << ((rte_le_to_cpu_16(vsi->info.tc_mapping[i]) &
> - ICE_AQ_VSI_TC_Q_NUM_M) >> ICE_AQ_VSI_TC_Q_NUM_S);
> + if (dev->data->dev_conf.txmode.mq_mode == RTE_ETH_MQ_TX_DCB) {
> + for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
> + q_base = q_map->tc_txq[0][i].base;
> + q_range = q_map->tc_txq[0][i].nb_queue;
>
> - if (q_base <= tx_queue_id && tx_queue_id < q_base + q_range)
> - break;
> + if (q_base <= tx_queue_id && tx_queue_id < q_base + q_range)
> + break;
>
> - cgd_idx++;
> - }
> + cgd_idx++;
> + }
>
> - if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
> - PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
> - rte_free(txq_elem);
> - return -EINVAL;
> + if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
> + PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
> + rte_free(txq_elem);
> + return -EINVAL;
> + }
> }
>
> tx_ctx.cgd_num = cgd_idx;
> diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> index c220760043..0bd86e1e7d 100644
> --- a/lib/ethdev/rte_ethdev.h
> +++ b/lib/ethdev/rte_ethdev.h
> @@ -1472,6 +1472,26 @@ struct rte_eth_intr_conf {
>
> #define rte_intr_conf rte_eth_intr_conf
>
> +#define RTE_ETH_DCB_NUM_TCS 8
> +#define RTE_ETH_MAX_VMDQ_POOL 64
> +
> +/**
> + * A structure used to get the information of queue and
> + * TC mapping on both Tx and Rx paths.
> + */
> +struct rte_eth_dcb_tc_queue_mapping {
> + /** Rx queues assigned to tc per Pool */
> + struct {
> + uint16_t base;
> + uint16_t nb_queue;
> + } tc_rxq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> + /** Rx queues assigned to tc per Pool */
> + struct {
> + uint16_t base;
> + uint16_t nb_queue;
> + } tc_txq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> +};
> +
> /**
> * A structure used to configure an Ethernet port.
> * Depending upon the Rx multi-queue mode, extra advanced
> @@ -1492,18 +1512,21 @@ struct rte_eth_conf {
> Read the datasheet of given Ethernet controller
> for details. The possible values of this field
> are defined in implementation of each driver. */
> + struct rte_eth_dcb_tc_queue_mapping q_map;
Is the driver supposed to tell 'q_map' is valid by looking at [0][0] 'nb_queue'?
> struct {
> struct rte_eth_rss_conf rss_conf; /**< Port RSS configuration */
> /** Port DCB Rx configuration. */
> struct rte_eth_dcb_conf dcb_rx_conf;
> /** Port VMDq Rx configuration. */
> struct rte_eth_vmdq_rx_conf vmdq_rx_conf;
> + /* VMDQ and DCB Rx queue mapping configuration. */
Perhaps it's better to have just one such comment right before 'q_map'.
Thank you.
> } rx_adv_conf; /**< Port Rx filtering configuration. */
> struct {
> /** Port DCB Tx configuration. */
> struct rte_eth_dcb_conf dcb_tx_conf;
> /** Port VMDq Tx configuration. */
> struct rte_eth_vmdq_tx_conf vmdq_tx_conf;
> + /* VMDQ and DCB Tx queue mapping configuration. */
> } tx_adv_conf; /**< Port Tx DCB configuration (union). */
> /** Currently,Priority Flow Control(PFC) are supported,if DCB with PFC
> is needed,and the variable must be set RTE_ETH_DCB_PFC_SUPPORT. */
> @@ -1930,26 +1953,6 @@ struct rte_eth_xstat_name {
> char name[RTE_ETH_XSTATS_NAME_SIZE]; /**< The statistic name. */
> };
>
> -#define RTE_ETH_DCB_NUM_TCS 8
> -#define RTE_ETH_MAX_VMDQ_POOL 64
> -
> -/**
> - * A structure used to get the information of queue and
> - * TC mapping on both Tx and Rx paths.
> - */
> -struct rte_eth_dcb_tc_queue_mapping {
> - /** Rx queues assigned to tc per Pool */
> - struct {
> - uint16_t base;
> - uint16_t nb_queue;
> - } tc_rxq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> - /** Rx queues assigned to tc per Pool */
> - struct {
> - uint16_t base;
> - uint16_t nb_queue;
> - } tc_txq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> -};
> -
> /**
> * A structure used to get the information of DCB.
> * It includes TC UP mapping and queue TC mapping.
> --
> 2.43.0
>
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 5/6] ethdev: remove dcb_capability_en from rte_eth_conf
2025-08-30 17:17 ` [RFC PATCH 5/6] ethdev: remove dcb_capability_en from rte_eth_conf Vladimir Medvedkin
@ 2025-08-30 20:46 ` Ivan Malov
2025-08-30 20:49 ` Ivan Malov
1 sibling, 0 replies; 18+ messages in thread
From: Ivan Malov @ 2025-08-30 20:46 UTC (permalink / raw)
To: Vladimir Medvedkin
Cc: dev, bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko,
stephen
Hi Vladimir,
On Sat, 30 Aug 2025, Vladimir Medvedkin wrote:
> Currently there are DCB configuration capability flags that are suppose
Typo: supposeD.
> to enable DCB Priority Groups (aka Traffic Classes), and Priority Flow
> Control. The former is not used anywhere at all, while the latter us used
Typo: Is used.
> in some drivers, but is used to enable PFC on all existing Traffic
> Classes, which feels like a questionable design choice.
>
> It is recommended to use existing API to enable PFC on specific Traffic
> Class.
>
> Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> ---
> app/test-pmd/cmdline.c | 19 +++----------------
> app/test-pmd/testpmd.c | 12 ++----------
> app/test-pmd/testpmd.h | 1 -
> lib/ethdev/rte_ethdev.h | 8 --------
> 4 files changed, 5 insertions(+), 35 deletions(-)
>
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index 82322f3456..346dd7c133 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -3526,7 +3526,6 @@ parse_dcb_token_find(char *split_str[], int split_num, int *param_num)
>
> static int
> parse_dcb_token_value(char *token_str,
> - uint8_t *pfc_en,
> uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES],
> uint8_t *prio_tc_en,
> uint8_t *keep_qnum)
> @@ -3549,17 +3548,6 @@ parse_dcb_token_value(char *token_str,
> split_str[split_num++] = token;
> } while (1);
>
> - /* parse fixed parameter "pfc-en" first. */
> - token = split_str[0];
> - if (strcmp(token, "on") == 0)
> - *pfc_en = 1;
> - else if (strcmp(token, "off") == 0)
> - *pfc_en = 0;
> - else {
> - fprintf(stderr, "Bad Argument: pfc-en must be on or off\n");
> - return -EINVAL;
> - }
> -
> if (split_num == 1)
> return 0;
>
> @@ -3612,7 +3600,6 @@ cmd_config_dcb_parsed(void *parsed_result,
> uint8_t prio_tc_en = 0;
> uint8_t keep_qnum = 0;
> struct rte_port *port;
> - uint8_t pfc_en = 0;
> int ret;
>
> if (port_id_is_invalid(port_id, ENABLED_WARN))
> @@ -3644,7 +3631,7 @@ cmd_config_dcb_parsed(void *parsed_result,
> return;
> }
>
> - ret = parse_dcb_token_value(res->token_str, &pfc_en, prio_tc, &prio_tc_en, &keep_qnum);
> + ret = parse_dcb_token_value(res->token_str, prio_tc, &prio_tc_en, &keep_qnum);
> if (ret != 0)
> return;
>
> @@ -3652,11 +3639,11 @@ cmd_config_dcb_parsed(void *parsed_result,
> if (!strncmp(res->vt_en, "on", 2))
> ret = init_port_dcb_config(port_id, DCB_VT_ENABLED,
> (int)res->num_tcs,
> - pfc_en, prio_tc, prio_tc_en, keep_qnum);
> + prio_tc, prio_tc_en, keep_qnum);
> else
> ret = init_port_dcb_config(port_id, DCB_ENABLED,
> (int)res->num_tcs,
> - pfc_en, prio_tc, prio_tc_en, keep_qnum);
> + prio_tc, prio_tc_en, keep_qnum);
> if (ret != 0) {
> fprintf(stderr, "Cannot initialize network ports.\n");
> return;
> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> index 3a55434d44..8602781aac 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -4093,8 +4093,7 @@ const uint16_t vlan_tags[] = {
>
> static void
> get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
> - int num_tcs, uint8_t pfc_en,
> - uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES], uint8_t prio_tc_en)
> + int num_tcs, uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES], uint8_t prio_tc_en)
> {
> uint8_t dcb_tc_val, i;
>
> @@ -4195,11 +4194,6 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
> eth_conf->txmode.mq_mode = RTE_ETH_MQ_TX_DCB;
> }
>
> - if (pfc_en)
> - eth_conf->dcb_capability_en =
> - RTE_ETH_DCB_PG_SUPPORT | RTE_ETH_DCB_PFC_SUPPORT;
> - else
> - eth_conf->dcb_capability_en = RTE_ETH_DCB_PG_SUPPORT;
> }
>
> static void
> @@ -4209,7 +4203,6 @@ clear_eth_dcb_conf(portid_t pid, struct rte_eth_conf *eth_conf)
>
> eth_conf->rxmode.mq_mode &= ~(RTE_ETH_MQ_RX_DCB | RTE_ETH_MQ_RX_VMDQ_DCB);
> eth_conf->txmode.mq_mode = RTE_ETH_MQ_TX_NONE;
> - eth_conf->dcb_capability_en = 0;
> if (dcb_config) {
> /* Unset VLAN filter configuration if already config DCB. */
> eth_conf->rxmode.offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
> @@ -4222,7 +4215,6 @@ int
> init_port_dcb_config(portid_t pid,
> enum dcb_mode_enable dcb_mode,
> int num_tcs,
> - uint8_t pfc_en,
> uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES],
> uint8_t prio_tc_en,
> uint8_t keep_qnum)
> @@ -4267,7 +4259,7 @@ init_port_dcb_config(portid_t pid,
>
> if (num_tcs > 1) {
> /* set configuration of DCB in vt mode and DCB in non-vt mode */
> - get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, pfc_en, prio_tc, prio_tc_en);
> + get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, prio_tc, prio_tc_en);
> port_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
> /* remove RSS HASH offload for DCB in vt mode */
> if (port_conf.rxmode.mq_mode == RTE_ETH_MQ_RX_VMDQ_DCB) {
> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
> index 4ff982ed3f..bb1aaec918 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -1151,7 +1151,6 @@ uint8_t port_is_bonding_member(portid_t member_pid);
>
> int init_port_dcb_config(portid_t pid, enum dcb_mode_enable dcb_mode,
> int num_tcs,
> - uint8_t pfc_en,
> uint8_t prio_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES],
> uint8_t prio_tc_en,
> uint8_t keep_qnum);
> diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> index 0bd86e1e7d..60532e0155 100644
> --- a/lib/ethdev/rte_ethdev.h
> +++ b/lib/ethdev/rte_ethdev.h
> @@ -858,11 +858,6 @@ rte_eth_rss_hf_refine(uint64_t rss_hf)
> #define RTE_ETH_DCB_NUM_QUEUES 128 /**< Maximum nb. of DCB queues. */
> /**@}*/
>
> -/**@{@name DCB capabilities */
> -#define RTE_ETH_DCB_PG_SUPPORT RTE_BIT32(0) /**< Priority Group(ETS) support. */
> -#define RTE_ETH_DCB_PFC_SUPPORT RTE_BIT32(1) /**< Priority Flow Control support. */
I apologise in case I misunderstand something, but this seems to be used in
https://github.com/DPDK/dpdk/blob/b222395561638f89562e4ef42e1eabf2d6db43dd/drivers/net/txgbe/txgbe_rxtx.c#L3830
https://github.com/DPDK/dpdk/blob/b222395561638f89562e4ef42e1eabf2d6db43dd/drivers/net/intel/ixgbe/ixgbe_rxtx.c#L4475
https://github.com/DPDK/dpdk/blob/b222395561638f89562e4ef42e1eabf2d6db43dd/drivers/net/intel/i40e/i40e_ethdev.c#L10715
https://github.com/DPDK/dpdk/blob/b222395561638f89562e4ef42e1eabf2d6db43dd/drivers/net/hns3/hns3_ethdev_vf.c#L525
https://github.com/DPDK/dpdk/blob/b222395561638f89562e4ef42e1eabf2d6db43dd/drivers/net/hns3/hns3_dcb.c#L1510
Or is this applied on top of something that has already removed those?
Thank you.
> -/**@}*/
> -
> /**@{@name VLAN offload bits */
> #define RTE_ETH_VLAN_STRIP_OFFLOAD 0x0001 /**< VLAN Strip On/Off */
> #define RTE_ETH_VLAN_FILTER_OFFLOAD 0x0002 /**< VLAN Filter On/Off */
> @@ -1528,9 +1523,6 @@ struct rte_eth_conf {
> struct rte_eth_vmdq_tx_conf vmdq_tx_conf;
> /* VMDQ and DCB Tx queue mapping configuration. */
> } tx_adv_conf; /**< Port Tx DCB configuration (union). */
> - /** Currently,Priority Flow Control(PFC) are supported,if DCB with PFC
> - is needed,and the variable must be set RTE_ETH_DCB_PFC_SUPPORT. */
> - uint32_t dcb_capability_en;
> struct rte_eth_intr_conf intr_conf; /**< Interrupt mode configuration. */
> };
>
> --
> 2.43.0
>
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 5/6] ethdev: remove dcb_capability_en from rte_eth_conf
2025-08-30 17:17 ` [RFC PATCH 5/6] ethdev: remove dcb_capability_en from rte_eth_conf Vladimir Medvedkin
2025-08-30 20:46 ` Ivan Malov
@ 2025-08-30 20:49 ` Ivan Malov
1 sibling, 0 replies; 18+ messages in thread
From: Ivan Malov @ 2025-08-30 20:49 UTC (permalink / raw)
To: Vladimir Medvedkin
Cc: dev, bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko,
stephen
On Sat, 30 Aug 2025, Vladimir Medvedkin wrote:
> -#define RTE_ETH_DCB_PFC_SUPPORT RTE_BIT32(1) /**< Priority Flow Control support. */
Sorry, I now see [0/6] explains other drivers have not been taken care of yet.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API
2025-08-30 17:17 [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Vladimir Medvedkin
` (5 preceding siblings ...)
2025-08-30 17:17 ` [RFC PATCH 6/6] ethdev: move mq_mode to [r,t]x_adv_conf Vladimir Medvedkin
@ 2025-08-30 21:13 ` Ivan Malov
2025-08-31 14:55 ` Vladimir Medvedkin
6 siblings, 1 reply; 18+ messages in thread
From: Ivan Malov @ 2025-08-30 21:13 UTC (permalink / raw)
To: Vladimir Medvedkin
Cc: dev, bruce.richardson, anatoly.burakov, thomas, andrew.rybchenko,
stephen
Hi Vladimir,
On Sat, 30 Aug 2025, Vladimir Medvedkin wrote:
> Hi all,
>
> This series reworks the ethdev API related to advanced queueing configuration,
> specifically Data Center Bridging (DCB) and Virtual Machine Device Queues
> (VMDq). The existing API was designed years ago around ixgbe hardware
> assumptions, which makes it difficult to properly support modern NICs and their
> more flexible capabilities.
>
I like this overall.
The series seems to be a good rework, but the PMD changes are going to be vast.
Also, given the fact it targets the same release cycle as some new drivers do,
it can be problematic to apply 'rx_adv_conf.mq_mode' to, say, [1] on the go.
[1] https://mails.dpdk.org/archives/dev/2025-August/323562.html
Also, now we've touched on the topic of traffic classes and priorities, if I may
be so bold as to ask an unrelated question about [2]. Does the priority value
have to come specifically from VLAN header? Or can it come, say, from ToS of
IPv4, or Traffic Class of IPv6, or from some vendor-specific header?
[2] https://doc.dpdk.org/api-25.07/structrte__eth__pfc__conf.html#a0ad043071ccc7a261d79a759dc9c6f0c
Thank you.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API
2025-08-30 21:13 ` [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Ivan Malov
@ 2025-08-31 14:55 ` Vladimir Medvedkin
0 siblings, 0 replies; 18+ messages in thread
From: Vladimir Medvedkin @ 2025-08-31 14:55 UTC (permalink / raw)
To: Ivan Malov
Cc: Vladimir Medvedkin, dev, bruce.richardson, anatoly.burakov,
thomas, andrew.rybchenko, stephen
[-- Attachment #1: Type: text/plain, Size: 2810 bytes --]
Hi Ivan,
Thanks for your comments, please see my comments inline below.
сб, 30 авг. 2025 г. в 22:14, Ivan Malov <ivan.malov@arknetworks.am>:
> Hi Vladimir,
>
> On Sat, 30 Aug 2025, Vladimir Medvedkin wrote:
>
> > Hi all,
> >
> > This series reworks the ethdev API related to advanced queueing
> configuration,
> > specifically Data Center Bridging (DCB) and Virtual Machine Device Queues
> > (VMDq). The existing API was designed years ago around ixgbe hardware
> > assumptions, which makes it difficult to properly support modern NICs
> and their
> > more flexible capabilities.
> >
>
> I like this overall.
>
> The series seems to be a good rework, but the PMD changes are going to be
> vast.
> Also, given the fact it targets the same release cycle as some new drivers
> do,
> it can be problematic to apply 'rx_adv_conf.mq_mode' to, say, [1] on the
> go.
>
> [1] https://mails.dpdk.org/archives/dev/2025-August/323562.html
Yes, I see, some patches in the series may be postponed for later, if
necessary.
>
>
>
> Also, now we've touched on the topic of traffic classes and priorities, if
> I may
> be so bold as to ask an unrelated question about [2]. Does the priority
> value
> have to come specifically from VLAN header? Or can it come, say, from ToS
> of
> IPv4, or Traffic Class of IPv6, or from some vendor-specific header?
>
> [2]
> https://doc.dpdk.org/api-25.07/structrte__eth__pfc__conf.html#a0ad043071ccc7a261d79a759dc9c6f0c
>
>
That's a good question. The short answer is yes, at the moment, but it won't
be 100% true in the future.
For example, Intel E800 Series network adapters can operate in two modes,
depending on how HW classifies incoming packets into their respective
traffic classes. One of the modes uses a 3-bit PCP VLAN field, and this is
the default mode. Another mode is to use the 6-bit DSCP, which is supported
by E800 NICs, but is not currently enabled. In DSCP mode, HW maintains one
additional DSCP-to-UP mapping table to translate incoming packets to
intermediate UP, and then uses a usual UP-to-TC mapping table (ref. to the
E810 datasheet 8.2.1.3.1.2 Packet CoS Classification Flow in “DSCP PFC” Mode).
Also please note that the PFC PAUSE frames carry per-priority pause quanta
for 8 priorities, and those priorities usually correspond to VLAN PCP.
Regarding vendor-specific headers, I'm not aware of any vendor that supports
this. Although this is theoretically possible, keep in mind that the HW
block responsible for TC classification should usually be located somewhere
at the very beginning of the Rx pipeline, there are strict performance
limitations for it, so most likely its implementation will be as simple as
possible.
> Thank you.
>
--
Regards,
Vladimir
[-- Attachment #2: Type: text/html, Size: 16902 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 1/6] ethdev: extend and refactor DCB configuration
2025-08-30 19:52 ` Ivan Malov
@ 2025-08-31 15:00 ` Vladimir Medvedkin
0 siblings, 0 replies; 18+ messages in thread
From: Vladimir Medvedkin @ 2025-08-31 15:00 UTC (permalink / raw)
To: Ivan Malov
Cc: Vladimir Medvedkin, dev, bruce.richardson, anatoly.burakov,
thomas, andrew.rybchenko, stephen
[-- Attachment #1: Type: text/plain, Size: 13796 bytes --]
сб, 30 авг. 2025 г. в 20:52, Ivan Malov <ivan.malov@arknetworks.am>:
> Hi Vladimir,
>
> On Sat, 30 Aug 2025, Vladimir Medvedkin wrote:
>
> > Currently there are two structutes defined for DCB configuration, one for
>
> Typo: structuRes.
>
> > RX and one for TX. They do have slight semantic difference, but in terms
> > of their structure they are identical. Refactor DCB configuration API to
> > use common structute for both TX and RX.
> >
> > Additionally, current structure do not reflect everything that is
> > required by the DCB specification, such as per Traffic Class bandwidth
> > allocation and Traffic Selection Algorithm (TSA). Extend rte_eth_dcb_conf
> > with additional DCB settings
> >
> > Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> > ---
> > app/test-pmd/testpmd.c | 19 ++++++-
> > drivers/net/intel/ice/ice_ethdev.c | 80 ++++++++++++++++++++----------
> > lib/ethdev/rte_ethdev.h | 25 ++++++----
> > 3 files changed, 85 insertions(+), 39 deletions(-)
> >
> > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> > index bb88555328..d64a7dcac5 100644
> > --- a/app/test-pmd/testpmd.c
> > +++ b/app/test-pmd/testpmd.c
> > @@ -4134,9 +4134,9 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf,
> enum dcb_mode_enable dcb_mode,
> > (rx_mq_mode &
> RTE_ETH_MQ_RX_VMDQ_DCB);
> > eth_conf->txmode.mq_mode = RTE_ETH_MQ_TX_VMDQ_DCB;
> > } else {
> > - struct rte_eth_dcb_rx_conf *rx_conf =
> > + struct rte_eth_dcb_conf *rx_conf =
> > ð_conf->rx_adv_conf.dcb_rx_conf;
> > - struct rte_eth_dcb_tx_conf *tx_conf =
> > + struct rte_eth_dcb_conf *tx_conf =
> > ð_conf->tx_adv_conf.dcb_tx_conf;
> >
> > rx_conf->nb_tcs = num_tcs;
> > @@ -4148,6 +4148,21 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf,
> enum dcb_mode_enable dcb_mode,
> > tx_conf->dcb_tc[i] = dcb_tc_val;
> > }
> >
> > + const int bw_share_percent = 100 / num_tcs;
> > + const int bw_share_left = 100 - bw_share_percent * num_tcs;
> > + for (i = 0; i < num_tcs; i++) {
> > + rx_conf->dcb_tc_bw[i] = bw_share_percent;
> > + tx_conf->dcb_tc_bw[i] = bw_share_percent;
> > +
> > + rx_conf->dcb_tsa[i] = RTE_ETH_DCB_TSA_ETS;
> > + tx_conf->dcb_tsa[i] = RTE_ETH_DCB_TSA_ETS;
> > + }
> > +
> > + for (i = 0; i < bw_share_left; i++) {
> > + rx_conf->dcb_tc_bw[i]++;
> > + tx_conf->dcb_tc_bw[i]++;
> > + }
>
> A brief comment would make the purpose clearer.
>
> > +
> > eth_conf->rxmode.mq_mode =
> > (enum rte_eth_rx_mq_mode)
> > (rx_mq_mode &
> RTE_ETH_MQ_RX_DCB_RSS);
> > diff --git a/drivers/net/intel/ice/ice_ethdev.c
> b/drivers/net/intel/ice/ice_ethdev.c
> > index 8ab0da3549..7ba25049d7 100644
> > --- a/drivers/net/intel/ice/ice_ethdev.c
> > +++ b/drivers/net/intel/ice/ice_ethdev.c
> > @@ -3760,10 +3760,13 @@ static int ice_init_rss(struct ice_pf *pf)
> > }
> >
> > static int
> > -check_dcb_conf(int is_8_ports, struct rte_eth_dcb_rx_conf *dcb_conf)
> > +check_dcb_conf(int is_8_ports, struct rte_eth_dcb_conf *dcb_conf)
> > {
> > uint32_t tc_map = 0;
> > int i;
> > + int total_bw_allocated = 0;
> > + bool ets_seen = false;
> > + int nb_tc_used;
> >
> > enum rte_eth_nb_tcs nb_tcs = dcb_conf->nb_tcs;
> > if (nb_tcs != RTE_ETH_4_TCS && is_8_ports) {
> > @@ -3784,7 +3787,31 @@ check_dcb_conf(int is_8_ports, struct
> rte_eth_dcb_rx_conf *dcb_conf)
> > return -1;
> > }
> >
> > - return rte_popcount32(tc_map);
> > + nb_tc_used = rte_popcount32(tc_map);
> > +
> > + /* calculate total ETS Bandwidth allocation */
> > + for (i = 0; i < nb_tc_used; i++) {
> > + if (dcb_conf->dcb_tsa[i] == RTE_ETH_DCB_TSA_ETS) {
> > + if (dcb_conf->dcb_tc_bw[i] == 0) {
> > + PMD_DRV_LOG(ERR,
> > + "Bad ETS BW configuration, can not
> allocate 0%%");
> > + return -1;
> > + }
> > + total_bw_allocated += dcb_conf->dcb_tc_bw[i];
> > + ets_seen = true;
> > + } else if (dcb_conf->dcb_tsa[i] != RTE_ETH_DCB_TSA_STRICT)
> {
> > + PMD_DRV_LOG(ERR, "Invalid TC TSA setting - only
> Strict and ETS are supported");
> > + return -1;
> > + }
> > + }
> > +
> > + /* total ETS BW allocation must add up to 100% */
> > + if (ets_seen && total_bw_allocated != 100) {
> > + PMD_DRV_LOG(ERR, "Invalid TC Bandwidth allocation
> configuration");
> > + return -1;
> > + }
> > +
> > + return nb_tc_used;
> > }
> >
> > static int
> > @@ -3819,15 +3846,22 @@ ice_dev_configure(struct rte_eth_dev *dev)
> > struct ice_qos_cfg *qos_cfg = &port_info->qos_cfg;
> > struct ice_dcbx_cfg *local_dcb_conf =
> &qos_cfg->local_dcbx_cfg;
> > struct ice_vsi_ctx ctxt;
> > - struct rte_eth_dcb_rx_conf *dcb_conf =
> &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
> > + struct rte_eth_dcb_conf *rx_dcb_conf =
> > + &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
> > + struct rte_eth_dcb_conf *tx_dcb_conf =
> > + &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
> > int i;
> > - enum rte_eth_nb_tcs nb_tcs = dcb_conf->nb_tcs;
> > - int nb_tc_used, queues_per_tc;
> > + enum rte_eth_nb_tcs nb_tcs = rx_dcb_conf->nb_tcs;
> > + int nb_tc_used_rx, nb_tc_used_tx, queues_per_tc;
> > uint16_t total_q_nb;
> >
> > - nb_tc_used = check_dcb_conf(ice_get_port_max_cgd(hw) ==
> ICE_4_CGD_PER_PORT,
> > - dcb_conf);
> > - if (nb_tc_used < 0)
> > + nb_tc_used_rx = check_dcb_conf(ice_get_port_max_cgd(hw) ==
> ICE_4_CGD_PER_PORT,
> > + rx_dcb_conf);
> > + if (nb_tc_used_rx < 0)
> > + return -EINVAL;
> > + nb_tc_used_tx = check_dcb_conf(ice_get_port_max_cgd(hw) ==
> ICE_4_CGD_PER_PORT,
> > + tx_dcb_conf);
> > + if (nb_tc_used_tx < 0)
> > return -EINVAL;
> >
> > ctxt.info = vsi->info;
> > @@ -3837,8 +3871,8 @@ ice_dev_configure(struct rte_eth_dev *dev)
> > }
> >
> > total_q_nb = dev->data->nb_rx_queues;
> > - queues_per_tc = total_q_nb / nb_tc_used;
> > - if (total_q_nb % nb_tc_used != 0) {
> > + queues_per_tc = total_q_nb / nb_tc_used_rx;
> > + if (total_q_nb % nb_tc_used_rx != 0) {
> > PMD_DRV_LOG(ERR, "For DCB, number of queues must
> be evenly divisble by number of used TCs");
> > return -EINVAL;
> > } else if (!rte_is_power_of_2(queues_per_tc)) {
> > @@ -3846,7 +3880,7 @@ ice_dev_configure(struct rte_eth_dev *dev)
> > return -EINVAL;
> > }
> >
> > - for (i = 0; i < nb_tc_used; i++) {
> > + for (i = 0; i < nb_tc_used_rx; i++) {
> > ctxt.info.tc_mapping[i] =
> > rte_cpu_to_le_16(((i * queues_per_tc) <<
> ICE_AQ_VSI_TC_Q_OFFSET_S) |
> > (rte_log2_u32(queues_per_tc) <<
> ICE_AQ_VSI_TC_Q_NUM_S));
> > @@ -3858,29 +3892,21 @@ ice_dev_configure(struct rte_eth_dev *dev)
> >
> > /* Associate each VLAN UP with particular TC */
> > for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
> > - local_dcb_conf->etscfg.prio_table[i] =
> dcb_conf->dcb_tc[i];
> > - local_dcb_conf->etsrec.prio_table[i] =
> dcb_conf->dcb_tc[i];
> > + local_dcb_conf->etscfg.prio_table[i] =
> rx_dcb_conf->dcb_tc[i];
> > + local_dcb_conf->etsrec.prio_table[i] =
> tx_dcb_conf->dcb_tc[i];
> > }
> >
> > - /*
> > - * Since current API does not support setting ETS BW Share
> and Scheduler
> > - * configure all TC as ETS and evenly share load across
> all existing TC
> > - **/
> > - const int bw_share_percent = 100 / nb_tc_used;
> > - const int bw_share_left = 100 - bw_share_percent *
> nb_tc_used;
> > - for (i = 0; i < nb_tc_used; i++) {
> > + for (i = 0; i < nb_tc_used_rx; i++) {
> > /* Per TC bandwidth table (all valued must add up
> to 100%), valid on ETS */
> > - local_dcb_conf->etscfg.tcbwtable[i] =
> bw_share_percent;
> > - local_dcb_conf->etsrec.tcbwtable[i] =
> bw_share_percent;
> > + local_dcb_conf->etscfg.tcbwtable[i] =
> rx_dcb_conf->dcb_tc_bw[i];
> >
> > /**< Transmission Selection Algorithm. 0 - Strict
> prio, 2 - ETS */
> > - local_dcb_conf->etscfg.tsatable[i] = 2;
> > - local_dcb_conf->etsrec.tsatable[i] = 2;
> > + local_dcb_conf->etscfg.tsatable[i] =
> rx_dcb_conf->dcb_tsa[i];
> > }
> >
> > - for (i = 0; i < bw_share_left; i++) {
> > - local_dcb_conf->etscfg.tcbwtable[i]++;
> > - local_dcb_conf->etsrec.tcbwtable[i]++;
> > + for (i = 0; i < nb_tc_used_tx; i++) {
> > + local_dcb_conf->etsrec.tcbwtable[i] =
> tx_dcb_conf->dcb_tc_bw[i];
> > + local_dcb_conf->etsrec.tsatable[i] =
> tx_dcb_conf->dcb_tsa[i];
> > }
> >
> > local_dcb_conf->pfc.pfccap = nb_tcs;
> > diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> > index f9fb6ae549..13b1a41d3b 100644
> > --- a/lib/ethdev/rte_ethdev.h
> > +++ b/lib/ethdev/rte_ethdev.h
> > @@ -853,6 +853,7 @@ rte_eth_rss_hf_refine(uint64_t rss_hf)
> > /**@{@name VMDq and DCB maximums */
> > #define RTE_ETH_VMDQ_MAX_VLAN_FILTERS 64 /**< Maximum nb. of VMDq VLAN
> filters. */
> > #define RTE_ETH_DCB_NUM_USER_PRIORITIES 8 /**< Maximum nb. of DCB
> priorities. */
> > +#define RTE_ETH_DCB_NUM_TCS 8 /**< Maximum nb. of DCB traffic
> classes. */
> > #define RTE_ETH_VMDQ_DCB_NUM_QUEUES 128 /**< Maximum nb. of VMDq DCB
> queues. */
> > #define RTE_ETH_DCB_NUM_QUEUES 128 /**< Maximum nb. of DCB
> queues. */
> > /**@}*/
> > @@ -929,11 +930,21 @@ enum rte_eth_nb_pools {
> > RTE_ETH_64_POOLS = 64 /**< 64 VMDq pools. */
> > };
> >
> > +#define RTE_ETH_DCB_TSA_STRICT 0
> > +#define RTE_ETH_DCB_TSA_ETS 2
>
> Why not enum?
>
Agree, enum will be better
>
> > +
> > /* This structure may be extended in future. */
> > -struct rte_eth_dcb_rx_conf {
> > +struct rte_eth_dcb_conf {
> > enum rte_eth_nb_tcs nb_tcs; /**< Possible DCB TCs, 4 or 8 TCs */
> > - /** Traffic class each UP mapped to. */
> > + /** Traffic class each UP mapped to.
>
> Perhaps keep '/**' on a separate line in a multi-line comment.
>
> Thank you.
>
> > + * Rx packets VLAN UP for Rx configuration
> > + * Rx PFC Pause frames UP for Tx configuration
> > + */
> > uint8_t dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
> > + /** Traffic class selector algorithm */
> > + uint8_t dcb_tsa[RTE_ETH_DCB_NUM_TCS];
> > + /** Traffic class relative bandwidth in percents */
> > + uint8_t dcb_tc_bw[RTE_ETH_DCB_NUM_TCS];
> > };
> >
> > struct rte_eth_vmdq_dcb_tx_conf {
> > @@ -942,12 +953,6 @@ struct rte_eth_vmdq_dcb_tx_conf {
> > uint8_t dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
> > };
> >
> > -struct rte_eth_dcb_tx_conf {
> > - enum rte_eth_nb_tcs nb_tcs; /**< Possible DCB TCs, 4 or 8 TCs. */
> > - /** Traffic class each UP mapped to. */
> > - uint8_t dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
> > -};
> > -
> > struct rte_eth_vmdq_tx_conf {
> > enum rte_eth_nb_pools nb_queue_pools; /**< VMDq mode, 64 pools. */
> > };
> > @@ -1531,7 +1536,7 @@ struct rte_eth_conf {
> > /** Port VMDq+DCB configuration. */
> > struct rte_eth_vmdq_dcb_conf vmdq_dcb_conf;
> > /** Port DCB Rx configuration. */
> > - struct rte_eth_dcb_rx_conf dcb_rx_conf;
> > + struct rte_eth_dcb_conf dcb_rx_conf;
> > /** Port VMDq Rx configuration. */
> > struct rte_eth_vmdq_rx_conf vmdq_rx_conf;
> > } rx_adv_conf; /**< Port Rx filtering configuration. */
> > @@ -1539,7 +1544,7 @@ struct rte_eth_conf {
> > /** Port VMDq+DCB Tx configuration. */
> > struct rte_eth_vmdq_dcb_tx_conf vmdq_dcb_tx_conf;
> > /** Port DCB Tx configuration. */
> > - struct rte_eth_dcb_tx_conf dcb_tx_conf;
> > + struct rte_eth_dcb_conf dcb_tx_conf;
> > /** Port VMDq Tx configuration. */
> > struct rte_eth_vmdq_tx_conf vmdq_tx_conf;
> > } tx_adv_conf; /**< Port Tx DCB configuration (union). */
> > --
> > 2.43.0
> >
> >
>
--
Regards,
Vladimir
[-- Attachment #2: Type: text/html, Size: 17546 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 1/6] ethdev: extend and refactor DCB configuration
2025-08-30 19:57 ` Ivan Malov
@ 2025-08-31 15:01 ` Vladimir Medvedkin
0 siblings, 0 replies; 18+ messages in thread
From: Vladimir Medvedkin @ 2025-08-31 15:01 UTC (permalink / raw)
To: Ivan Malov
Cc: Vladimir Medvedkin, dev, bruce.richardson, anatoly.burakov,
thomas, andrew.rybchenko, stephen
[-- Attachment #1: Type: text/plain, Size: 503 bytes --]
Replied in a previous email
сб, 30 авг. 2025 г. в 20:57, Ivan Malov <ivan.malov@arknetworks.am>:
> On Sat, 30 Aug 2025, Vladimir Medvedkin wrote:
>
> > + /** Traffic class each UP mapped to.
> > + * Rx packets VLAN UP for Rx configuration
> > + * Rx PFC Pause frames UP for Tx configuration
>
> Is this confined to VLAN? Can the UP come from other headers of the packet?
> I apologise in case my question is wrong.
>
> Thank you.
>
--
Regards,
Vladimir
[-- Attachment #2: Type: text/html, Size: 1000 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 4/6] ethdev: extend VMDq/DCB configuration with queue mapping
2025-08-30 20:36 ` Ivan Malov
@ 2025-08-31 15:09 ` Vladimir Medvedkin
2025-08-31 15:57 ` Ivan Malov
0 siblings, 1 reply; 18+ messages in thread
From: Vladimir Medvedkin @ 2025-08-31 15:09 UTC (permalink / raw)
To: Ivan Malov
Cc: Vladimir Medvedkin, dev, bruce.richardson, anatoly.burakov,
thomas, andrew.rybchenko, stephen
[-- Attachment #1: Type: text/plain, Size: 17184 bytes --]
сб, 30 авг. 2025 г. в 21:54, Ivan Malov <ivan.malov@arknetworks.am>:
> Hi Vladimir,
>
> On Sat, 30 Aug 2025, Vladimir Medvedkin wrote:
>
> > Currently DCB Traffic Class queue mapping is only used when calling get
> > DCB info API, while setting up queue mappings is up to each individual
> > driver. Use the tc queue mapping structure to enable setting up custom
> > mapping explicitly.
> >
> > Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> > ---
> > app/test-pmd/testpmd.c | 57 ++++++++++++++++++------------
> > drivers/net/intel/ice/ice_ethdev.c | 39 ++++++++++----------
> > drivers/net/intel/ice/ice_rxtx.c | 27 +++++++-------
> > lib/ethdev/rte_ethdev.h | 43 +++++++++++-----------
> > 4 files changed, 92 insertions(+), 74 deletions(-)
> >
> > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> > index b5a7e7b3ee..3a55434d44 100644
> > --- a/app/test-pmd/testpmd.c
> > +++ b/app/test-pmd/testpmd.c
> > @@ -4158,6 +4158,16 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf,
> enum dcb_mode_enable dcb_mode,
> > struct rte_eth_dcb_conf *tx_conf =
> > ð_conf->tx_adv_conf.dcb_tx_conf;
> >
> > + struct rte_eth_dcb_tc_queue_mapping *q_map =
> ð_conf->q_map;
> > + memset(q_map, 0, sizeof(*q_map));
> > + int queues_per_tc = nb_rxq / num_tcs;
> > + for (i = 0; i < num_tcs; i++) {
> > + q_map->tc_rxq[0][i].base = i * queues_per_tc;
> > + q_map->tc_txq[0][i].base = i * queues_per_tc;
> > + q_map->tc_rxq[0][i].nb_queue = queues_per_tc;
> > + q_map->tc_txq[0][i].nb_queue = queues_per_tc;
> > + }
> > +
> > for (i = 0; i < RTE_ETH_DCB_NUM_USER_PRIORITIES; i++) {
> > dcb_tc_val = prio_tc_en ? prio_tc[i] : i % num_tcs;
> > rx_conf->dcb_tc[i] = dcb_tc_val;
> > @@ -4231,6 +4241,30 @@ init_port_dcb_config(portid_t pid,
> > /* retain the original device configuration. */
> > memcpy(&port_conf, &rte_port->dev_conf, sizeof(struct
> rte_eth_conf));
> >
> > + if (num_tcs > 1 && keep_qnum == 0) {
> > + /* Assume the ports in testpmd have the same dcb capability
> > + * and has the same number of rxq and txq in dcb mode
> > + */
> > + if (dcb_mode == DCB_VT_ENABLED) {
> > + if (rte_port->dev_info.max_vfs > 0) {
> > + nb_rxq = rte_port->dev_info.nb_rx_queues;
> > + nb_txq = rte_port->dev_info.nb_tx_queues;
> > + } else {
> > + nb_rxq = rte_port->dev_info.max_rx_queues;
> > + nb_txq = rte_port->dev_info.max_tx_queues;
> > + }
> > + } else {
> > + /*if vt is disabled, use all pf queues */
>
> Missing space between '/*' and 'if'.
>
> > + if (rte_port->dev_info.vmdq_pool_base == 0) {
> > + nb_rxq = rte_port->dev_info.max_rx_queues;
> > + nb_txq = rte_port->dev_info.max_tx_queues;
> > + } else {
> > + nb_rxq = (queueid_t)num_tcs;
> > + nb_txq = (queueid_t)num_tcs;
> > + }
> > + }
> > + }
> > +
> > if (num_tcs > 1) {
> > /* set configuration of DCB in vt mode and DCB in non-vt
> mode */
> > get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, pfc_en,
> prio_tc, prio_tc_en);
> > @@ -4267,29 +4301,6 @@ init_port_dcb_config(portid_t pid,
> > return -1;
> > }
> >
> > - if (num_tcs > 1 && keep_qnum == 0) {
> > - /* Assume the ports in testpmd have the same dcb capability
> > - * and has the same number of rxq and txq in dcb mode
> > - */
> > - if (dcb_mode == DCB_VT_ENABLED) {
> > - if (rte_port->dev_info.max_vfs > 0) {
> > - nb_rxq = rte_port->dev_info.nb_rx_queues;
> > - nb_txq = rte_port->dev_info.nb_tx_queues;
> > - } else {
> > - nb_rxq = rte_port->dev_info.max_rx_queues;
> > - nb_txq = rte_port->dev_info.max_tx_queues;
> > - }
> > - } else {
> > - /*if vt is disabled, use all pf queues */
> > - if (rte_port->dev_info.vmdq_pool_base == 0) {
> > - nb_rxq = rte_port->dev_info.max_rx_queues;
> > - nb_txq = rte_port->dev_info.max_tx_queues;
> > - } else {
> > - nb_rxq = (queueid_t)num_tcs;
> > - nb_txq = (queueid_t)num_tcs;
> > - }
> > - }
> > - }
> > rx_free_thresh = 64;
> >
> > memcpy(&rte_port->dev_conf, &port_conf, sizeof(struct
> rte_eth_conf));
> > diff --git a/drivers/net/intel/ice/ice_ethdev.c
> b/drivers/net/intel/ice/ice_ethdev.c
> > index ecde00182f..27559bbe18 100644
> > --- a/drivers/net/intel/ice/ice_ethdev.c
> > +++ b/drivers/net/intel/ice/ice_ethdev.c
> > @@ -3846,7 +3846,7 @@ ice_dev_configure(struct rte_eth_dev *dev)
> > struct rte_eth_dcb_conf *tx_dcb_conf =
> > &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
> > int i;
> > - int nb_tc_used_rx, nb_tc_used_tx, queues_per_tc;
> > + int nb_tc_used_rx, nb_tc_used_tx;
> > uint16_t total_q_nb;
> >
> > nb_tc_used_rx = check_dcb_conf(ice_get_port_max_cgd(hw) ==
> ICE_4_CGD_PER_PORT,
> > @@ -3865,19 +3865,23 @@ ice_dev_configure(struct rte_eth_dev *dev)
> > }
> >
> > total_q_nb = dev->data->nb_rx_queues;
> > - queues_per_tc = total_q_nb / nb_tc_used_rx;
> > - if (total_q_nb % nb_tc_used_rx != 0) {
> > - PMD_DRV_LOG(ERR, "For DCB, number of queues must
> be evenly divisble by number of used TCs");
> > - return -EINVAL;
> > - } else if (!rte_is_power_of_2(queues_per_tc)) {
> > - PMD_DRV_LOG(ERR, "For DCB, number of queues per TC
> must be a power of 2");
> > - return -EINVAL;
> > - }
> > -
> > + struct rte_eth_dcb_tc_queue_mapping *q_map =
> &dev->data->dev_conf.q_map;
> > for (i = 0; i < nb_tc_used_rx; i++) {
> > + if (q_map->tc_rxq[0][i].nb_queue != 0 &&
>
> How is 'nb_queue == 0' case handled here and below? Should some
> driver-default
> fill-in be used, similar to code being deleted above?
>
> Or is '(0 << ICE_AQ_VSI_TC_Q_OFFSET_S) | (0 << ICE_AQ_VSI_TC_Q_NUM_S)'
> legit?
>
Yes, this is legit. In this case packets arriving to the corresponding TC
will be sent to the default queue (i.e. the first queue).
>
> > +
> !rte_is_power_of_2(q_map->tc_rxq[0][i].nb_queue)) {
> > + PMD_DRV_LOG(ERR, "For DCB, number of
> queues per TC must be a power of 2");
> > + return -EINVAL;
> > + }
> > + if ((q_map->tc_rxq[0][i].base +
> q_map->tc_rxq[0][i].nb_queue) > total_q_nb) {
> > + PMD_DRV_LOG(ERR, "Queue range for TC %d
> exceeds total number of queues",
> > + i);
> > + return -EINVAL;
> > + }
> > ctxt.info.tc_mapping[i] =
> > - rte_cpu_to_le_16(((i * queues_per_tc) <<
> ICE_AQ_VSI_TC_Q_OFFSET_S) |
> > - (rte_log2_u32(queues_per_tc) <<
> ICE_AQ_VSI_TC_Q_NUM_S));
> > + rte_cpu_to_le_16((q_map->tc_rxq[0][i].base
> <<
> > + ICE_AQ_VSI_TC_Q_OFFSET_S) |
> > +
> (rte_log2_u32(q_map->tc_rxq[0][i].nb_queue) <<
> > + ICE_AQ_VSI_TC_Q_NUM_S));
>
> This seems to always use pool [0] but does not seem to check if 'nb_queue'
> in,
> say, pool [1] is non-zero, to return an error or something. Or is this
> unneeded?
>
Yes, this is unneeded. DCB with VMDq is not supported in ice PMD. In more
detail, we do not support VMDq1, where per-VM queue ranges are "exposed"
like in older ixgbe HW. Instead we support VMDq2, where each per-VM queue
range is covered under VSI (think of it as a virtual interface) abstraction
layer.
For queue mapping I reuse the existing structure, which is used
with rte_eth_dev_get_dcb_info() API. Maybe it is better to create a
dedicated queue mapping structure without all VMDq-related stuff?
>
> > }
> >
> > memset(local_dcb_conf, 0, sizeof(*local_dcb_conf));
> > @@ -3941,6 +3945,7 @@ ice_get_dcb_info(struct rte_eth_dev *dev, struct
> rte_eth_dcb_info *dcb_info)
> > struct ice_dcbx_cfg *dcb_conf = &qos_cfg->local_dcbx_cfg;
> > struct ice_vsi *vsi = pf->main_vsi;
> > struct ice_vsi_ctx ctxt = { 0 };
> > + struct rte_eth_dcb_tc_queue_mapping *q_map =
> &dev->data->dev_conf.q_map;
> >
> > ctxt.info = vsi->info;
> > if (rte_le_to_cpu_16(ctxt.info.mapping_flags) ==
> ICE_AQ_VSI_Q_MAP_NONCONTIG) {
> > @@ -3953,13 +3958,11 @@ ice_get_dcb_info(struct rte_eth_dev *dev, struct
> rte_eth_dcb_info *dcb_info)
> > dcb_info->prio_tc[i] = dcb_conf->etscfg.prio_table[i];
> > dcb_info->tc_bws[i] = dcb_conf->etscfg.tcbwtable[i];
> > /* Using VMDQ pool zero since DCB+VMDQ is not supported */
> > - uint16_t tc_rx_q_map =
> rte_le_to_cpu_16(ctxt.info.tc_mapping[i]);
> > - dcb_info->tc_queue.tc_rxq[0][i].base = tc_rx_q_map &
> ICE_AQ_VSI_TC_Q_OFFSET_M;
> > - dcb_info->tc_queue.tc_rxq[0][i].nb_queue =
> > - 1 << ((tc_rx_q_map & ICE_AQ_VSI_TC_Q_NUM_M) >>
> ICE_AQ_VSI_TC_Q_NUM_S);
> > + dcb_info->tc_queue.tc_rxq[0][i].base =
> q_map->tc_rxq[0][i].base;
> > + dcb_info->tc_queue.tc_rxq[0][i].nb_queue =
> q_map->tc_rxq[0][i].nb_queue;
> >
> > - dcb_info->tc_queue.tc_txq[0][i].base =
> dcb_info->tc_queue.tc_rxq[0][i].base;
> > - dcb_info->tc_queue.tc_txq[0][i].nb_queue =
> dcb_info->tc_queue.tc_rxq[0][i].nb_queue;
> > + dcb_info->tc_queue.tc_txq[0][i].base =
> q_map->tc_txq[0][i].base;
> > + dcb_info->tc_queue.tc_txq[0][i].nb_queue =
> q_map->tc_txq[0][i].nb_queue;
> > }
> >
> > return 0;
> > diff --git a/drivers/net/intel/ice/ice_rxtx.c
> b/drivers/net/intel/ice/ice_rxtx.c
> > index 451816affd..55424e7a23 100644
> > --- a/drivers/net/intel/ice/ice_rxtx.c
> > +++ b/drivers/net/intel/ice/ice_rxtx.c
> > @@ -796,6 +796,7 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t
> tx_queue_id)
> > int buf_len;
> > struct ice_adapter *ad =
> ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
> > u16 q_base, q_range, cgd_idx = 0;
> > + struct rte_eth_dcb_tc_queue_mapping *q_map =
> &dev->data->dev_conf.q_map;
> >
> > PMD_INIT_FUNC_TRACE();
> >
> > @@ -840,22 +841,22 @@ ice_tx_queue_start(struct rte_eth_dev *dev,
> uint16_t tx_queue_id)
> > tx_ctx.legacy_int = 1; /* Legacy or Advanced Host Interface */
> > tx_ctx.tsyn_ena = 1;
> >
> > - /* Mirror RXQ<->CGD association to TXQ<->CDG */
> > - for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
> > - q_base = rte_le_to_cpu_16(vsi->info.tc_mapping[i]) &
> ICE_AQ_VSI_TC_Q_OFFSET_M;
> > - q_range = 1 << ((rte_le_to_cpu_16(vsi->info.tc_mapping[i])
> &
> > - ICE_AQ_VSI_TC_Q_NUM_M) >> ICE_AQ_VSI_TC_Q_NUM_S);
> > + if (dev->data->dev_conf.txmode.mq_mode == RTE_ETH_MQ_TX_DCB) {
> > + for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
> > + q_base = q_map->tc_txq[0][i].base;
> > + q_range = q_map->tc_txq[0][i].nb_queue;
> >
> > - if (q_base <= tx_queue_id && tx_queue_id < q_base +
> q_range)
> > - break;
> > + if (q_base <= tx_queue_id && tx_queue_id < q_base
> + q_range)
> > + break;
> >
> > - cgd_idx++;
> > - }
> > + cgd_idx++;
> > + }
> >
> > - if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
> > - PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
> > - rte_free(txq_elem);
> > - return -EINVAL;
> > + if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
> > + PMD_DRV_LOG(ERR, "Bad queue mapping
> configuration");
> > + rte_free(txq_elem);
> > + return -EINVAL;
> > + }
> > }
> >
> > tx_ctx.cgd_num = cgd_idx;
> > diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> > index c220760043..0bd86e1e7d 100644
> > --- a/lib/ethdev/rte_ethdev.h
> > +++ b/lib/ethdev/rte_ethdev.h
> > @@ -1472,6 +1472,26 @@ struct rte_eth_intr_conf {
> >
> > #define rte_intr_conf rte_eth_intr_conf
> >
> > +#define RTE_ETH_DCB_NUM_TCS 8
> > +#define RTE_ETH_MAX_VMDQ_POOL 64
> > +
> > +/**
> > + * A structure used to get the information of queue and
> > + * TC mapping on both Tx and Rx paths.
> > + */
> > +struct rte_eth_dcb_tc_queue_mapping {
> > + /** Rx queues assigned to tc per Pool */
> > + struct {
> > + uint16_t base;
> > + uint16_t nb_queue;
> > + } tc_rxq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> > + /** Rx queues assigned to tc per Pool */
> > + struct {
> > + uint16_t base;
> > + uint16_t nb_queue;
> > + } tc_txq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> > +};
> > +
> > /**
> > * A structure used to configure an Ethernet port.
> > * Depending upon the Rx multi-queue mode, extra advanced
> > @@ -1492,18 +1512,21 @@ struct rte_eth_conf {
> > Read the datasheet of given Ethernet
> controller
> > for details. The possible values of this
> field
> > are defined in implementation of each
> driver. */
> > + struct rte_eth_dcb_tc_queue_mapping q_map;
>
> Is the driver supposed to tell 'q_map' is valid by looking at [0][0]
> 'nb_queue'?
>
Could you please clarify what validity criteria for the [0][0] 'nb_queue'
do you mean?
>
> > struct {
> > struct rte_eth_rss_conf rss_conf; /**< Port RSS
> configuration */
> > /** Port DCB Rx configuration. */
> > struct rte_eth_dcb_conf dcb_rx_conf;
> > /** Port VMDq Rx configuration. */
> > struct rte_eth_vmdq_rx_conf vmdq_rx_conf;
> > + /* VMDQ and DCB Rx queue mapping configuration. */
>
> Perhaps it's better to have just one such comment right before 'q_map'.
>
Oh, my bad, last minute rework, thanks!
>
> Thank you.
>
> > } rx_adv_conf; /**< Port Rx filtering configuration. */
> > struct {
> > /** Port DCB Tx configuration. */
> > struct rte_eth_dcb_conf dcb_tx_conf;
> > /** Port VMDq Tx configuration. */
> > struct rte_eth_vmdq_tx_conf vmdq_tx_conf;
> > + /* VMDQ and DCB Tx queue mapping configuration. */
> > } tx_adv_conf; /**< Port Tx DCB configuration (union). */
> > /** Currently,Priority Flow Control(PFC) are supported,if DCB with
> PFC
> > is needed,and the variable must be set
> RTE_ETH_DCB_PFC_SUPPORT. */
> > @@ -1930,26 +1953,6 @@ struct rte_eth_xstat_name {
> > char name[RTE_ETH_XSTATS_NAME_SIZE]; /**< The statistic name. */
> > };
> >
> > -#define RTE_ETH_DCB_NUM_TCS 8
> > -#define RTE_ETH_MAX_VMDQ_POOL 64
> > -
> > -/**
> > - * A structure used to get the information of queue and
> > - * TC mapping on both Tx and Rx paths.
> > - */
> > -struct rte_eth_dcb_tc_queue_mapping {
> > - /** Rx queues assigned to tc per Pool */
> > - struct {
> > - uint16_t base;
> > - uint16_t nb_queue;
> > - } tc_rxq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> > - /** Rx queues assigned to tc per Pool */
> > - struct {
> > - uint16_t base;
> > - uint16_t nb_queue;
> > - } tc_txq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> > -};
> > -
> > /**
> > * A structure used to get the information of DCB.
> > * It includes TC UP mapping and queue TC mapping.
> > --
> > 2.43.0
> >
> >
>
--
Regards,
Vladimir
[-- Attachment #2: Type: text/html, Size: 22358 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 4/6] ethdev: extend VMDq/DCB configuration with queue mapping
2025-08-31 15:09 ` Vladimir Medvedkin
@ 2025-08-31 15:57 ` Ivan Malov
0 siblings, 0 replies; 18+ messages in thread
From: Ivan Malov @ 2025-08-31 15:57 UTC (permalink / raw)
To: Vladimir Medvedkin
Cc: Vladimir Medvedkin, dev, bruce.richardson, anatoly.burakov,
thomas, andrew.rybchenko, stephen
[-- Attachment #1: Type: text/plain, Size: 21164 bytes --]
Hi Vladimir,
Thanks for the response. Please see below.
On Sun, 31 Aug 2025, Vladimir Medvedkin wrote:
>
>
> сб, 30 авг. 2025 г. в 21:54, Ivan Malov <ivan.malov@arknetworks.am>:
> Hi Vladimir,
>
> On Sat, 30 Aug 2025, Vladimir Medvedkin wrote:
>
> > Currently DCB Traffic Class queue mapping is only used when calling get
> > DCB info API, while setting up queue mappings is up to each individual
> > driver. Use the tc queue mapping structure to enable setting up custom
> > mapping explicitly.
> >
> > Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> > ---
> > app/test-pmd/testpmd.c | 57 ++++++++++++++++++------------
> > drivers/net/intel/ice/ice_ethdev.c | 39 ++++++++++----------
> > drivers/net/intel/ice/ice_rxtx.c | 27 +++++++-------
> > lib/ethdev/rte_ethdev.h | 43 +++++++++++-----------
> > 4 files changed, 92 insertions(+), 74 deletions(-)
> >
> > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> > index b5a7e7b3ee..3a55434d44 100644
> > --- a/app/test-pmd/testpmd.c
> > +++ b/app/test-pmd/testpmd.c
> > @@ -4158,6 +4158,16 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, enum dcb_mode_enable dcb_mode,
> > struct rte_eth_dcb_conf *tx_conf =
> > ð_conf->tx_adv_conf.dcb_tx_conf;
> >
> > + struct rte_eth_dcb_tc_queue_mapping *q_map = ð_conf->q_map;
> > + memset(q_map, 0, sizeof(*q_map));
> > + int queues_per_tc = nb_rxq / num_tcs;
> > + for (i = 0; i < num_tcs; i++) {
> > + q_map->tc_rxq[0][i].base = i * queues_per_tc;
> > + q_map->tc_txq[0][i].base = i * queues_per_tc;
> > + q_map->tc_rxq[0][i].nb_queue = queues_per_tc;
> > + q_map->tc_txq[0][i].nb_queue = queues_per_tc;
> > + }
> > +
> > for (i = 0; i < RTE_ETH_DCB_NUM_USER_PRIORITIES; i++) {
> > dcb_tc_val = prio_tc_en ? prio_tc[i] : i % num_tcs;
> > rx_conf->dcb_tc[i] = dcb_tc_val;
> > @@ -4231,6 +4241,30 @@ init_port_dcb_config(portid_t pid,
> > /* retain the original device configuration. */
> > memcpy(&port_conf, &rte_port->dev_conf, sizeof(struct rte_eth_conf));
> >
> > + if (num_tcs > 1 && keep_qnum == 0) {
> > + /* Assume the ports in testpmd have the same dcb capability
> > + * and has the same number of rxq and txq in dcb mode
> > + */
> > + if (dcb_mode == DCB_VT_ENABLED) {
> > + if (rte_port->dev_info.max_vfs > 0) {
> > + nb_rxq = rte_port->dev_info.nb_rx_queues;
> > + nb_txq = rte_port->dev_info.nb_tx_queues;
> > + } else {
> > + nb_rxq = rte_port->dev_info.max_rx_queues;
> > + nb_txq = rte_port->dev_info.max_tx_queues;
> > + }
> > + } else {
> > + /*if vt is disabled, use all pf queues */
>
> Missing space between '/*' and 'if'.
>
> > + if (rte_port->dev_info.vmdq_pool_base == 0) {
> > + nb_rxq = rte_port->dev_info.max_rx_queues;
> > + nb_txq = rte_port->dev_info.max_tx_queues;
> > + } else {
> > + nb_rxq = (queueid_t)num_tcs;
> > + nb_txq = (queueid_t)num_tcs;
> > + }
> > + }
> > + }
> > +
> > if (num_tcs > 1) {
> > /* set configuration of DCB in vt mode and DCB in non-vt mode */
> > get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, pfc_en, prio_tc, prio_tc_en);
> > @@ -4267,29 +4301,6 @@ init_port_dcb_config(portid_t pid,
> > return -1;
> > }
> >
> > - if (num_tcs > 1 && keep_qnum == 0) {
> > - /* Assume the ports in testpmd have the same dcb capability
> > - * and has the same number of rxq and txq in dcb mode
> > - */
> > - if (dcb_mode == DCB_VT_ENABLED) {
> > - if (rte_port->dev_info.max_vfs > 0) {
> > - nb_rxq = rte_port->dev_info.nb_rx_queues;
> > - nb_txq = rte_port->dev_info.nb_tx_queues;
> > - } else {
> > - nb_rxq = rte_port->dev_info.max_rx_queues;
> > - nb_txq = rte_port->dev_info.max_tx_queues;
> > - }
> > - } else {
> > - /*if vt is disabled, use all pf queues */
> > - if (rte_port->dev_info.vmdq_pool_base == 0) {
> > - nb_rxq = rte_port->dev_info.max_rx_queues;
> > - nb_txq = rte_port->dev_info.max_tx_queues;
> > - } else {
> > - nb_rxq = (queueid_t)num_tcs;
> > - nb_txq = (queueid_t)num_tcs;
> > - }
> > - }
> > - }
> > rx_free_thresh = 64;
> >
> > memcpy(&rte_port->dev_conf, &port_conf, sizeof(struct rte_eth_conf));
> > diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
> > index ecde00182f..27559bbe18 100644
> > --- a/drivers/net/intel/ice/ice_ethdev.c
> > +++ b/drivers/net/intel/ice/ice_ethdev.c
> > @@ -3846,7 +3846,7 @@ ice_dev_configure(struct rte_eth_dev *dev)
> > struct rte_eth_dcb_conf *tx_dcb_conf =
> > &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
> > int i;
> > - int nb_tc_used_rx, nb_tc_used_tx, queues_per_tc;
> > + int nb_tc_used_rx, nb_tc_used_tx;
> > uint16_t total_q_nb;
> >
> > nb_tc_used_rx = check_dcb_conf(ice_get_port_max_cgd(hw) == ICE_4_CGD_PER_PORT,
> > @@ -3865,19 +3865,23 @@ ice_dev_configure(struct rte_eth_dev *dev)
> > }
> >
> > total_q_nb = dev->data->nb_rx_queues;
> > - queues_per_tc = total_q_nb / nb_tc_used_rx;
> > - if (total_q_nb % nb_tc_used_rx != 0) {
> > - PMD_DRV_LOG(ERR, "For DCB, number of queues must be evenly divisble by number of used TCs");
> > - return -EINVAL;
> > - } else if (!rte_is_power_of_2(queues_per_tc)) {
> > - PMD_DRV_LOG(ERR, "For DCB, number of queues per TC must be a power of 2");
> > - return -EINVAL;
> > - }
> > -
> > + struct rte_eth_dcb_tc_queue_mapping *q_map = &dev->data->dev_conf.q_map;
> > for (i = 0; i < nb_tc_used_rx; i++) {
> > + if (q_map->tc_rxq[0][i].nb_queue != 0 &&
>
> How is 'nb_queue == 0' case handled here and below? Should some driver-default
> fill-in be used, similar to code being deleted above?
>
> Or is '(0 << ICE_AQ_VSI_TC_Q_OFFSET_S) | (0 << ICE_AQ_VSI_TC_Q_NUM_S)' legit?
>
>
> Yes, this is legit. In this case packets arriving to the corresponding TC will be sent to the default queue (i.e. the first queue).
>
>
> > + !rte_is_power_of_2(q_map->tc_rxq[0][i].nb_queue)) {
> > + PMD_DRV_LOG(ERR, "For DCB, number of queues per TC must be a power of 2");
> > + return -EINVAL;
> > + }
> > + if ((q_map->tc_rxq[0][i].base + q_map->tc_rxq[0][i].nb_queue) > total_q_nb) {
> > + PMD_DRV_LOG(ERR, "Queue range for TC %d exceeds total number of queues",
> > + i);
> > + return -EINVAL;
> > + }
> > ctxt.info.tc_mapping[i] =
> > - rte_cpu_to_le_16(((i * queues_per_tc) << ICE_AQ_VSI_TC_Q_OFFSET_S) |
> > - (rte_log2_u32(queues_per_tc) << ICE_AQ_VSI_TC_Q_NUM_S));
> > + rte_cpu_to_le_16((q_map->tc_rxq[0][i].base <<
> > + ICE_AQ_VSI_TC_Q_OFFSET_S) |
> > + (rte_log2_u32(q_map->tc_rxq[0][i].nb_queue) <<
> > + ICE_AQ_VSI_TC_Q_NUM_S));
>
> This seems to always use pool [0] but does not seem to check if 'nb_queue' in,
> say, pool [1] is non-zero, to return an error or something. Or is this unneeded?
>
>
> Yes, this is unneeded. DCB with VMDq is not supported in ice PMD. In more detail, we do not support VMDq1, where per-VM queue ranges are "exposed" like in older ixgbe HW. Instead we
> support VMDq2, where each per-VM queue range is covered under VSI (think of it as a virtual interface) abstraction layer.
If this lack of support for VMDq1 is somehow expressed via device capabilities,
then OK. At first I thought that if the rogue application filled in tc_rxq[1..63]
in disregard of capability report, then the driver could check and reject that.
> For queue mapping I reuse the existing structure, which is used with rte_eth_dev_get_dcb_info() API. Maybe it is better to create a dedicated queue mapping structure without all
> VMDq-related stuff?
May be it is better to reuse the existing structure, but I don't have a strong
opinion. Perhaps other vendors can express their thoughts.
>
>
> > }
> >
> > memset(local_dcb_conf, 0, sizeof(*local_dcb_conf));
> > @@ -3941,6 +3945,7 @@ ice_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
> > struct ice_dcbx_cfg *dcb_conf = &qos_cfg->local_dcbx_cfg;
> > struct ice_vsi *vsi = pf->main_vsi;
> > struct ice_vsi_ctx ctxt = { 0 };
> > + struct rte_eth_dcb_tc_queue_mapping *q_map = &dev->data->dev_conf.q_map;
> >
> > ctxt.info = vsi->info;
> > if (rte_le_to_cpu_16(ctxt.info.mapping_flags) == ICE_AQ_VSI_Q_MAP_NONCONTIG) {
> > @@ -3953,13 +3958,11 @@ ice_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
> > dcb_info->prio_tc[i] = dcb_conf->etscfg.prio_table[i];
> > dcb_info->tc_bws[i] = dcb_conf->etscfg.tcbwtable[i];
> > /* Using VMDQ pool zero since DCB+VMDQ is not supported */
> > - uint16_t tc_rx_q_map = rte_le_to_cpu_16(ctxt.info.tc_mapping[i]);
> > - dcb_info->tc_queue.tc_rxq[0][i].base = tc_rx_q_map & ICE_AQ_VSI_TC_Q_OFFSET_M;
> > - dcb_info->tc_queue.tc_rxq[0][i].nb_queue =
> > - 1 << ((tc_rx_q_map & ICE_AQ_VSI_TC_Q_NUM_M) >> ICE_AQ_VSI_TC_Q_NUM_S);
> > + dcb_info->tc_queue.tc_rxq[0][i].base = q_map->tc_rxq[0][i].base;
> > + dcb_info->tc_queue.tc_rxq[0][i].nb_queue = q_map->tc_rxq[0][i].nb_queue;
> >
> > - dcb_info->tc_queue.tc_txq[0][i].base = dcb_info->tc_queue.tc_rxq[0][i].base;
> > - dcb_info->tc_queue.tc_txq[0][i].nb_queue = dcb_info->tc_queue.tc_rxq[0][i].nb_queue;
> > + dcb_info->tc_queue.tc_txq[0][i].base = q_map->tc_txq[0][i].base;
> > + dcb_info->tc_queue.tc_txq[0][i].nb_queue = q_map->tc_txq[0][i].nb_queue;
> > }
> >
> > return 0;
> > diff --git a/drivers/net/intel/ice/ice_rxtx.c b/drivers/net/intel/ice/ice_rxtx.c
> > index 451816affd..55424e7a23 100644
> > --- a/drivers/net/intel/ice/ice_rxtx.c
> > +++ b/drivers/net/intel/ice/ice_rxtx.c
> > @@ -796,6 +796,7 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
> > int buf_len;
> > struct ice_adapter *ad = ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
> > u16 q_base, q_range, cgd_idx = 0;
> > + struct rte_eth_dcb_tc_queue_mapping *q_map = &dev->data->dev_conf.q_map;
> >
> > PMD_INIT_FUNC_TRACE();
> >
> > @@ -840,22 +841,22 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
> > tx_ctx.legacy_int = 1; /* Legacy or Advanced Host Interface */
> > tx_ctx.tsyn_ena = 1;
> >
> > - /* Mirror RXQ<->CGD association to TXQ<->CDG */
> > - for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
> > - q_base = rte_le_to_cpu_16(vsi->info.tc_mapping[i]) & ICE_AQ_VSI_TC_Q_OFFSET_M;
> > - q_range = 1 << ((rte_le_to_cpu_16(vsi->info.tc_mapping[i]) &
> > - ICE_AQ_VSI_TC_Q_NUM_M) >> ICE_AQ_VSI_TC_Q_NUM_S);
> > + if (dev->data->dev_conf.txmode.mq_mode == RTE_ETH_MQ_TX_DCB) {
> > + for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
> > + q_base = q_map->tc_txq[0][i].base;
> > + q_range = q_map->tc_txq[0][i].nb_queue;
> >
> > - if (q_base <= tx_queue_id && tx_queue_id < q_base + q_range)
> > - break;
> > + if (q_base <= tx_queue_id && tx_queue_id < q_base + q_range)
> > + break;
> >
> > - cgd_idx++;
> > - }
> > + cgd_idx++;
> > + }
> >
> > - if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
> > - PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
> > - rte_free(txq_elem);
> > - return -EINVAL;
> > + if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
> > + PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
> > + rte_free(txq_elem);
> > + return -EINVAL;
> > + }
> > }
> >
> > tx_ctx.cgd_num = cgd_idx;
> > diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> > index c220760043..0bd86e1e7d 100644
> > --- a/lib/ethdev/rte_ethdev.h
> > +++ b/lib/ethdev/rte_ethdev.h
> > @@ -1472,6 +1472,26 @@ struct rte_eth_intr_conf {
> >
> > #define rte_intr_conf rte_eth_intr_conf
> >
> > +#define RTE_ETH_DCB_NUM_TCS 8
> > +#define RTE_ETH_MAX_VMDQ_POOL 64
> > +
> > +/**
> > + * A structure used to get the information of queue and
> > + * TC mapping on both Tx and Rx paths.
> > + */
> > +struct rte_eth_dcb_tc_queue_mapping {
> > + /** Rx queues assigned to tc per Pool */
> > + struct {
> > + uint16_t base;
> > + uint16_t nb_queue;
> > + } tc_rxq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> > + /** Rx queues assigned to tc per Pool */
> > + struct {
> > + uint16_t base;
> > + uint16_t nb_queue;
> > + } tc_txq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> > +};
> > +
> > /**
> > * A structure used to configure an Ethernet port.
> > * Depending upon the Rx multi-queue mode, extra advanced
> > @@ -1492,18 +1512,21 @@ struct rte_eth_conf {
> > Read the datasheet of given Ethernet controller
> > for details. The possible values of this field
> > are defined in implementation of each driver. */
> > + struct rte_eth_dcb_tc_queue_mapping q_map;
>
> Is the driver supposed to tell 'q_map' is valid by looking at [0][0] 'nb_queue'?
>
>
> Could you please clarify what validity criteria for the [0][0] 'nb_queue' do you mean?
I mean the hypothetical situation where the vendor does not allow the user to
customise the queue pools and thus has to check whether the user has tried to
use this structure in 'adv_rx_conf' and reject that. Or is that pointless?
Thank you.
>
>
> > struct {
> > struct rte_eth_rss_conf rss_conf; /**< Port RSS configuration */
> > /** Port DCB Rx configuration. */
> > struct rte_eth_dcb_conf dcb_rx_conf;
> > /** Port VMDq Rx configuration. */
> > struct rte_eth_vmdq_rx_conf vmdq_rx_conf;
> > + /* VMDQ and DCB Rx queue mapping configuration. */
>
> Perhaps it's better to have just one such comment right before 'q_map'.
>
>
> Oh, my bad, last minute rework, thanks!
>
>
> Thank you.
>
> > } rx_adv_conf; /**< Port Rx filtering configuration. */
> > struct {
> > /** Port DCB Tx configuration. */
> > struct rte_eth_dcb_conf dcb_tx_conf;
> > /** Port VMDq Tx configuration. */
> > struct rte_eth_vmdq_tx_conf vmdq_tx_conf;
> > + /* VMDQ and DCB Tx queue mapping configuration. */
> > } tx_adv_conf; /**< Port Tx DCB configuration (union). */
> > /** Currently,Priority Flow Control(PFC) are supported,if DCB with PFC
> > is needed,and the variable must be set RTE_ETH_DCB_PFC_SUPPORT. */
> > @@ -1930,26 +1953,6 @@ struct rte_eth_xstat_name {
> > char name[RTE_ETH_XSTATS_NAME_SIZE]; /**< The statistic name. */
> > };
> >
> > -#define RTE_ETH_DCB_NUM_TCS 8
> > -#define RTE_ETH_MAX_VMDQ_POOL 64
> > -
> > -/**
> > - * A structure used to get the information of queue and
> > - * TC mapping on both Tx and Rx paths.
> > - */
> > -struct rte_eth_dcb_tc_queue_mapping {
> > - /** Rx queues assigned to tc per Pool */
> > - struct {
> > - uint16_t base;
> > - uint16_t nb_queue;
> > - } tc_rxq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> > - /** Rx queues assigned to tc per Pool */
> > - struct {
> > - uint16_t base;
> > - uint16_t nb_queue;
> > - } tc_txq[RTE_ETH_MAX_VMDQ_POOL][RTE_ETH_DCB_NUM_TCS];
> > -};
> > -
> > /**
> > * A structure used to get the information of DCB.
> > * It includes TC UP mapping and queue TC mapping.
> > --
> > 2.43.0
> >
> >
>
>
>
> --
> Regards,
> Vladimir
>
>
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2025-08-31 15:57 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-08-30 17:17 [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Vladimir Medvedkin
2025-08-30 17:17 ` [RFC PATCH 1/6] ethdev: extend and refactor DCB configuration Vladimir Medvedkin
2025-08-30 19:52 ` Ivan Malov
2025-08-31 15:00 ` Vladimir Medvedkin
2025-08-30 19:57 ` Ivan Malov
2025-08-31 15:01 ` Vladimir Medvedkin
2025-08-30 17:17 ` [RFC PATCH 2/6] ethdev: remove nb_tcs from rte_eth_dcb_conf structure Vladimir Medvedkin
2025-08-30 17:17 ` [RFC PATCH 3/6] ethdev: decouple VMDq and DCB cofiguration Vladimir Medvedkin
2025-08-30 17:17 ` [RFC PATCH 4/6] ethdev: extend VMDq/DCB configuration with queue mapping Vladimir Medvedkin
2025-08-30 20:36 ` Ivan Malov
2025-08-31 15:09 ` Vladimir Medvedkin
2025-08-31 15:57 ` Ivan Malov
2025-08-30 17:17 ` [RFC PATCH 5/6] ethdev: remove dcb_capability_en from rte_eth_conf Vladimir Medvedkin
2025-08-30 20:46 ` Ivan Malov
2025-08-30 20:49 ` Ivan Malov
2025-08-30 17:17 ` [RFC PATCH 6/6] ethdev: move mq_mode to [r,t]x_adv_conf Vladimir Medvedkin
2025-08-30 21:13 ` [RFC PATCH 0/6] ethdev: refactor and extend DCB configuration API Ivan Malov
2025-08-31 14:55 ` Vladimir Medvedkin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).