When empty segments are dropped, some descriptor variable values are
updated in the segment processing loop before it is exited. This can
lead to a wedged queue where all subsequent packets are dropped for
this queue.

Also move the check for empty packet to catch the case of a zero
length packet with multiple segments.

Fixes: d863f19efa4f ("net/vmxnet3: skip empty segments in transmission")
Cc: sta...@dpdk.org
Signed-off-by: Ronak Doshi <dos...@vmware.com>
Acked-by: Jochen Behrens <jbehr...@vmware.com>
--
Change log
v2: fixed typo
---
 drivers/net/vmxnet3/vmxnet3_rxtx.c | 33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/net/vmxnet3/vmxnet3_rxtx.c 
b/drivers/net/vmxnet3/vmxnet3_rxtx.c
index a875ffec07..f4cade0954 100644
--- a/drivers/net/vmxnet3/vmxnet3_rxtx.c
+++ b/drivers/net/vmxnet3/vmxnet3_rxtx.c
@@ -412,8 +412,8 @@ vmxnet3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 
        nb_tx = 0;
        while (nb_tx < nb_pkts) {
-               Vmxnet3_GenericDesc *gdesc;
-               vmxnet3_buf_info_t *tbi;
+               Vmxnet3_GenericDesc *gdesc = NULL;
+               vmxnet3_buf_info_t *tbi = NULL;
                uint32_t first2fill, avail, dw2;
                struct rte_mbuf *txm = tx_pkts[nb_tx];
                struct rte_mbuf *m_seg = txm;
@@ -457,18 +457,18 @@ vmxnet3_xmit_pkts(void *tx_queue, struct rte_mbuf 
**tx_pkts,
                        continue;
                }
 
+               /* Skip empty packets */
+               if (unlikely(rte_pktmbuf_pkt_len(txm) == 0)) {
+                       txq->stats.drop_total++;
+                       rte_pktmbuf_free(txm);
+                       nb_tx++;
+                       continue;
+               }
+
                if (txm->nb_segs == 1 &&
                    rte_pktmbuf_pkt_len(txm) <= txq->txdata_desc_size) {
                        struct Vmxnet3_TxDataDesc *tdd;
 
-                       /* Skip empty packets */
-                       if (unlikely(rte_pktmbuf_pkt_len(txm) == 0)) {
-                               txq->stats.drop_total++;
-                               rte_pktmbuf_free(txm);
-                               nb_tx++;
-                               continue;
-                       }
-
                        tdd = (struct Vmxnet3_TxDataDesc *)
                                ((uint8 *)txq->data_ring.base +
                                 txq->cmd_ring.next2fill *
@@ -481,6 +481,10 @@ vmxnet3_xmit_pkts(void *tx_queue, struct rte_mbuf 
**tx_pkts,
                dw2 = (txq->cmd_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT;
                first2fill = txq->cmd_ring.next2fill;
                do {
+                       /* Skip empty segments */
+                       if (unlikely(m_seg->data_len == 0))
+                               continue;
+
                        /* Remember the transmit buffer for cleanup */
                        tbi = txq->cmd_ring.buf_info + txq->cmd_ring.next2fill;
 
@@ -490,10 +494,6 @@ vmxnet3_xmit_pkts(void *tx_queue, struct rte_mbuf 
**tx_pkts,
                         */
                        gdesc = txq->cmd_ring.base + txq->cmd_ring.next2fill;
 
-                       /* Skip empty segments */
-                       if (unlikely(m_seg->data_len == 0))
-                               continue;
-
                        if (copy_size) {
                                uint64 offset =
                                        (uint64)txq->cmd_ring.next2fill *
@@ -514,6 +514,11 @@ vmxnet3_xmit_pkts(void *tx_queue, struct rte_mbuf 
**tx_pkts,
                        /* use the right gen for non-SOP desc */
                        dw2 = txq->cmd_ring.gen << VMXNET3_TXD_GEN_SHIFT;
                } while ((m_seg = m_seg->next) != NULL);
+               /* We must have executed the complete preceding loop at least
+                * once without skipping an empty segment, as we can't have
+                * a packet with only empty segments.
+                * Thus, tbi and gdesc have been initialized.
+                */
 
                /* set the last buf_info for the pkt */
                tbi->m = txm;
-- 
2.11.0

Reply via email to