Skip to content

Commit

Permalink
net/vmxnet3: fix drop of empty segments in Tx
Browse files Browse the repository at this point in the history
[ upstream commit b44f3e1381f3910be50d03c784f5c073c25245dd ]

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: d863f19 ("net/vmxnet3: skip empty segments in transmission")

Signed-off-by: Ronak Doshi <doshir@vmware.com>
Acked-by: Jochen Behrens <jbehrens@vmware.com>
  • Loading branch information
Ronak Doshi authored and kevintraynor committed Jul 11, 2023
1 parent b23b258 commit 6de921b
Showing 1 changed file with 19 additions and 14 deletions.
33 changes: 19 additions & 14 deletions drivers/net/vmxnet3/vmxnet3_rxtx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 *
Expand All @@ -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;

Expand All @@ -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 *
Expand All @@ -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;
Expand Down

0 comments on commit 6de921b

Please sign in to comment.