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