From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=DATE_IN_FUTURE_06_12, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E2C81C3A5A6 for ; Mon, 23 Sep 2019 06:24:02 +0000 (UTC) Received: from dpdk.org (dpdk.org [92.243.14.124]) by mail.kernel.org (Postfix) with ESMTP id 6F3C520835 for ; Mon, 23 Sep 2019 06:24:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6F3C520835 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=dev-bounces@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 0E0FC54AE; Mon, 23 Sep 2019 08:24:01 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 6163C4CE4; Mon, 23 Sep 2019 08:23:58 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 22 Sep 2019 23:23:56 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,539,1559545200"; d="scan'208";a="272179290" Received: from npg-dpdk-virtual-marvin-dev.sh.intel.com ([10.67.119.142]) by orsmga001.jf.intel.com with ESMTP; 22 Sep 2019 23:23:54 -0700 From: Marvin Liu To: maxime.coquelin@redhat.com, tiwei.bie@intel.com, zhihong.wang@intel.com, stephen@networkplumber.org Cc: dev@dpdk.org, stable@dpdk.org, Marvin Liu Date: Mon, 23 Sep 2019 22:05:11 +0800 Message-Id: <20190923140511.107939-1-yong.liu@intel.com> X-Mailer: git-send-email 2.17.1 Subject: [dpdk-dev] [PATCH] net/virtio: fix mbuf data and pkt length mismatch X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" If reserve virtio header room by function rte_pktmbuf_prepend, both segment data length and packet length of mbuf will be increased. Data length will be equal to descriptor length, while packet length should be decreased as virtio-net header won't be taken into packet. Thus will cause mismatch in mbuf structure. Fix this issue by access mbuf data directly and increase descriptor length if it is needed. Fixes: 58169a9c8153 ("net/virtio: support Tx checksum offload") Fixes: 892dc798fa9c ("net/virtio: implement Tx path for packed queues") Fixes: 4905ed3a523f ("net/virtio: optimize Tx enqueue for packed ring") Fixes: e5f456a98d3c ("net/virtio: support in-order Rx and Tx") Cc: stable@dpdk.org Reported-by: Stephen Hemminger Signed-off-by: Marvin Liu diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c index 27ead19fb..822cce06d 100644 --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -597,9 +597,8 @@ virtqueue_enqueue_xmit_inorder(struct virtnet_tx *txvq, dxp->cookie = (void *)cookies[i]; dxp->ndescs = 1; - hdr = (struct virtio_net_hdr *) - rte_pktmbuf_prepend(cookies[i], head_size); - cookies[i]->pkt_len -= head_size; + hdr = (struct virtio_net_hdr *)(char *)cookies[i]->buf_addr + + cookies[i]->data_off - head_size; /* if offload disabled, hdr is not zeroed yet, do it now */ if (!vq->hw->has_tx_offload) @@ -608,9 +607,10 @@ virtqueue_enqueue_xmit_inorder(struct virtnet_tx *txvq, virtqueue_xmit_offload(hdr, cookies[i], true); start_dp[idx].addr = VIRTIO_MBUF_DATA_DMA_ADDR(cookies[i], vq); - start_dp[idx].len = cookies[i]->data_len; + start_dp[idx].len = cookies[i]->data_len + head_size; start_dp[idx].flags = 0; + vq_update_avail_ring(vq, idx); idx++; @@ -644,9 +644,8 @@ virtqueue_enqueue_xmit_packed_fast(struct virtnet_tx *txvq, flags = vq->vq_packed.cached_flags; /* prepend cannot fail, checked by caller */ - hdr = (struct virtio_net_hdr *) - rte_pktmbuf_prepend(cookie, head_size); - cookie->pkt_len -= head_size; + hdr = (struct virtio_net_hdr *)(char *)cookie->buf_addr + + cookie->data_off - head_size; /* if offload disabled, hdr is not zeroed yet, do it now */ if (!vq->hw->has_tx_offload) @@ -655,7 +654,7 @@ virtqueue_enqueue_xmit_packed_fast(struct virtnet_tx *txvq, virtqueue_xmit_offload(hdr, cookie, true); dp->addr = VIRTIO_MBUF_DATA_DMA_ADDR(cookie, vq); - dp->len = cookie->data_len; + dp->len = cookie->data_len + head_size; dp->id = id; if (++vq->vq_avail_idx >= vq->vq_nentries) { @@ -687,6 +686,7 @@ virtqueue_enqueue_xmit_packed(struct virtnet_tx *txvq, struct rte_mbuf *cookie, uint16_t head_size = vq->hw->vtnet_hdr_size; struct virtio_net_hdr *hdr; uint16_t prev; + bool prepend_header = false; id = in_order ? vq->vq_avail_idx : vq->vq_desc_head_idx; @@ -705,12 +705,9 @@ virtqueue_enqueue_xmit_packed(struct virtnet_tx *txvq, struct rte_mbuf *cookie, if (can_push) { /* prepend cannot fail, checked by caller */ - hdr = (struct virtio_net_hdr *) - rte_pktmbuf_prepend(cookie, head_size); - /* rte_pktmbuf_prepend() counts the hdr size to the pkt length, - * which is wrong. Below subtract restores correct pkt size. - */ - cookie->pkt_len -= head_size; + hdr = (struct virtio_net_hdr *)(char *)cookie->buf_addr + + cookie->data_off - head_size; + prepend_header = true; /* if offload disabled, it is not zeroed below, do it now */ if (!vq->hw->has_tx_offload) @@ -738,6 +735,11 @@ virtqueue_enqueue_xmit_packed(struct virtnet_tx *txvq, struct rte_mbuf *cookie, start_dp[idx].addr = VIRTIO_MBUF_DATA_DMA_ADDR(cookie, vq); start_dp[idx].len = cookie->data_len; + if (prepend_header) { + start_dp[idx].len += head_size; + prepend_header = false; + } + if (likely(idx != head_idx)) { flags = cookie->next ? VRING_DESC_F_NEXT : 0; flags |= vq->vq_packed.cached_flags; @@ -779,6 +781,7 @@ virtqueue_enqueue_xmit(struct virtnet_tx *txvq, struct rte_mbuf *cookie, uint16_t seg_num = cookie->nb_segs; uint16_t head_idx, idx; uint16_t head_size = vq->hw->vtnet_hdr_size; + bool prepend_header = false; struct virtio_net_hdr *hdr; head_idx = vq->vq_desc_head_idx; @@ -794,12 +797,9 @@ virtqueue_enqueue_xmit(struct virtnet_tx *txvq, struct rte_mbuf *cookie, if (can_push) { /* prepend cannot fail, checked by caller */ - hdr = (struct virtio_net_hdr *) - rte_pktmbuf_prepend(cookie, head_size); - /* rte_pktmbuf_prepend() counts the hdr size to the pkt length, - * which is wrong. Below subtract restores correct pkt size. - */ - cookie->pkt_len -= head_size; + hdr = (struct virtio_net_hdr *)(char *)cookie->buf_addr + + cookie->data_off - head_size; + prepend_header = true; /* if offload disabled, it is not zeroed below, do it now */ if (!vq->hw->has_tx_offload) @@ -838,6 +838,10 @@ virtqueue_enqueue_xmit(struct virtnet_tx *txvq, struct rte_mbuf *cookie, do { start_dp[idx].addr = VIRTIO_MBUF_DATA_DMA_ADDR(cookie, vq); start_dp[idx].len = cookie->data_len; + if (prepend_header) { + start_dp[idx].len += head_size; + prepend_header = false; + } start_dp[idx].flags = cookie->next ? VRING_DESC_F_NEXT : 0; idx = start_dp[idx].next; } while ((cookie = cookie->next) != NULL); -- 2.17.1