net/virtio: fix in-order Rx with segmented packet

After having dequeued a burst of descriptors, there may be a
need to dequeue a few more if the last packet was segmented
and not complete. When it happens, the extra segments were
not properly attached to the mbuf chain, and so were lost.

Also, head segment data_len field is wrongly summed with
the length of all the segments of the chain.

This patch fixes both the mbuf chaining and head segment's
data_len field.

Fixes: e5f456a98d3c ("net/virtio: support in-order Rx and Tx")
Cc: stable@dpdk.org

Reported-by: Yaroslav Brustinov <ybrustin@cisco.com>
Reviewed-by: David Marchand <david.marchand@redhat.com>
Reviewed-by: Tiwei Bie <tiwei.bie@intel.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
This commit is contained in:
Maxime Coquelin 2019-06-05 12:00:36 +02:00 committed by Ferruh Yigit
parent fa2407ac30
commit 61d0bec3ba

View File

@ -1419,7 +1419,7 @@ virtio_recv_pkts_inorder(void *rx_queue,
struct virtqueue *vq = rxvq->vq;
struct virtio_hw *hw = vq->hw;
struct rte_mbuf *rxm;
struct rte_mbuf *prev;
struct rte_mbuf *prev = NULL;
uint16_t nb_used, num, nb_rx;
uint32_t len[VIRTIO_MBUF_BURST_SZ];
struct rte_mbuf *rcv_pkts[VIRTIO_MBUF_BURST_SZ];
@ -1511,7 +1511,6 @@ virtio_recv_pkts_inorder(void *rx_queue,
rxm->data_len = (uint16_t)(len[i]);
rx_pkts[nb_rx]->pkt_len += (uint32_t)(len[i]);
rx_pkts[nb_rx]->data_len += (uint16_t)(len[i]);
if (prev)
prev->next = rxm;
@ -1531,7 +1530,6 @@ virtio_recv_pkts_inorder(void *rx_queue,
uint16_t rcv_cnt = RTE_MIN((uint16_t)seg_res,
VIRTIO_MBUF_BURST_SZ);
prev = rcv_pkts[nb_rx];
if (likely(VIRTQUEUE_NUSED(vq) >= rcv_cnt)) {
virtio_rmb(hw->weak_barriers);
num = virtqueue_dequeue_rx_inorder(vq, rcv_pkts, len,
@ -1548,7 +1546,6 @@ virtio_recv_pkts_inorder(void *rx_queue,
prev->next = rxm;
prev = rxm;
rx_pkts[nb_rx]->pkt_len += len[extra_idx];
rx_pkts[nb_rx]->data_len += len[extra_idx];
extra_idx += 1;
};
seg_res -= rcv_cnt;