Fix DCB forwarding failed when the number of TCs on ports is inconsistent.
When ports have asymmetric TC configurations (e.g. 2 ports, port0 has
4 TCs and port1 has 8 TCs), the forwarding logic iterates based only
on the Rx port TC count.
This can lead to accessing invalid Tx TC entries and incorrect queue
mapping, which will result in a SIGFPE exception.
Additionally, the existing VMDq pool guard in dcb_fwd_config_setup()
only checks RX queue counts and does not consider the case where the TX
port has no queues for a given pool/TC combination.
Fix this by:
1. Introducing an effective TC count using RTE_MIN() of Rx and Tx TC
values, ensuring forwarding only operates on valid TCs supported by
both ports.
2. Updating the loop condition to use the effective TC count instead of
only the Rx TC count.
3. Extending the queue validation in dcb_fwd_config_setup() to ensure
both Rx and Tx queues are valid for a given TC.
Testpmd command to reproduce:
x86_64-native-linuxapp-gcc/app/dpdk-testpmd -l 1-20 -n 4 \
-a 0000:31:00.0 -a 0000:4b:00.0 \
--file-prefix=testpmd1 -- -i --rxq=256 --txq=256 \
--nb-cores=16 --total-num-mbufs=600000
port stop all
port config 0 dcb vt off 8 pfc on
port config 1 dcb vt off 8 pfc on
port start all
port stop all
port config 0 dcb vt off 4 pfc on
This ensures correct queue mapping and avoids issues when switching
between different DCB configurations across ports.
Fixes: 1a572499beb6 ("app/testpmd: setup DCB forwarding based on traffic class")
Cc: [email protected]
Signed-off-by: Talluri Chaitanyababu <[email protected]>
Signed-off-by: Shaiq Wani <[email protected]>
---
v5:
* Updated commit message as per review comments.
* Added reproduction steps and SIGFPE explanation.
* Updated Fixes tag.
v4:
* Removed runtime update of dcb_fwd_tc_mask as per review comments.
* Used effective TC count (RTE_MIN of RX/TX) to handle asymmetric configs.
* Moved queue validation to dcb_fwd_check_cores_per_tc().
v3: Removed old email address.
v2:
* Used res->num_tcs to derive dcb_fwd_tc_mask.
* Removed redundant rte_eth_dev_get_dcb_info().
---
app/test-pmd/config.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index f9f3c542a6..052e8b7c24 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -5377,6 +5377,7 @@ dcb_fwd_config_setup(void)
uint16_t nb_rx_queue, nb_tx_queue;
uint16_t i, j, k, sm_id = 0;
uint16_t sub_core_idx = 0;
+ uint8_t effective_nb_tcs;
uint16_t total_tc_num;
struct rte_port *port;
uint8_t tc = 0;
@@ -5442,6 +5443,7 @@ dcb_fwd_config_setup(void)
dcb_fwd_tc_update_dcb_info(&rxp_dcb_info);
(void)rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
dcb_fwd_tc_update_dcb_info(&txp_dcb_info);
+ effective_nb_tcs = RTE_MIN(rxp_dcb_info.nb_tcs, txp_dcb_info.nb_tcs);
for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) {
fwd_lcores[lc_id]->stream_nb = 0;
@@ -5450,7 +5452,8 @@ dcb_fwd_config_setup(void)
/* if the nb_queue is zero, means this tc is
* not enabled on the POOL
*/
- if (rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue == 0)
+ if (rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue == 0 ||
+ txp_dcb_info.tc_queue.tc_txq[i][tc].nb_queue == 0)
break;
k = fwd_lcores[lc_id]->stream_nb +
fwd_lcores[lc_id]->stream_idx;
@@ -5480,7 +5483,7 @@ dcb_fwd_config_setup(void)
sub_core_idx = 0;
tc++;
- if (tc < rxp_dcb_info.nb_tcs)
+ if (tc < effective_nb_tcs)
continue;
/* Restart from TC 0 on next RX port */
tc = 0;
@@ -5497,6 +5500,8 @@ dcb_fwd_config_setup(void)
dcb_fwd_tc_update_dcb_info(&rxp_dcb_info);
rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
dcb_fwd_tc_update_dcb_info(&txp_dcb_info);
+
+ effective_nb_tcs = RTE_MIN(rxp_dcb_info.nb_tcs,
txp_dcb_info.nb_tcs);
}
}
--
2.43.0