[v4] ethdev: TEST support single queue per port
Checks
Commit Message
Configuring one queue per port fails compilation on my system.
Test to see how much it fails in CI.
Signed-off-by: Morten Brørup <mb@smartsharesystems.com>
---
v4:
* Workaound GCC optimizer incorrectly throwing a warning in these network
drivers:
* bnxt
* e1000
* failsafe
* hns3
v3:
* Fix net/ixgbe driver.
v2:
* Fix net/vmxnet3 driver.
---
config/rte_config.h | 4 ++--
drivers/net/bnxt/bnxt_ethdev.c | 3 +++
drivers/net/e1000/igb_rxtx.c | 3 +++
drivers/net/failsafe/failsafe_ops.c | 6 ++++++
drivers/net/hns3/hns3_rxtx.c | 3 +++
drivers/net/ixgbe/ixgbe_ethdev.c | 3 ++-
drivers/net/vmxnet3/vmxnet3_ethdev.c | 32 +++++++++++++++++-----------
7 files changed, 39 insertions(+), 15 deletions(-)
Comments
On Thu, 24 Oct 2024 14:55:50 +0000
Morten Brørup <mb@smartsharesystems.com> wrote:
> diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
> index 1f7c0d77d5..f34a953ecd 100644
> --- a/drivers/net/bnxt/bnxt_ethdev.c
> +++ b/drivers/net/bnxt/bnxt_ethdev.c
> @@ -842,6 +842,8 @@ static int bnxt_alloc_prev_ring_stats(struct bnxt *bp)
> return -ENOMEM;
> }
>
> +#pragma GCC push_options
> +#pragma GCC optimize("no-peel-loops")
> static int bnxt_start_nic(struct bnxt *bp)
> {
> struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(bp->eth_dev);
> @@ -1006,6 +1008,7 @@ static int bnxt_start_nic(struct bnxt *bp)
>
> return rc;
> }
> +#pragma GCC pop_options
What is the warning, I hate pragma's they are technical debt.
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Thursday, 24 October 2024 18.42
>
> On Thu, 24 Oct 2024 14:55:50 +0000
> Morten Brørup <mb@smartsharesystems.com> wrote:
>
> > diff --git a/drivers/net/bnxt/bnxt_ethdev.c
> b/drivers/net/bnxt/bnxt_ethdev.c
> > index 1f7c0d77d5..f34a953ecd 100644
> > --- a/drivers/net/bnxt/bnxt_ethdev.c
> > +++ b/drivers/net/bnxt/bnxt_ethdev.c
> > @@ -842,6 +842,8 @@ static int bnxt_alloc_prev_ring_stats(struct bnxt
> *bp)
> > return -ENOMEM;
> > }
> >
> > +#pragma GCC push_options
> > +#pragma GCC optimize("no-peel-loops")
> > static int bnxt_start_nic(struct bnxt *bp)
> > {
> > struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(bp->eth_dev);
> > @@ -1006,6 +1008,7 @@ static int bnxt_start_nic(struct bnxt *bp)
> >
> > return rc;
> > }
> > +#pragma GCC pop_options
>
> What is the warning,
The warning is about access at offset beyond the array.
It seems the optimizer loop unrolls or something similar, not realizing the array only has one entry. And then it warns when it realizes afterwards.
> I hate pragma's they are technical debt.
Me too.
The CI shows that clang doesn't have this problem, only GCC.
But we should to be able to build DPDK with only one queue per port, to conserve memory.
@@ -65,8 +65,8 @@
#define RTE_MBUF_DEFAULT_MEMPOOL_OPS "ring_mp_mc"
/* ether defines */
-#define RTE_MAX_QUEUES_PER_PORT 1024
-#define RTE_ETHDEV_QUEUE_STAT_CNTRS 16 /* max 256 */
+#define RTE_MAX_QUEUES_PER_PORT 1 /* default 1024 */
+#define RTE_ETHDEV_QUEUE_STAT_CNTRS 1 /* max 256, default 16 */
#define RTE_ETHDEV_RXTX_CALLBACKS 1
#define RTE_MAX_MULTI_HOST_CTRLS 4
@@ -842,6 +842,8 @@ static int bnxt_alloc_prev_ring_stats(struct bnxt *bp)
return -ENOMEM;
}
+#pragma GCC push_options
+#pragma GCC optimize("no-peel-loops")
static int bnxt_start_nic(struct bnxt *bp)
{
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(bp->eth_dev);
@@ -1006,6 +1008,7 @@ static int bnxt_start_nic(struct bnxt *bp)
return rc;
}
+#pragma GCC pop_options
static int bnxt_shutdown_nic(struct bnxt *bp)
{
@@ -1860,6 +1860,8 @@ eth_igb_tx_descriptor_status(void *tx_queue, uint16_t offset)
return RTE_ETH_TX_DESC_FULL;
}
+#pragma GCC push_options
+#pragma GCC optimize("no-peel-loops")
void
igb_dev_clear_queues(struct rte_eth_dev *dev)
{
@@ -1885,6 +1887,7 @@ igb_dev_clear_queues(struct rte_eth_dev *dev)
}
}
}
+#pragma GCC pop_options
void
igb_dev_free_queues(struct rte_eth_dev *dev)
@@ -103,6 +103,8 @@ fs_dev_configure(struct rte_eth_dev *dev)
return 0;
}
+#pragma GCC push_options
+#pragma GCC optimize("no-peel-loops")
static void
fs_set_queues_state_start(struct rte_eth_dev *dev)
{
@@ -123,6 +125,7 @@ fs_set_queues_state_start(struct rte_eth_dev *dev)
RTE_ETH_QUEUE_STATE_STARTED;
}
}
+#pragma GCC pop_options
static int
fs_dev_start(struct rte_eth_dev *dev)
@@ -171,6 +174,8 @@ fs_dev_start(struct rte_eth_dev *dev)
return 0;
}
+#pragma GCC push_options
+#pragma GCC optimize("no-peel-loops")
static void
fs_set_queues_state_stop(struct rte_eth_dev *dev)
{
@@ -185,6 +190,7 @@ fs_set_queues_state_stop(struct rte_eth_dev *dev)
dev->data->tx_queue_state[i] =
RTE_ETH_QUEUE_STATE_STOPPED;
}
+#pragma GCC pop_options
static int
fs_dev_stop(struct rte_eth_dev *dev)
@@ -1299,6 +1299,8 @@ hns3_init_queues(struct hns3_adapter *hns, bool reset_queue)
return ret;
}
+#pragma GCC push_options
+#pragma GCC optimize("no-peel-loops")
void
hns3_start_tqps(struct hns3_hw *hw)
{
@@ -1322,6 +1324,7 @@ hns3_start_tqps(struct hns3_hw *hw)
RTE_ETH_QUEUE_STATE_STARTED;
}
}
+#pragma GCC pop_options
void
hns3_stop_tqps(struct hns3_hw *hw)
@@ -3385,7 +3385,8 @@ ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
stats->opackets = hw_stats->gptc;
stats->obytes = hw_stats->gotc;
- for (i = 0; i < IXGBE_QUEUE_STAT_COUNTERS; i++) {
+ for (i = 0; i < RTE_MIN(IXGBE_QUEUE_STAT_COUNTERS,
+ (typeof(IXGBE_QUEUE_STAT_COUNTERS))RTE_ETHDEV_QUEUE_STAT_CNTRS); i++) {
stats->q_ipackets[i] = hw_stats->qprc[i];
stats->q_opackets[i] = hw_stats->qptc[i];
stats->q_ibytes[i] = hw_stats->qbrc[i];
@@ -1470,42 +1470,52 @@ vmxnet3_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
struct vmxnet3_hw *hw = dev->data->dev_private;
struct UPT1_TxStats txStats;
struct UPT1_RxStats rxStats;
+ uint64_t packets, bytes;
VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
for (i = 0; i < hw->num_tx_queues; i++) {
vmxnet3_tx_stats_get(hw, i, &txStats);
- stats->q_opackets[i] = txStats.ucastPktsTxOK +
+ packets = txStats.ucastPktsTxOK +
txStats.mcastPktsTxOK +
txStats.bcastPktsTxOK;
- stats->q_obytes[i] = txStats.ucastBytesTxOK +
+ bytes = txStats.ucastBytesTxOK +
txStats.mcastBytesTxOK +
txStats.bcastBytesTxOK;
- stats->opackets += stats->q_opackets[i];
- stats->obytes += stats->q_obytes[i];
+ stats->opackets += packets;
+ stats->obytes += bytes;
stats->oerrors += txStats.pktsTxError + txStats.pktsTxDiscard;
+
+ if (i < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
+ stats->q_opackets[i] = packets;
+ stats->q_obytes[i] = bytes;
+ }
}
for (i = 0; i < hw->num_rx_queues; i++) {
vmxnet3_rx_stats_get(hw, i, &rxStats);
- stats->q_ipackets[i] = rxStats.ucastPktsRxOK +
+ packets = rxStats.ucastPktsRxOK +
rxStats.mcastPktsRxOK +
rxStats.bcastPktsRxOK;
- stats->q_ibytes[i] = rxStats.ucastBytesRxOK +
+ bytes = rxStats.ucastBytesRxOK +
rxStats.mcastBytesRxOK +
rxStats.bcastBytesRxOK;
- stats->ipackets += stats->q_ipackets[i];
- stats->ibytes += stats->q_ibytes[i];
-
- stats->q_errors[i] = rxStats.pktsRxError;
+ stats->ipackets += packets;
+ stats->ibytes += bytes;
stats->ierrors += rxStats.pktsRxError;
stats->imissed += rxStats.pktsRxOutOfBuf;
+
+ if (i < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
+ stats->q_ipackets[i] = packets;
+ stats->q_ibytes[i] = bytes;
+ stats->q_errors[i] = rxStats.pktsRxError;
+ }
}
return 0;
@@ -1521,8 +1531,6 @@ vmxnet3_dev_stats_reset(struct rte_eth_dev *dev)
VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
- RTE_BUILD_BUG_ON(RTE_ETHDEV_QUEUE_STAT_CNTRS < VMXNET3_MAX_TX_QUEUES);
-
for (i = 0; i < hw->num_tx_queues; i++) {
vmxnet3_hw_tx_stats_get(hw, i, &txStats);
memcpy(&hw->snapshot_tx_stats[i], &txStats,