From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 66156532C; Tue, 20 Sep 2016 11:08:05 +0200 (CEST) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga103.fm.intel.com with ESMTP; 20 Sep 2016 02:08:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.30,367,1470726000"; d="scan'208";a="763653863" Received: from unknown (HELO dpdk5.sh.intel.com) ([10.239.129.118]) by FMSMGA003.fm.intel.com with ESMTP; 20 Sep 2016 02:08:03 -0700 From: Zhihong Wang To: dev@dpdk.org Cc: maxime.coquelin@redhat.com, yuanhan.liu@linux.intel.com, thomas.monjalon@6wind.com, stable@dpdk.org, Zhihong Wang Date: Mon, 19 Sep 2016 22:00:12 -0400 Message-Id: <1474336817-22683-2-git-send-email-zhihong.wang@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1474336817-22683-1-git-send-email-zhihong.wang@intel.com> References: <1471319402-112998-1-git-send-email-zhihong.wang@intel.com> <1474336817-22683-1-git-send-email-zhihong.wang@intel.com> Subject: [dpdk-dev] [PATCH v6 1/6] vhost: fix windows vm hang X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2016 09:08:06 -0000 This patch fixes a Windows VM compatibility issue in DPDK 16.07 vhost code which causes the guest to hang once any packets are enqueued when mrg_rxbuf is turned on by setting the right id and len in the used ring. As defined in virtio spec 0.95 and 1.0, in each used ring element, id means index of start of used descriptor chain, and len means total length of the descriptor chain which was written to. While in 16.07 code, index of the last descriptor is assigned to id, and the length of the last descriptor is assigned to len. How to test? 1. Start testpmd in the host with a vhost port. 2. Start a Windows VM image with qemu and connect to the vhost port. 3. Start io forwarding with tx_first in host testpmd. For 16.07 code, the Windows VM will hang once any packets are enqueued. Cc: Signed-off-by: Zhihong Wang --- Changes in v5: 1. Add details in commit log. lib/librte_vhost/virtio_net.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c index 8a151af..0d6e7d9 100644 --- a/lib/librte_vhost/virtio_net.c +++ b/lib/librte_vhost/virtio_net.c @@ -384,6 +384,8 @@ copy_mbuf_to_desc_mergeable(struct virtio_net *dev, struct vhost_virtqueue *vq, uint16_t start_idx = vq->last_used_idx; uint16_t cur_idx = start_idx; uint64_t desc_addr; + uint32_t desc_chain_head; + uint32_t desc_chain_len; uint32_t mbuf_offset, mbuf_avail; uint32_t desc_offset, desc_avail; uint32_t cpy_len; @@ -412,6 +414,8 @@ copy_mbuf_to_desc_mergeable(struct virtio_net *dev, struct vhost_virtqueue *vq, desc_avail = buf_vec[vec_idx].buf_len - dev->vhost_hlen; desc_offset = dev->vhost_hlen; + desc_chain_head = buf_vec[vec_idx].desc_idx; + desc_chain_len = desc_offset; mbuf_avail = rte_pktmbuf_data_len(m); mbuf_offset = 0; @@ -419,19 +423,21 @@ copy_mbuf_to_desc_mergeable(struct virtio_net *dev, struct vhost_virtqueue *vq, /* done with current desc buf, get the next one */ if (desc_avail == 0) { desc_idx = buf_vec[vec_idx].desc_idx; + vec_idx++; if (!(vq->desc[desc_idx].flags & VRING_DESC_F_NEXT)) { /* Update used ring with desc information */ used_idx = cur_idx++ & (vq->size - 1); - vq->used->ring[used_idx].id = desc_idx; - vq->used->ring[used_idx].len = desc_offset; + vq->used->ring[used_idx].id = desc_chain_head; + vq->used->ring[used_idx].len = desc_chain_len; vhost_log_used_vring(dev, vq, offsetof(struct vring_used, ring[used_idx]), sizeof(vq->used->ring[used_idx])); + desc_chain_head = buf_vec[vec_idx].desc_idx; + desc_chain_len = 0; } - vec_idx++; desc_addr = gpa_to_vva(dev, buf_vec[vec_idx].buf_addr); if (unlikely(!desc_addr)) return 0; @@ -463,11 +469,12 @@ copy_mbuf_to_desc_mergeable(struct virtio_net *dev, struct vhost_virtqueue *vq, mbuf_offset += cpy_len; desc_avail -= cpy_len; desc_offset += cpy_len; + desc_chain_len += cpy_len; } used_idx = cur_idx & (vq->size - 1); - vq->used->ring[used_idx].id = buf_vec[vec_idx].desc_idx; - vq->used->ring[used_idx].len = desc_offset; + vq->used->ring[used_idx].id = desc_chain_head; + vq->used->ring[used_idx].len = desc_chain_len; vhost_log_used_vring(dev, vq, offsetof(struct vring_used, ring[used_idx]), sizeof(vq->used->ring[used_idx])); -- 2.7.4