Before this patch, packets that are invalid in the DQO format with
respect to offloads, descriptor limits, or packet size limits, are
dropped by the driver without any form of recourse for the application,
potentially leading to a disruption in traffic that can be hard to
debug.

Introduce tx_pkt_prepare for the DQ queue format to avoid dropping
packets without first giving the application a way to know that they
are invalid.

Fixes: 84472d3edffa ("net/gve: fix Tx stall on invalid packets")
Cc: [email protected]

Signed-off-by: Joshua Washington <[email protected]>
Reviewed-by: Praveen Kaligineedi <[email protected]>
Reviewed-by: Ankit Garg <[email protected]>
---
Depends-on: series-39707 ("net/gve: fix DQO Tx queue stalls")
---
 drivers/net/gve/gve_ethdev.h |  3 ++
 drivers/net/gve/gve_tx_dqo.c | 64 ++++++++++++++++++++++++++++++++++--
 2 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 26c6a304a6..ab5af33ca9 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -649,6 +649,9 @@ gve_rx_burst_dqo(void *rxq, struct rte_mbuf **rx_pkts, 
uint16_t nb_pkts);
 uint16_t
 gve_tx_burst_dqo(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
 
+uint16_t
+gve_tx_pkt_prepare_dqo(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
+
 void
 gve_set_rx_function_dqo(struct rte_eth_dev *dev);
 
diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index 00a4ea9d27..67ad41d618 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2022-2023 Intel Corporation
  */
 
+#include <rte_net.h>
+
 #include "gve_ethdev.h"
 #include "base/gve_adminq.h"
 #include "rte_malloc.h"
@@ -125,7 +127,7 @@ gve_tx_clean_descs_dqo(struct gve_tx_queue *txq, uint16_t 
nb_descs) {
 
 /* Validate packet lengths against the device limits. */
 static inline bool
-gve_tx_validate_pkt(const struct rte_mbuf *tx_pkt, bool is_tso)
+gve_tx_validate_pkt_limits(const struct rte_mbuf *tx_pkt, bool is_tso)
 {
        uint32_t headlen;
 
@@ -303,6 +305,63 @@ gve_fill_tx_pkt_desc(struct gve_tx_queue *txq, uint16_t 
*tx_id,
        }
 }
 
+uint16_t
+gve_tx_pkt_prepare_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t 
nb_pkts)
+{
+       struct gve_tx_queue *txq = tx_queue;
+       uint16_t i;
+
+       for (i = 0; i < nb_pkts; i++) {
+               struct rte_mbuf *tx_pkt;
+               uint16_t nb_descs;
+               bool tso;
+               int err;
+
+               tx_pkt = tx_pkts[i];
+
+#ifdef RTE_ETHDEV_DEBUG_TX
+               const char *reason;
+
+               if (rte_mbuf_check(tx_pkt, true, &reason)) {
+                       rte_errno = EINVAL;
+                       return i;
+               }
+
+               err = rte_validate_tx_offload(tx_pkt);
+               if (err != 0) {
+                       rte_errno = -err;
+                       return i;
+               }
+#endif
+
+               tso = !!(tx_pkt->ol_flags & RTE_MBUF_F_TX_TCP_SEG);
+               if (!gve_tx_validate_pkt_limits(tx_pkt, tso)) {
+                       rte_errno = EINVAL;
+                       return i;
+               }
+
+               /* Handle non-TSO packets with a direct check of nb_segs. We
+                * already validated that the packet is no larger than 9728B, so
+                * every segment is guaranteed to only require a single
+                * descriptor.
+                */
+               nb_descs = tso ? gve_tx_pkt_nb_data_descs(tx_pkt) + 1 :
+                       tx_pkt->nb_segs;
+               if (!gve_tx_validate_descs(txq, tx_pkt, nb_descs, tso)) {
+                       rte_errno = ENOTSUP;
+                       return i;
+               }
+
+               err = rte_net_intel_cksum_prepare(tx_pkt);
+               if (err != 0) {
+                       rte_errno = -err;
+                       return i;
+               }
+       }
+
+       return nb_pkts;
+}
+
 uint16_t
 gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 {
@@ -349,7 +408,7 @@ 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)) {
+               if (!gve_tx_validate_pkt_limits(tx_pkt, tso)) {
                        txq->stats.invalid_pkts++;
                        rte_pktmbuf_free(tx_pkt);
                        continue;
@@ -703,4 +762,5 @@ void
 gve_set_tx_function_dqo(struct rte_eth_dev *dev)
 {
        dev->tx_pkt_burst = gve_tx_burst_dqo;
+       dev->tx_pkt_prepare = gve_tx_pkt_prepare_dqo;
 }
-- 
2.56.0.307.g5fe7bd680c-goog

Reply via email to