All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls
@ 2026-10-16 17:45 Tathagat Priyadarshi
  2026-10-16 17:45 ` [PATCH v4 01/10] net/gve: fix DQO descriptor cleaning loop bound Tathagat Priyadarshi
                   ` (9 more replies)
  0 siblings, 10 replies; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-16 17:45 UTC (permalink / raw)
  To: dev; +Cc: Joshua Washington, Stephen Hemminger

This series fixes several ways the gve DQO RDA Tx path can stall or
post invalid descriptors: completion handling bugs (1-2), a report
event interval that can starve the ring (3), a stray TSO context
descriptor when completion tags run out (4), a missing cacheline
margin (5), invalid packets blocking the burst (6-8), and missing
device length checks (9-10).

v4:
- Rebased on main; v3 no longer applied after 4a543ae8c8
  ("net/gve: clean Tx queue directly in DQO") removed txqs next
  to the field changed in 3/10. No functional changes.

v3:
- Split the series into one fix per patch, per review feedback.
  The code is the same as v2 except where noted below.
- 1/10, 2/10: v2 1/4, split in two. Kept Joshua's Ack.
- 3/10: v2 2/4 without the declaration reordering
  (per Joshua Washington) and without ringing the doorbell on each
  report event, which is a performance change to be sent separately
  with numbers (per Stephen Hemminger).
- 4/10: the completion tag reorder from v2 2/4, as its own patch.
  Fixes tag now points at the commit that made the tag pop fallible.
- 5/10: v2 3/4, unchanged. Kept Joshua's Ack.
- 6/10-10/10: v2 4/4, split:
  * Keep too_many_descs and add per-reason invalid_mbufs and
    invalid_pkts counters instead of a generic dropped_pkts
    (per Joshua Washington), and export them as xstats
    (per Stephen Hemminger).
  * Count sent packets after writing descriptors instead of
    subtracting drops (per Joshua Washington).
  * Move the length and TSO header checks into gve_tx_validate_pkt(),
    leaving gve_tx_validate_descs() to descriptor counts, without
    the declaration moves.
  * Reword the TSO length limit (per Stephen Hemminger) and shorten
    the commit messages.
- Stephen's Reviewed-by on v2 is not carried over because of the
  rework.

Tathagat Priyadarshi (10):
  net/gve: fix DQO descriptor cleaning loop bound
  net/gve: fix DQO completion queue stall on unknown type
  net/gve: fix DQO Tx report event interval
  net/gve: fix stray TSO context descriptor on tag exhaustion
  net/gve: add cacheline overlap margin to DQO Tx ring
  net/gve: fix Tx stall on invalid packets
  net/gve: export Tx drop counters in xstats
  net/gve: reject Tx packets that cannot fit in the ring
  net/gve: enforce DQO Tx packet length limits
  net/gve: enforce DQO TSO header and length limits

 drivers/net/gve/base/gve_desc_dqo.h |   3 +
 drivers/net/gve/gve_ethdev.c        |   3 +
 drivers/net/gve/gve_ethdev.h        |   4 +-
 drivers/net/gve/gve_tx_dqo.c        | 113 +++++++++++++++++++++-------
 4 files changed, 96 insertions(+), 27 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v4 01/10] net/gve: fix DQO descriptor cleaning loop bound
  2026-10-16 17:45 [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls Tathagat Priyadarshi
@ 2026-10-16 17:45 ` Tathagat Priyadarshi
  2026-10-16 17:45 ` [PATCH v4 02/10] net/gve: fix DQO completion queue stall on unknown type Tathagat Priyadarshi
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-16 17:45 UTC (permalink / raw)
  To: dev
  Cc: Joshua Washington, Stephen Hemminger, stable, Jeroen de Borst,
	Rushil Gupta, Junfeng Guo

gve_tx_clean_descs_dqo() loops on "while (--nb_descs)", which
processes one completion fewer than requested, and none when asked
for one.

Use a post-decrement so exactly nb_descs completions are processed.

Fixes: 4022f9999f56 ("net/gve: support basic Tx data path for DQO")
Cc: stable@dpdk.org

Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
Acked-by: Joshua Washington <joshwash@google.com>
---
 drivers/net/gve/gve_tx_dqo.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index 901c6ca749..7e12da68e6 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -119,7 +119,7 @@ gve_tx_clean_dqo(struct gve_tx_queue *txq)
 
 static inline void
 gve_tx_clean_descs_dqo(struct gve_tx_queue *txq, uint16_t nb_descs) {
-	while (--nb_descs)
+	while (nb_descs--)
 		gve_tx_clean_dqo(txq);
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v4 02/10] net/gve: fix DQO completion queue stall on unknown type
  2026-10-16 17:45 [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls Tathagat Priyadarshi
  2026-10-16 17:45 ` [PATCH v4 01/10] net/gve: fix DQO descriptor cleaning loop bound Tathagat Priyadarshi
@ 2026-10-16 17:45 ` Tathagat Priyadarshi
  2026-10-16 17:45 ` [PATCH v4 03/10] net/gve: fix DQO Tx report event interval Tathagat Priyadarshi
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-16 17:45 UTC (permalink / raw)
  To: dev
  Cc: Joshua Washington, Stephen Hemminger, stable, Rushil Gupta,
	Jeroen de Borst, Junfeng Guo

When gve_tx_clean_dqo() sees an unknown completion type, it returns
without advancing complq_tail. Every later call stops at the same
entry, so Tx completions are never processed again.

Log the type and skip the entry.

Fixes: 4022f9999f56 ("net/gve: support basic Tx data path for DQO")
Cc: stable@dpdk.org

Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
Acked-by: Joshua Washington <joshwash@google.com>
---
 drivers/net/gve/gve_tx_dqo.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index 7e12da68e6..4b84135d02 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -105,8 +105,8 @@ gve_tx_clean_dqo(struct gve_tx_queue *txq)
 		PMD_DRV_DP_LOG(DEBUG, "GVE_COMPL_TYPE_DQO_MISS ignored !!!");
 		break;
 	default:
-		PMD_DRV_DP_LOG(ERR, "unknown completion type.");
-		return;
+		PMD_DRV_DP_LOG(ERR, "unknown completion type %u", compl_desc->type);
+		break;
 	}
 
 	next++;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v4 03/10] net/gve: fix DQO Tx report event interval
  2026-10-16 17:45 [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls Tathagat Priyadarshi
  2026-10-16 17:45 ` [PATCH v4 01/10] net/gve: fix DQO descriptor cleaning loop bound Tathagat Priyadarshi
  2026-10-16 17:45 ` [PATCH v4 02/10] net/gve: fix DQO completion queue stall on unknown type Tathagat Priyadarshi
@ 2026-10-16 17:45 ` Tathagat Priyadarshi
  2026-10-16 17:45 ` [PATCH v4 04/10] net/gve: fix stray TSO context descriptor on tag exhaustion Tathagat Priyadarshi
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-16 17:45 UTC (permalink / raw)
  To: dev
  Cc: Joshua Washington, Stephen Hemminger, stable, Junfeng Guo,
	Rushil Gupta, Jeroen de Borst, Varun Lakkur Ambaji Rao

A descriptor completion is requested once every 32 packets, and Tx
descriptors are only reclaimed on these completions. With
multi-segment or TSO packets the ring can fill before 32 packets are
posted, so no completion is ever requested and the Tx queue stalls
for good.

Request a completion once GVE_TX_MIN_RE_INTERVAL descriptors have
been posted since the last one, as the Linux driver does.

Fixes: 4022f9999f56 ("net/gve: support basic Tx data path for DQO")
Fixes: 403c671a46b6 ("net/gve: support TSO in DQO RDA")
Cc: stable@dpdk.org

Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
---
 drivers/net/gve/gve_ethdev.h |  2 +-
 drivers/net/gve/gve_tx_dqo.c | 22 ++++++++++++++--------
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 19eac9ec0b..4d17ba727d 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -193,7 +193,7 @@ struct gve_tx_queue {
 	uint16_t sw_size;
 	uint8_t cur_gen_bit;
 	uint32_t last_desc_cleaned;
-	uint16_t re_cnt;
+	uint16_t last_re_idx;
 
 	/* Only valid for DQO_RDA queue format */
 	struct gve_tx_queue *complq;
diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index 4b84135d02..6cca968122 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -251,6 +251,8 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 	volatile union gve_tx_desc_dqo *txr;
 	volatile union gve_tx_desc_dqo *txd;
 	uint16_t mask = txq->nb_tx_desc - 1;
+	uint16_t last_re_interval;
+	uint16_t last_desc_idx;
 	struct gve_tx_pkt *pkts;
 	struct rte_mbuf *tx_pkt;
 	uint16_t compl_tag;
@@ -328,20 +330,23 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 		txd = &txr[(tx_id - 1) & mask];
 		txd->pkt.end_of_packet = 1;
 
+		/* Request a descriptor completion once at least
+		 * GVE_TX_MIN_RE_INTERVAL descriptors have been posted
+		 * since the last request.
+		 */
+		last_desc_idx = (tx_id - 1) & mask;
+		last_re_interval = (last_desc_idx - txq->last_re_idx) & mask;
+		if (unlikely(last_re_interval >= GVE_TX_MIN_RE_INTERVAL)) {
+			txd->pkt.report_event = true;
+			txq->last_re_idx = last_desc_idx;
+		}
+
 		txq->nb_free -= nb_descs;
 		txq->nb_used += nb_descs;
 	}
 
 	/* update the tail pointer if any packets were processed */
 	if (nb_tx > 0) {
-		/* Request a descriptor completion on the last descriptor */
-		txq->re_cnt += nb_tx;
-		if (txq->re_cnt >= GVE_TX_MIN_RE_INTERVAL) {
-			txd = &txr[(tx_id - 1) & mask];
-			txd->pkt.report_event = true;
-			txq->re_cnt = 0;
-		}
-
 		rte_write32(tx_id, txq->qtx_tail);
 		txq->tx_tail = tx_id;
 
@@ -442,6 +447,7 @@ gve_reset_tx_ring_state_dqo(struct gve_tx_queue *txq)
 	txq->nb_used = 0;
 
 	txq->last_desc_cleaned = 0;
+	txq->last_re_idx = 0;
 	txq->nb_free = txq->nb_tx_desc - 1;
 
 	txq->complq_tail = 0;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v4 04/10] net/gve: fix stray TSO context descriptor on tag exhaustion
  2026-10-16 17:45 [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls Tathagat Priyadarshi
                   ` (2 preceding siblings ...)
  2026-10-16 17:45 ` [PATCH v4 03/10] net/gve: fix DQO Tx report event interval Tathagat Priyadarshi
@ 2026-10-16 17:45 ` Tathagat Priyadarshi
  2026-10-16 17:45 ` [PATCH v4 05/10] net/gve: add cacheline overlap margin to DQO Tx ring Tathagat Priyadarshi
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-16 17:45 UTC (permalink / raw)
  To: dev; +Cc: Joshua Washington, Stephen Hemminger, stable, Ankit Garg

For TSO packets, the context descriptor is written and tx_id advanced
before a completion tag is allocated. If no tag is available, the
burst stops, but when earlier packets in the burst were sent, the
tail written at the end of the burst still covers the context
descriptor. The device then receives it with no data descriptors
behind it, and the slot is never deducted from nb_free.

Allocate the completion tag before writing any descriptor.

Fixes: 5fd289ff3a00 ("net/gve: support out-of-order completions on DQ Tx")
Cc: stable@dpdk.org

Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
---
 drivers/net/gve/gve_tx_dqo.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index 6cca968122..55187fec71 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -305,15 +305,15 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 			break;
 		}
 
+		if (!gve_free_compl_tags_pop(txq, &compl_tag))
+			break;
+
 		if (tso) {
 			txd = &txr[tx_id];
 			gve_tx_fill_seg_desc_dqo(txd, tx_pkt);
 			tx_id = (tx_id + 1) & mask;
 		}
 
-		if (!gve_free_compl_tags_pop(txq, &compl_tag))
-			break;
-
 		pkts[compl_tag].mbuf = tx_pkt;
 		while (tx_pkt) {
 			/* Skip writing descriptors if mbuf has no data. */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v4 05/10] net/gve: add cacheline overlap margin to DQO Tx ring
  2026-10-16 17:45 [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls Tathagat Priyadarshi
                   ` (3 preceding siblings ...)
  2026-10-16 17:45 ` [PATCH v4 04/10] net/gve: fix stray TSO context descriptor on tag exhaustion Tathagat Priyadarshi
@ 2026-10-16 17:45 ` Tathagat Priyadarshi
  2026-10-16 17:45 ` [PATCH v4 06/10] net/gve: fix Tx stall on invalid packets Tathagat Priyadarshi
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-16 17:45 UTC (permalink / raw)
  To: dev
  Cc: Joshua Washington, Stephen Hemminger, stable, Jeroen de Borst,
	Rushil Gupta, Junfeng Guo

The GVNIC DQO hardware DMA engine prefetches descriptors in cacheline
units (64 bytes = 4 descriptors of 16 bytes each). When producer tail
and consumer head indices share a cacheline, CPU and device DMA memory
collisions can occur.

Align with the Linux driver (gve_has_tx_slots_available()) by requiring
GVE_TX_MIN_DESC_PREVENT_CACHE_OVERLAP (4 descriptors) headroom when
checking descriptor availability before enqueueing packets.

Fixes: 4022f9999f56 ("net/gve: support basic Tx data path for DQO")
Cc: stable@dpdk.org

Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
Acked-by: Joshua Washington <joshwash@google.com>
---
 drivers/net/gve/gve_tx_dqo.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index 55187fec71..637632ce4d 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -256,6 +256,7 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 	struct gve_tx_pkt *pkts;
 	struct rte_mbuf *tx_pkt;
 	uint16_t compl_tag;
+	uint16_t req_descs;
 	const char *reason;
 	uint16_t nb_tx = 0;
 	uint64_t bytes = 0;
@@ -288,14 +289,17 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
 		nb_descs = gve_tx_pkt_nb_data_descs(tx_pkt);
 		nb_descs += tso;
+		req_descs = nb_descs + GVE_TX_MIN_DESC_PREVENT_CACHE_OVERLAP;
 
-		/* Clean if there aren't enough descriptors to send the packet. */
-		if (unlikely(!gve_can_tx(txq, nb_descs, 1))) {
+		/* Clean if there aren't enough descriptors to send the packet
+		 * while maintaining the cacheline overlap margin.
+		 */
+		if (unlikely(!gve_can_tx(txq, req_descs, 1))) {
 			int nb_to_clean = RTE_MAX(DQO_TX_MULTIPLIER * txq->rs_thresh,
-						  nb_descs);
+						  (int)req_descs);
 
 			gve_tx_clean_descs_dqo(txq, nb_to_clean);
-			if (!gve_can_tx(txq, nb_descs, 1))
+			if (!gve_can_tx(txq, req_descs, 1))
 				break;
 		}
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v4 06/10] net/gve: fix Tx stall on invalid packets
  2026-10-16 17:45 [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls Tathagat Priyadarshi
                   ` (4 preceding siblings ...)
  2026-10-16 17:45 ` [PATCH v4 05/10] net/gve: add cacheline overlap margin to DQO Tx ring Tathagat Priyadarshi
@ 2026-10-16 17:45 ` Tathagat Priyadarshi
  2026-10-16 17:45 ` [PATCH v4 07/10] net/gve: export Tx drop counters in xstats Tathagat Priyadarshi
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-16 17:45 UTC (permalink / raw)
  To: dev; +Cc: Joshua Washington, Stephen Hemminger, stable, Ankit Garg

When a packet fails rte_mbuf_check() or exceeds the descriptor limit,
the Tx burst stops at that packet without consuming it. The
application retries the same packet, it fails again, and the queue
never moves.

Free such packets and continue with the burst. Validate before the
ring space check, so that an oversized packet is dropped instead of
stopping the burst there. Count rte_mbuf_check() failures in a new
invalid_mbufs counter.

Fixes: f4a70b449bfa ("net/gve: add DQO Tx descriptor limit")
Fixes: f33ce4445ee6 ("net/gve: validate Tx packet before sending")
Cc: stable@dpdk.org

Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
---
 drivers/net/gve/gve_ethdev.h |  1 +
 drivers/net/gve/gve_tx_dqo.c | 24 +++++++++++++++---------
 2 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 4d17ba727d..66cb31dadb 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -114,6 +114,7 @@ struct gve_tx_stats {
 	uint64_t bytes;
 	uint64_t errors;
 	uint64_t too_many_descs;
+	uint64_t invalid_mbufs;
 };
 
 struct gve_rx_stats {
diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index 637632ce4d..281700b463 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -258,6 +258,7 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 	uint16_t compl_tag;
 	uint16_t req_descs;
 	const char *reason;
+	uint16_t nb_sent = 0;
 	uint16_t nb_tx = 0;
 	uint64_t bytes = 0;
 	uint64_t ol_flags;
@@ -280,7 +281,9 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
 		if (rte_mbuf_check(tx_pkt, true, &reason)) {
 			PMD_DRV_DP_LOG(DEBUG, "Invalid mbuf: %s", reason);
-			break;
+			txq->stats.invalid_mbufs++;
+			rte_pktmbuf_free(tx_pkt);
+			continue;
 		}
 
 		ol_flags = tx_pkt->ol_flags;
@@ -289,6 +292,14 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
 		nb_descs = gve_tx_pkt_nb_data_descs(tx_pkt);
 		nb_descs += tso;
+
+		/* Drop packet if it doesn't adhere to hardware limits. */
+		if (!gve_tx_validate_descs(tx_pkt, nb_descs, tso)) {
+			txq->stats.too_many_descs++;
+			rte_pktmbuf_free(tx_pkt);
+			continue;
+		}
+
 		req_descs = nb_descs + GVE_TX_MIN_DESC_PREVENT_CACHE_OVERLAP;
 
 		/* Clean if there aren't enough descriptors to send the packet
@@ -303,12 +314,6 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 				break;
 		}
 
-		/* Drop packet if it doesn't adhere to hardware limits. */
-		if (!gve_tx_validate_descs(tx_pkt, nb_descs, tso)) {
-			txq->stats.too_many_descs++;
-			break;
-		}
-
 		if (!gve_free_compl_tags_pop(txq, &compl_tag))
 			break;
 
@@ -347,6 +352,7 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
 		txq->nb_free -= nb_descs;
 		txq->nb_used += nb_descs;
+		nb_sent++;
 	}
 
 	/* update the tail pointer if any packets were processed */
@@ -354,9 +360,9 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 		rte_write32(tx_id, txq->qtx_tail);
 		txq->tx_tail = tx_id;
 
-		txq->stats.packets += nb_tx;
+		txq->stats.packets += nb_sent;
 		txq->stats.bytes += bytes;
-		txq->stats.errors += nb_pkts - nb_tx;
+		txq->stats.errors += nb_pkts - nb_sent;
 	}
 
 	return nb_tx;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v4 07/10] net/gve: export Tx drop counters in xstats
  2026-10-16 17:45 [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls Tathagat Priyadarshi
                   ` (5 preceding siblings ...)
  2026-10-16 17:45 ` [PATCH v4 06/10] net/gve: fix Tx stall on invalid packets Tathagat Priyadarshi
@ 2026-10-16 17:45 ` Tathagat Priyadarshi
  2026-10-16 18:18   ` Joshua Washington
  2026-10-16 17:45 ` [PATCH v4 08/10] net/gve: reject Tx packets that cannot fit in the ring Tathagat Priyadarshi
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-16 17:45 UTC (permalink / raw)
  To: dev; +Cc: Joshua Washington, Stephen Hemminger, stable, Ankit Garg

too_many_descs is counted but missing from the Tx xstats table, so it
cannot be read. Export it together with invalid_mbufs.

Fixes: f4a70b449bfa ("net/gve: add DQO Tx descriptor limit")
Cc: stable@dpdk.org

Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
---
 drivers/net/gve/gve_ethdev.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index 3c8d1a76e4..1dfbe8f396 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -1042,6 +1042,8 @@ static const struct gve_xstats_name_offset tx_xstats_name_offset[] = {
 	{ "packets", TX_QUEUE_STATS_OFFSET(packets) },
 	{ "bytes",   TX_QUEUE_STATS_OFFSET(bytes) },
 	{ "errors",  TX_QUEUE_STATS_OFFSET(errors) },
+	{ "too_many_descs", TX_QUEUE_STATS_OFFSET(too_many_descs) },
+	{ "invalid_mbufs", TX_QUEUE_STATS_OFFSET(invalid_mbufs) },
 };
 
 static const struct gve_xstats_name_offset rx_xstats_name_offset[] = {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v4 08/10] net/gve: reject Tx packets that cannot fit in the ring
  2026-10-16 17:45 [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls Tathagat Priyadarshi
                   ` (6 preceding siblings ...)
  2026-10-16 17:45 ` [PATCH v4 07/10] net/gve: export Tx drop counters in xstats Tathagat Priyadarshi
@ 2026-10-16 17:45 ` Tathagat Priyadarshi
  2026-10-16 18:18   ` Joshua Washington
  2026-10-16 17:45 ` [PATCH v4 09/10] net/gve: enforce DQO Tx packet length limits Tathagat Priyadarshi
  2026-10-16 17:45 ` [PATCH v4 10/10] net/gve: enforce DQO TSO header and " Tathagat Priyadarshi
  9 siblings, 1 reply; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-16 17:45 UTC (permalink / raw)
  To: dev
  Cc: Joshua Washington, Stephen Hemminger, stable,
	Varun Lakkur Ambaji Rao, Rushil Gupta

A TSO packet needing more descriptors than the ring can ever have
free fails the ring space check on every burst and blocks the queue.
One slot is always reserved, the cacheline overlap margin must stay
free, and up to GVE_TX_MIN_RE_INTERVAL - 1 posted descriptors are not
reclaimed until more are posted.

Drop such packets and count them as too_many_descs.

Fixes: 403c671a46b6 ("net/gve: support TSO in DQO RDA")
Cc: stable@dpdk.org

Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
---
 drivers/net/gve/gve_tx_dqo.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index 281700b463..46a03d482d 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -123,14 +123,30 @@ gve_tx_clean_descs_dqo(struct gve_tx_queue *txq, uint16_t nb_descs) {
 		gve_tx_clean_dqo(txq);
 }
 
+/* Max descriptors a single packet may use. A larger packet can never pass
+ * gve_can_tx(): one slot is always reserved, the cacheline overlap margin
+ * must stay free, and up to GVE_TX_MIN_RE_INTERVAL - 1 descriptors posted
+ * after the last report_event are not reclaimed until more are posted.
+ */
+static inline int
+gve_tx_max_pkt_descs(const struct gve_tx_queue *txq)
+{
+	return (int)txq->nb_tx_desc - 1 - GVE_TX_MIN_DESC_PREVENT_CACHE_OVERLAP -
+		(GVE_TX_MIN_RE_INTERVAL - 1);
+}
+
 /* GVE expects at most 10 data descriptors per mtu-sized segment. Beyond this,
  * the hardware will assume the driver is malicious and stop transmitting
  * packets altogether. Validate that a packet can be sent to avoid sending
  * posting descriptors for an invalid packet.
  */
 static inline bool
-gve_tx_validate_descs(struct rte_mbuf *tx_pkt, uint16_t nb_descs, bool is_tso)
+gve_tx_validate_descs(const struct gve_tx_queue *txq, struct rte_mbuf *tx_pkt,
+		      uint16_t nb_descs, bool is_tso)
 {
+	if (nb_descs > gve_tx_max_pkt_descs(txq))
+		return false;
+
 	if (!is_tso)
 		return nb_descs <= GVE_TX_MAX_DATA_DESCS;
 
@@ -294,7 +310,7 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 		nb_descs += tso;
 
 		/* Drop packet if it doesn't adhere to hardware limits. */
-		if (!gve_tx_validate_descs(tx_pkt, nb_descs, tso)) {
+		if (!gve_tx_validate_descs(txq, tx_pkt, nb_descs, tso)) {
 			txq->stats.too_many_descs++;
 			rte_pktmbuf_free(tx_pkt);
 			continue;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v4 09/10] net/gve: enforce DQO Tx packet length limits
  2026-10-16 17:45 [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls Tathagat Priyadarshi
                   ` (7 preceding siblings ...)
  2026-10-16 17:45 ` [PATCH v4 08/10] net/gve: reject Tx packets that cannot fit in the ring Tathagat Priyadarshi
@ 2026-10-16 17:45 ` Tathagat Priyadarshi
  2026-10-16 18:22   ` Joshua Washington
  2026-10-16 17:45 ` [PATCH v4 10/10] net/gve: enforce DQO TSO header and " Tathagat Priyadarshi
  9 siblings, 1 reply; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-16 17:45 UTC (permalink / raw)
  To: dev
  Cc: Joshua Washington, Stephen Hemminger, stable, Jeroen de Borst,
	Rushil Gupta, Junfeng Guo

The device requires non-TSO packets to be 17 to 9728 bytes long, as
noted in the Linux driver, but packets of any length are posted. The
device treats an out-of-range packet as coming from a malicious
driver: it drops the packet and disables the datapath, stalling all
queues.

Drop such packets in the driver and count them in a new invalid_pkts
counter.

Fixes: 4022f9999f56 ("net/gve: support basic Tx data path for DQO")
Cc: stable@dpdk.org

Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
---
 drivers/net/gve/base/gve_desc_dqo.h |  2 ++
 drivers/net/gve/gve_ethdev.c        |  1 +
 drivers/net/gve/gve_ethdev.h        |  1 +
 drivers/net/gve/gve_tx_dqo.c        | 17 +++++++++++++++++
 4 files changed, 21 insertions(+)

diff --git a/drivers/net/gve/base/gve_desc_dqo.h b/drivers/net/gve/base/gve_desc_dqo.h
index c1534959c2..d50d88765e 100644
--- a/drivers/net/gve/base/gve_desc_dqo.h
+++ b/drivers/net/gve/base/gve_desc_dqo.h
@@ -12,6 +12,8 @@
 
 #define GVE_TX_MAX_HDR_SIZE_DQO 255
 #define GVE_TX_MIN_TSO_MSS_DQO 88
+#define GVE_TX_MIN_PKT_SIZE_DQO 17
+#define GVE_TX_MAX_PKT_SIZE_DQO 9728
 
 /* Basic TX descriptor (DTYPE 0x0C) */
 struct gve_tx_pkt_desc_dqo {
diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index 1dfbe8f396..53b0a0ec63 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -1044,6 +1044,7 @@ static const struct gve_xstats_name_offset tx_xstats_name_offset[] = {
 	{ "errors",  TX_QUEUE_STATS_OFFSET(errors) },
 	{ "too_many_descs", TX_QUEUE_STATS_OFFSET(too_many_descs) },
 	{ "invalid_mbufs", TX_QUEUE_STATS_OFFSET(invalid_mbufs) },
+	{ "invalid_pkts", TX_QUEUE_STATS_OFFSET(invalid_pkts) },
 };
 
 static const struct gve_xstats_name_offset rx_xstats_name_offset[] = {
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 66cb31dadb..be744d955b 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -115,6 +115,7 @@ struct gve_tx_stats {
 	uint64_t errors;
 	uint64_t too_many_descs;
 	uint64_t invalid_mbufs;
+	uint64_t invalid_pkts;
 };
 
 struct gve_rx_stats {
diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index 46a03d482d..f686a8c110 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -123,6 +123,17 @@ gve_tx_clean_descs_dqo(struct gve_tx_queue *txq, uint16_t nb_descs) {
 		gve_tx_clean_dqo(txq);
 }
 
+/* Validate packet lengths against the device limits. */
+static inline bool
+gve_tx_validate_pkt(const struct rte_mbuf *tx_pkt, bool is_tso)
+{
+	if (!is_tso)
+		return tx_pkt->pkt_len >= GVE_TX_MIN_PKT_SIZE_DQO &&
+		       tx_pkt->pkt_len <= GVE_TX_MAX_PKT_SIZE_DQO;
+
+	return true;
+}
+
 /* Max descriptors a single packet may use. A larger packet can never pass
  * gve_can_tx(): one slot is always reserved, the cacheline overlap margin
  * must stay free, and up to GVE_TX_MIN_RE_INTERVAL - 1 descriptors posted
@@ -306,6 +317,12 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 		tso = !!(ol_flags & RTE_MBUF_F_TX_TCP_SEG);
 		csum = !!(ol_flags & GVE_TX_CKSUM_OFFLOAD_MASK_DQO);
 
+		if (!gve_tx_validate_pkt(tx_pkt, tso)) {
+			txq->stats.invalid_pkts++;
+			rte_pktmbuf_free(tx_pkt);
+			continue;
+		}
+
 		nb_descs = gve_tx_pkt_nb_data_descs(tx_pkt);
 		nb_descs += tso;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v4 10/10] net/gve: enforce DQO TSO header and length limits
  2026-10-16 17:45 [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls Tathagat Priyadarshi
                   ` (8 preceding siblings ...)
  2026-10-16 17:45 ` [PATCH v4 09/10] net/gve: enforce DQO Tx packet length limits Tathagat Priyadarshi
@ 2026-10-16 17:45 ` Tathagat Priyadarshi
  2026-10-16 18:33   ` Joshua Washington
  9 siblings, 1 reply; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-16 17:45 UTC (permalink / raw)
  To: dev
  Cc: Joshua Washington, Stephen Hemminger, stable, Rushil Gupta,
	Varun Lakkur Ambaji Rao, Ankit Garg

TSO packets are not checked against the device limits before use.
The device requires an MSS of 88 to 9728 bytes and a payload of at
most 262143 bytes, as noted in the Linux driver. A packet outside
these limits triggers malicious driver detection, which drops it and
disables the datapath, stalling all queues.

The missing checks also break the driver itself: a tso_segsz of 0
divides by zero in gve_tx_validate_descs(), headers longer than 255
bytes are truncated by the 8-bit header_len field, and headers not
contained in the first segment give gve_tx_validate_descs() a
negative first segment length.

Drop TSO packets that violate these limits and count them as
invalid_pkts.

Fixes: 403c671a46b6 ("net/gve: support TSO in DQO RDA")
Fixes: be8f0eb81f98 ("net/gve: fix DQO TSO descriptor limit")
Cc: stable@dpdk.org

Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
---
 drivers/net/gve/base/gve_desc_dqo.h |  1 +
 drivers/net/gve/gve_tx_dqo.c        | 14 +++++++++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/net/gve/base/gve_desc_dqo.h b/drivers/net/gve/base/gve_desc_dqo.h
index d50d88765e..53e394f01c 100644
--- a/drivers/net/gve/base/gve_desc_dqo.h
+++ b/drivers/net/gve/base/gve_desc_dqo.h
@@ -14,6 +14,7 @@
 #define GVE_TX_MIN_TSO_MSS_DQO 88
 #define GVE_TX_MIN_PKT_SIZE_DQO 17
 #define GVE_TX_MAX_PKT_SIZE_DQO 9728
+#define GVE_TX_MAX_TSO_LEN_DQO ((256 * 1024) - 1)
 
 /* Basic TX descriptor (DTYPE 0x0C) */
 struct gve_tx_pkt_desc_dqo {
diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index f686a8c110..52fcdb285a 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -127,11 +127,23 @@ gve_tx_clean_descs_dqo(struct gve_tx_queue *txq, uint16_t nb_descs) {
 static inline bool
 gve_tx_validate_pkt(const struct rte_mbuf *tx_pkt, bool is_tso)
 {
+	uint32_t headlen;
+
 	if (!is_tso)
 		return tx_pkt->pkt_len >= GVE_TX_MIN_PKT_SIZE_DQO &&
 		       tx_pkt->pkt_len <= GVE_TX_MAX_PKT_SIZE_DQO;
 
-	return true;
+	/* Headers must be present, fit the context descriptor, and be
+	 * contained in the first segment; the payload must not be empty.
+	 */
+	headlen = tx_pkt->l2_len + tx_pkt->l3_len + tx_pkt->l4_len;
+	if (tx_pkt->l4_len == 0 || headlen > GVE_TX_MAX_HDR_SIZE_DQO ||
+	    tx_pkt->data_len < headlen || tx_pkt->pkt_len <= headlen)
+		return false;
+
+	return tx_pkt->pkt_len - headlen <= GVE_TX_MAX_TSO_LEN_DQO &&
+	       tx_pkt->tso_segsz >= GVE_TX_MIN_TSO_MSS_DQO &&
+	       tx_pkt->tso_segsz <= GVE_TX_MAX_PKT_SIZE_DQO;
 }
 
 /* Max descriptors a single packet may use. A larger packet can never pass
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v4 07/10] net/gve: export Tx drop counters in xstats
  2026-10-16 17:45 ` [PATCH v4 07/10] net/gve: export Tx drop counters in xstats Tathagat Priyadarshi
@ 2026-10-16 18:18   ` Joshua Washington
  0 siblings, 0 replies; 18+ messages in thread
From: Joshua Washington @ 2026-10-16 18:18 UTC (permalink / raw)
  To: Tathagat Priyadarshi; +Cc: dev, Stephen Hemminger, stable, Ankit Garg

On Fri, Oct 16, 2026 at 10:46 AM Tathagat Priyadarshi
<tathagat.dpdk@gmail.com> wrote:
>
> too_many_descs is counted but missing from the Tx xstats table, so it
> cannot be read. Export it together with invalid_mbufs.
>
> Fixes: f4a70b449bfa ("net/gve: add DQO Tx descriptor limit")
> Cc: stable@dpdk.org
>
> Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
Acked-by: Joshua Washington <joshwash@google.com>
> ---
>  drivers/net/gve/gve_ethdev.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
> index 3c8d1a76e4..1dfbe8f396 100644
> --- a/drivers/net/gve/gve_ethdev.c
> +++ b/drivers/net/gve/gve_ethdev.c
> @@ -1042,6 +1042,8 @@ static const struct gve_xstats_name_offset tx_xstats_name_offset[] = {
>         { "packets", TX_QUEUE_STATS_OFFSET(packets) },
>         { "bytes",   TX_QUEUE_STATS_OFFSET(bytes) },
>         { "errors",  TX_QUEUE_STATS_OFFSET(errors) },
> +       { "too_many_descs", TX_QUEUE_STATS_OFFSET(too_many_descs) },
> +       { "invalid_mbufs", TX_QUEUE_STATS_OFFSET(invalid_mbufs) },
>  };
>
>  static const struct gve_xstats_name_offset rx_xstats_name_offset[] = {
> --
> 2.43.0
>

Thanks!

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v4 08/10] net/gve: reject Tx packets that cannot fit in the ring
  2026-10-16 17:45 ` [PATCH v4 08/10] net/gve: reject Tx packets that cannot fit in the ring Tathagat Priyadarshi
@ 2026-10-16 18:18   ` Joshua Washington
  0 siblings, 0 replies; 18+ messages in thread
From: Joshua Washington @ 2026-10-16 18:18 UTC (permalink / raw)
  To: Tathagat Priyadarshi
  Cc: dev, Stephen Hemminger, stable, Varun Lakkur Ambaji Rao,
	Rushil Gupta

On Fri, Oct 16, 2026 at 10:46 AM Tathagat Priyadarshi
<tathagat.dpdk@gmail.com> wrote:
>
> A TSO packet needing more descriptors than the ring can ever have
> free fails the ring space check on every burst and blocks the queue.
> One slot is always reserved, the cacheline overlap margin must stay
> free, and up to GVE_TX_MIN_RE_INTERVAL - 1 posted descriptors are not
> reclaimed until more are posted.
>
> Drop such packets and count them as too_many_descs.
>
> Fixes: 403c671a46b6 ("net/gve: support TSO in DQO RDA")
> Cc: stable@dpdk.org
>
> Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
Acked-by: Joshua Washington <joshwash@google.com>
> ---
>  drivers/net/gve/gve_tx_dqo.c | 20 ++++++++++++++++++--
>  1 file changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
> index 281700b463..46a03d482d 100644
> --- a/drivers/net/gve/gve_tx_dqo.c
> +++ b/drivers/net/gve/gve_tx_dqo.c
> @@ -123,14 +123,30 @@ gve_tx_clean_descs_dqo(struct gve_tx_queue *txq, uint16_t nb_descs) {
>                 gve_tx_clean_dqo(txq);
>  }
>
> +/* Max descriptors a single packet may use. A larger packet can never pass
> + * gve_can_tx(): one slot is always reserved, the cacheline overlap margin
> + * must stay free, and up to GVE_TX_MIN_RE_INTERVAL - 1 descriptors posted
> + * after the last report_event are not reclaimed until more are posted.
> + */
> +static inline int
> +gve_tx_max_pkt_descs(const struct gve_tx_queue *txq)
> +{
> +       return (int)txq->nb_tx_desc - 1 - GVE_TX_MIN_DESC_PREVENT_CACHE_OVERLAP -
> +               (GVE_TX_MIN_RE_INTERVAL - 1);
> +}
> +
>  /* GVE expects at most 10 data descriptors per mtu-sized segment. Beyond this,
>   * the hardware will assume the driver is malicious and stop transmitting
>   * packets altogether. Validate that a packet can be sent to avoid sending
>   * posting descriptors for an invalid packet.
>   */
>  static inline bool
> -gve_tx_validate_descs(struct rte_mbuf *tx_pkt, uint16_t nb_descs, bool is_tso)
> +gve_tx_validate_descs(const struct gve_tx_queue *txq, struct rte_mbuf *tx_pkt,
> +                     uint16_t nb_descs, bool is_tso)
>  {
> +       if (nb_descs > gve_tx_max_pkt_descs(txq))
> +               return false;
> +
>         if (!is_tso)
>                 return nb_descs <= GVE_TX_MAX_DATA_DESCS;
>
> @@ -294,7 +310,7 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
>                 nb_descs += tso;
>
>                 /* Drop packet if it doesn't adhere to hardware limits. */
> -               if (!gve_tx_validate_descs(tx_pkt, nb_descs, tso)) {
> +               if (!gve_tx_validate_descs(txq, tx_pkt, nb_descs, tso)) {
>                         txq->stats.too_many_descs++;
>                         rte_pktmbuf_free(tx_pkt);
>                         continue;
> --
> 2.43.0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v4 09/10] net/gve: enforce DQO Tx packet length limits
  2026-10-16 17:45 ` [PATCH v4 09/10] net/gve: enforce DQO Tx packet length limits Tathagat Priyadarshi
@ 2026-10-16 18:22   ` Joshua Washington
  2026-10-18  7:54     ` Tathagat Priyadarshi
  0 siblings, 1 reply; 18+ messages in thread
From: Joshua Washington @ 2026-10-16 18:22 UTC (permalink / raw)
  To: Tathagat Priyadarshi
  Cc: dev, Stephen Hemminger, stable, Jeroen de Borst, Rushil Gupta,
	Junfeng Guo

On Fri, Oct 16, 2026 at 10:46 AM Tathagat Priyadarshi
<tathagat.dpdk@gmail.com> wrote:
>
> The device requires non-TSO packets to be 17 to 9728 bytes long, as
> noted in the Linux driver, but packets of any length are posted. The
> device treats an out-of-range packet as coming from a malicious
> driver: it drops the packet and disables the datapath, stalling all
> queues.
>
> Drop such packets in the driver and count them in a new invalid_pkts
> counter.
>
> Fixes: 4022f9999f56 ("net/gve: support basic Tx data path for DQO")
> Cc: stable@dpdk.org
>
> Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
Acked-by: Joshua Washington <joshwash@google.com>
> ---
>  drivers/net/gve/base/gve_desc_dqo.h |  2 ++
>  drivers/net/gve/gve_ethdev.c        |  1 +
>  drivers/net/gve/gve_ethdev.h        |  1 +
>  drivers/net/gve/gve_tx_dqo.c        | 17 +++++++++++++++++
>  4 files changed, 21 insertions(+)
>
> diff --git a/drivers/net/gve/base/gve_desc_dqo.h b/drivers/net/gve/base/gve_desc_dqo.h
> index c1534959c2..d50d88765e 100644
> --- a/drivers/net/gve/base/gve_desc_dqo.h
> +++ b/drivers/net/gve/base/gve_desc_dqo.h
> @@ -12,6 +12,8 @@
>
>  #define GVE_TX_MAX_HDR_SIZE_DQO 255
>  #define GVE_TX_MIN_TSO_MSS_DQO 88
> +#define GVE_TX_MIN_PKT_SIZE_DQO 17
> +#define GVE_TX_MAX_PKT_SIZE_DQO 9728
>
>  /* Basic TX descriptor (DTYPE 0x0C) */
>  struct gve_tx_pkt_desc_dqo {
> diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
> index 1dfbe8f396..53b0a0ec63 100644
> --- a/drivers/net/gve/gve_ethdev.c
> +++ b/drivers/net/gve/gve_ethdev.c
> @@ -1044,6 +1044,7 @@ static const struct gve_xstats_name_offset tx_xstats_name_offset[] = {
>         { "errors",  TX_QUEUE_STATS_OFFSET(errors) },
>         { "too_many_descs", TX_QUEUE_STATS_OFFSET(too_many_descs) },
>         { "invalid_mbufs", TX_QUEUE_STATS_OFFSET(invalid_mbufs) },
> +       { "invalid_pkts", TX_QUEUE_STATS_OFFSET(invalid_pkts) },
>  };
>
>  static const struct gve_xstats_name_offset rx_xstats_name_offset[] = {
> diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
> index 66cb31dadb..be744d955b 100644
> --- a/drivers/net/gve/gve_ethdev.h
> +++ b/drivers/net/gve/gve_ethdev.h
> @@ -115,6 +115,7 @@ struct gve_tx_stats {
>         uint64_t errors;
>         uint64_t too_many_descs;
>         uint64_t invalid_mbufs;
> +       uint64_t invalid_pkts;
>  };
>
>  struct gve_rx_stats {
> diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
> index 46a03d482d..f686a8c110 100644
> --- a/drivers/net/gve/gve_tx_dqo.c
> +++ b/drivers/net/gve/gve_tx_dqo.c
> @@ -123,6 +123,17 @@ gve_tx_clean_descs_dqo(struct gve_tx_queue *txq, uint16_t nb_descs) {
>                 gve_tx_clean_dqo(txq);
>  }
>
> +/* Validate packet lengths against the device limits. */
> +static inline bool
> +gve_tx_validate_pkt(const struct rte_mbuf *tx_pkt, bool is_tso)

Minor nit (not worth blocking over, but maybe can be done as the
patches are being merged): can this be renamed to
gve_tx_validate_pkt_len? This is one step of many in the packet
validation pipeline.

> +{
> +       if (!is_tso)
> +               return tx_pkt->pkt_len >= GVE_TX_MIN_PKT_SIZE_DQO &&
> +                      tx_pkt->pkt_len <= GVE_TX_MAX_PKT_SIZE_DQO;
> +
> +       return true;
> +}
> +
>  /* Max descriptors a single packet may use. A larger packet can never pass
>   * gve_can_tx(): one slot is always reserved, the cacheline overlap margin
>   * must stay free, and up to GVE_TX_MIN_RE_INTERVAL - 1 descriptors posted
> @@ -306,6 +317,12 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
>                 tso = !!(ol_flags & RTE_MBUF_F_TX_TCP_SEG);
>                 csum = !!(ol_flags & GVE_TX_CKSUM_OFFLOAD_MASK_DQO);
>
> +               if (!gve_tx_validate_pkt(tx_pkt, tso)) {
> +                       txq->stats.invalid_pkts++;
> +                       rte_pktmbuf_free(tx_pkt);
> +                       continue;
> +               }
> +
>                 nb_descs = gve_tx_pkt_nb_data_descs(tx_pkt);
>                 nb_descs += tso;
>
> --
> 2.43.0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v4 10/10] net/gve: enforce DQO TSO header and length limits
  2026-10-16 17:45 ` [PATCH v4 10/10] net/gve: enforce DQO TSO header and " Tathagat Priyadarshi
@ 2026-10-16 18:33   ` Joshua Washington
  0 siblings, 0 replies; 18+ messages in thread
From: Joshua Washington @ 2026-10-16 18:33 UTC (permalink / raw)
  To: Tathagat Priyadarshi
  Cc: dev, Stephen Hemminger, stable, Rushil Gupta,
	Varun Lakkur Ambaji Rao, Ankit Garg

On Fri, Oct 16, 2026 at 10:46 AM Tathagat Priyadarshi
<tathagat.dpdk@gmail.com> wrote:
>
> TSO packets are not checked against the device limits before use.
> The device requires an MSS of 88 to 9728 bytes and a payload of at
> most 262143 bytes, as noted in the Linux driver. A packet outside
> these limits triggers malicious driver detection, which drops it and
> disables the datapath, stalling all queues.
>
> The missing checks also break the driver itself: a tso_segsz of 0
> divides by zero in gve_tx_validate_descs(), headers longer than 255
> bytes are truncated by the 8-bit header_len field, and headers not
> contained in the first segment give gve_tx_validate_descs() a
> negative first segment length.
>
> Drop TSO packets that violate these limits and count them as
> invalid_pkts.
>
> Fixes: 403c671a46b6 ("net/gve: support TSO in DQO RDA")
> Fixes: be8f0eb81f98 ("net/gve: fix DQO TSO descriptor limit")
> Cc: stable@dpdk.org
>
> Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
Acked-by: Joshua Washington <joshwash@google.com>
> ---
>  drivers/net/gve/base/gve_desc_dqo.h |  1 +
>  drivers/net/gve/gve_tx_dqo.c        | 14 +++++++++++++-
>  2 files changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/gve/base/gve_desc_dqo.h b/drivers/net/gve/base/gve_desc_dqo.h
> index d50d88765e..53e394f01c 100644
> --- a/drivers/net/gve/base/gve_desc_dqo.h
> +++ b/drivers/net/gve/base/gve_desc_dqo.h
> @@ -14,6 +14,7 @@
>  #define GVE_TX_MIN_TSO_MSS_DQO 88
>  #define GVE_TX_MIN_PKT_SIZE_DQO 17
>  #define GVE_TX_MAX_PKT_SIZE_DQO 9728
> +#define GVE_TX_MAX_TSO_LEN_DQO ((256 * 1024) - 1)
>
>  /* Basic TX descriptor (DTYPE 0x0C) */
>  struct gve_tx_pkt_desc_dqo {
> diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
> index f686a8c110..52fcdb285a 100644
> --- a/drivers/net/gve/gve_tx_dqo.c
> +++ b/drivers/net/gve/gve_tx_dqo.c
> @@ -127,11 +127,23 @@ gve_tx_clean_descs_dqo(struct gve_tx_queue *txq, uint16_t nb_descs) {
>  static inline bool
>  gve_tx_validate_pkt(const struct rte_mbuf *tx_pkt, bool is_tso)
>  {
> +       uint32_t headlen;
> +
>         if (!is_tso)
>                 return tx_pkt->pkt_len >= GVE_TX_MIN_PKT_SIZE_DQO &&
>                        tx_pkt->pkt_len <= GVE_TX_MAX_PKT_SIZE_DQO;
>
> -       return true;
> +       /* Headers must be present, fit the context descriptor, and be
> +        * contained in the first segment; the payload must not be empty.
> +        */
> +       headlen = tx_pkt->l2_len + tx_pkt->l3_len + tx_pkt->l4_len;
> +       if (tx_pkt->l4_len == 0 || headlen > GVE_TX_MAX_HDR_SIZE_DQO ||
> +           tx_pkt->data_len < headlen || tx_pkt->pkt_len <= headlen)
> +               return false;
> +
> +       return tx_pkt->pkt_len - headlen <= GVE_TX_MAX_TSO_LEN_DQO &&
> +              tx_pkt->tso_segsz >= GVE_TX_MIN_TSO_MSS_DQO &&
> +              tx_pkt->tso_segsz <= GVE_TX_MAX_PKT_SIZE_DQO;
>  }
>
>  /* Max descriptors a single packet may use. A larger packet can never pass
> --
> 2.43.0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v4 09/10] net/gve: enforce DQO Tx packet length limits
  2026-10-16 18:22   ` Joshua Washington
@ 2026-10-18  7:54     ` Tathagat Priyadarshi
  2026-10-19 16:55       ` Stephen Hemminger
  0 siblings, 1 reply; 18+ messages in thread
From: Tathagat Priyadarshi @ 2026-10-18  7:54 UTC (permalink / raw)
  To: Joshua Washington
  Cc: dev, Stephen Hemminger, stable, Jeroen de Borst, Rushil Gupta,
	Junfeng Guo

On Fri, Oct 16, 2026 at 11:52 PM Joshua Washington <joshwash@google.com> wrote:
>
> On Fri, Oct 16, 2026 at 10:46 AM Tathagat Priyadarshi
> <tathagat.dpdk@gmail.com> wrote:
> >
> > The device requires non-TSO packets to be 17 to 9728 bytes long, as
> > noted in the Linux driver, but packets of any length are posted. The
> > device treats an out-of-range packet as coming from a malicious
> > driver: it drops the packet and disables the datapath, stalling all
> > queues.
> >
> > Drop such packets in the driver and count them in a new invalid_pkts
> > counter.
> >
> > Fixes: 4022f9999f56 ("net/gve: support basic Tx data path for DQO")
> > Cc: stable@dpdk.org
> >
> > Signed-off-by: Tathagat Priyadarshi <tathagat.dpdk@gmail.com>
> Acked-by: Joshua Washington <joshwash@google.com>
> > ---
> >  drivers/net/gve/base/gve_desc_dqo.h |  2 ++
> >  drivers/net/gve/gve_ethdev.c        |  1 +
> >  drivers/net/gve/gve_ethdev.h        |  1 +
> >  drivers/net/gve/gve_tx_dqo.c        | 17 +++++++++++++++++
> >  4 files changed, 21 insertions(+)
> >
> > diff --git a/drivers/net/gve/base/gve_desc_dqo.h b/drivers/net/gve/base/gve_desc_dqo.h
> > index c1534959c2..d50d88765e 100644
> > --- a/drivers/net/gve/base/gve_desc_dqo.h
> > +++ b/drivers/net/gve/base/gve_desc_dqo.h
> > @@ -12,6 +12,8 @@
> >
> >  #define GVE_TX_MAX_HDR_SIZE_DQO 255
> >  #define GVE_TX_MIN_TSO_MSS_DQO 88
> > +#define GVE_TX_MIN_PKT_SIZE_DQO 17
> > +#define GVE_TX_MAX_PKT_SIZE_DQO 9728
> >
> >  /* Basic TX descriptor (DTYPE 0x0C) */
> >  struct gve_tx_pkt_desc_dqo {
> > diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
> > index 1dfbe8f396..53b0a0ec63 100644
> > --- a/drivers/net/gve/gve_ethdev.c
> > +++ b/drivers/net/gve/gve_ethdev.c
> > @@ -1044,6 +1044,7 @@ static const struct gve_xstats_name_offset tx_xstats_name_offset[] = {
> >         { "errors",  TX_QUEUE_STATS_OFFSET(errors) },
> >         { "too_many_descs", TX_QUEUE_STATS_OFFSET(too_many_descs) },
> >         { "invalid_mbufs", TX_QUEUE_STATS_OFFSET(invalid_mbufs) },
> > +       { "invalid_pkts", TX_QUEUE_STATS_OFFSET(invalid_pkts) },
> >  };
> >
> >  static const struct gve_xstats_name_offset rx_xstats_name_offset[] = {
> > diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
> > index 66cb31dadb..be744d955b 100644
> > --- a/drivers/net/gve/gve_ethdev.h
> > +++ b/drivers/net/gve/gve_ethdev.h
> > @@ -115,6 +115,7 @@ struct gve_tx_stats {
> >         uint64_t errors;
> >         uint64_t too_many_descs;
> >         uint64_t invalid_mbufs;
> > +       uint64_t invalid_pkts;
> >  };
> >
> >  struct gve_rx_stats {
> > diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
> > index 46a03d482d..f686a8c110 100644
> > --- a/drivers/net/gve/gve_tx_dqo.c
> > +++ b/drivers/net/gve/gve_tx_dqo.c
> > @@ -123,6 +123,17 @@ gve_tx_clean_descs_dqo(struct gve_tx_queue *txq, uint16_t nb_descs) {
> >                 gve_tx_clean_dqo(txq);
> >  }
> >
> > +/* Validate packet lengths against the device limits. */
> > +static inline bool
> > +gve_tx_validate_pkt(const struct rte_mbuf *tx_pkt, bool is_tso)
>
> Minor nit (not worth blocking over, but maybe can be done as the
> patches are being merged): can this be renamed to
> gve_tx_validate_pkt_len? This is one step of many in the packet
> validation pipeline.

Thanks for the review, Joshua. Agreed on renaming to gve_tx_validate_pkt_len.
This change impacts patches 9/10 and 10/10. I am happy to submit a v5
series if preferred,
or the maintainer can rename it upon applying.

>
> > +{
> > +       if (!is_tso)
> > +               return tx_pkt->pkt_len >= GVE_TX_MIN_PKT_SIZE_DQO &&
> > +                      tx_pkt->pkt_len <= GVE_TX_MAX_PKT_SIZE_DQO;
> > +
> > +       return true;
> > +}
> > +
> >  /* Max descriptors a single packet may use. A larger packet can never pass
> >   * gve_can_tx(): one slot is always reserved, the cacheline overlap margin
> >   * must stay free, and up to GVE_TX_MIN_RE_INTERVAL - 1 descriptors posted
> > @@ -306,6 +317,12 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
> >                 tso = !!(ol_flags & RTE_MBUF_F_TX_TCP_SEG);
> >                 csum = !!(ol_flags & GVE_TX_CKSUM_OFFLOAD_MASK_DQO);
> >
> > +               if (!gve_tx_validate_pkt(tx_pkt, tso)) {
> > +                       txq->stats.invalid_pkts++;
> > +                       rte_pktmbuf_free(tx_pkt);
> > +                       continue;
> > +               }
> > +
> >                 nb_descs = gve_tx_pkt_nb_data_descs(tx_pkt);
> >                 nb_descs += tso;
> >
> > --
> > 2.43.0
> >

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v4 09/10] net/gve: enforce DQO Tx packet length limits
  2026-10-18  7:54     ` Tathagat Priyadarshi
@ 2026-10-19 16:55       ` Stephen Hemminger
  2026-10-19 17:35         ` Joshua Washington
  0 siblings, 1 reply; 18+ messages in thread
From: Stephen Hemminger @ 2026-10-19 16:55 UTC (permalink / raw)
  To: Tathagat Priyadarshi
  Cc: Joshua Washington, dev, stable, Jeroen de Borst, Rushil Gupta,
	Junfeng Guo

On Sun, 18 Oct 2026 13:24:03 +0530
Tathagat Priyadarshi <tathagat.dpdk@gmail.com> wrote:

> > > +static inline bool
> > > +gve_tx_validate_pkt(const struct rte_mbuf *tx_pkt, bool is_tso)  
> >
> > Minor nit (not worth blocking over, but maybe can be done as the
> > patches are being merged): can this be renamed to
> > gve_tx_validate_pkt_len? This is one step of many in the packet
> > validation pipeline.  
> 
> Thanks for the review, Joshua. Agreed on renaming to gve_tx_validate_pkt_len.
> This change impacts patches 9/10 and 10/10. I am happy to submit a v5
> series if preferred,
> or the maintainer can rename it upon applying.

Renames should go through patchwork. I can cleanup commit messages and
release notes, that is where I stop.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v4 09/10] net/gve: enforce DQO Tx packet length limits
  2026-10-19 16:55       ` Stephen Hemminger
@ 2026-10-19 17:35         ` Joshua Washington
  0 siblings, 0 replies; 18+ messages in thread
From: Joshua Washington @ 2026-10-19 17:35 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Tathagat Priyadarshi, dev, dpdk stable, Jeroen de Borst,
	Rushil Gupta, Junfeng Guo

On Mon, Oct 19, 2026 at 9:55 AM Stephen Hemminger
<stephen@networkplumber.org> wrote:
>
> On Sun, 18 Oct 2026 13:24:03 +0530
> Tathagat Priyadarshi <tathagat.dpdk@gmail.com> wrote:
>
> > > > +static inline bool
> > > > +gve_tx_validate_pkt(const struct rte_mbuf *tx_pkt, bool is_tso)
> > >
> > > Minor nit (not worth blocking over, but maybe can be done as the
> > > patches are being merged): can this be renamed to
> > > gve_tx_validate_pkt_len? This is one step of many in the packet
> > > validation pipeline.
> >
> > Thanks for the review, Joshua. Agreed on renaming to gve_tx_validate_pkt_len.
> > This change impacts patches 9/10 and 10/10. I am happy to submit a v5
> > series if preferred,
> > or the maintainer can rename it upon applying.
>
> Renames should go through patchwork. I can cleanup commit messages and
> release notes, that is where I stop.

In that case, would it be okay to merge as-is? I will be following up
this series directly with some TX datapath fixes of my own which are
kind of related to Tathagat's fixes, so I can probably update the
function name in my patch series, rather than going to v5.

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2026-10-19 17:36 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 17:45 [PATCH v4 00/10] net/gve: fix DQO Tx queue stalls Tathagat Priyadarshi
2026-10-16 17:45 ` [PATCH v4 01/10] net/gve: fix DQO descriptor cleaning loop bound Tathagat Priyadarshi
2026-10-16 17:45 ` [PATCH v4 02/10] net/gve: fix DQO completion queue stall on unknown type Tathagat Priyadarshi
2026-10-16 17:45 ` [PATCH v4 03/10] net/gve: fix DQO Tx report event interval Tathagat Priyadarshi
2026-10-16 17:45 ` [PATCH v4 04/10] net/gve: fix stray TSO context descriptor on tag exhaustion Tathagat Priyadarshi
2026-10-16 17:45 ` [PATCH v4 05/10] net/gve: add cacheline overlap margin to DQO Tx ring Tathagat Priyadarshi
2026-10-16 17:45 ` [PATCH v4 06/10] net/gve: fix Tx stall on invalid packets Tathagat Priyadarshi
2026-10-16 17:45 ` [PATCH v4 07/10] net/gve: export Tx drop counters in xstats Tathagat Priyadarshi
2026-10-16 18:18   ` Joshua Washington
2026-10-16 17:45 ` [PATCH v4 08/10] net/gve: reject Tx packets that cannot fit in the ring Tathagat Priyadarshi
2026-10-16 18:18   ` Joshua Washington
2026-10-16 17:45 ` [PATCH v4 09/10] net/gve: enforce DQO Tx packet length limits Tathagat Priyadarshi
2026-10-16 18:22   ` Joshua Washington
2026-10-18  7:54     ` Tathagat Priyadarshi
2026-10-19 16:55       ` Stephen Hemminger
2026-10-19 17:35         ` Joshua Washington
2026-10-16 17:45 ` [PATCH v4 10/10] net/gve: enforce DQO TSO header and " Tathagat Priyadarshi
2026-10-16 18:33   ` Joshua Washington

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.