From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0DC80A04B3; Mon, 16 Dec 2019 11:17:00 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 79C151BFB4; Mon, 16 Dec 2019 11:16:59 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id DEF881BFAB; Mon, 16 Dec 2019 11:16:57 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Dec 2019 02:16:56 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.69,321,1571727600"; d="scan'208";a="217123851" Received: from dpdk-xuanding-dev2.sh.intel.com ([10.67.119.47]) by orsmga006.jf.intel.com with ESMTP; 16 Dec 2019 02:16:54 -0800 From: Xuan Ding To: dev@dpdk.org Cc: maxime.coquelin@redhat.com, Bie@dpdk.org, Tiwei , Wang@dpdk.org, Zhihong , Xuan Ding , stable@dpdk.org Date: Mon, 16 Dec 2019 10:16:31 +0000 Message-Id: <20191216101631.81713-1-xuan.ding@intel.com> X-Mailer: git-send-email 2.17.1 Subject: [dpdk-dev] [PATCH v2] net/virtio-user: fix packed ring server mode 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" This patch fixes the situation where datapath does not work properly when vhost reconnects to virtio in server mode with packed ring. Currently, virtio and vhost share memory of vring. For split ring, vhost can read the status of discriptors directly from the available ring and the used ring during reconnection. Therefore, the datapath can continue. But for packed ring, when reconnecting to virtio, vhost cannot get the status of discriptors only through the descriptor ring. By resetting Tx and Rx queues, the datapath can restart from the beginning. Fixes: 4c3f5822eb214 ("net/virtio: add packed virtqueue defines") Cc: stable@dpdk.org Signed-off-by: Xuan Ding v2 changes: * Renamed queue reset functions and moved them to virtqueue.c. --- drivers/net/virtio/virtio_ethdev.c | 48 ++++++++++++++++- drivers/net/virtio/virtio_ethdev.h | 2 + drivers/net/virtio/virtio_user_ethdev.c | 8 +++ drivers/net/virtio/virtqueue.c | 71 +++++++++++++++++++++++++ drivers/net/virtio/virtqueue.h | 4 ++ 5 files changed, 131 insertions(+), 2 deletions(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 044eb10a7..5ba1cc743 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -433,6 +433,28 @@ virtio_init_vring(struct virtqueue *vq) virtqueue_disable_intr(vq); } +static int +virtqueue_reset_packed(struct rte_eth_dev *dev) +{ + uint16_t i; + struct virtnet_rx *rxvq; + struct virtnet_tx *txvq; + + /* Vring reset for each Tx queue and Rx queue. */ + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxvq = dev->data->rx_queues[i]; + virtqueue_rxvq_reset_packed(rxvq->vq); + virtio_dev_rx_queue_setup_finish(dev, i); + } + + for (i = 0; i < dev->data->nb_tx_queues; i++) { + txvq = dev->data->tx_queues[i]; + virtqueue_txvq_reset_packed(txvq->vq); + } + + return 0; +} + static int virtio_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx) { @@ -1913,6 +1935,8 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) goto err_vtpci_init; } + rte_spinlock_init(&hw->state_lock); + /* reset device and negotiate default features */ ret = virtio_init_device(eth_dev, VIRTIO_PMD_DEFAULT_GUEST_FEATURES); if (ret < 0) @@ -2155,8 +2179,6 @@ virtio_dev_configure(struct rte_eth_dev *dev) return -EBUSY; } - rte_spinlock_init(&hw->state_lock); - hw->use_simple_rx = 1; if (vtpci_with_feature(hw, VIRTIO_F_IN_ORDER)) { @@ -2421,6 +2443,28 @@ virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask) return 0; } +int +virtio_user_reset_device(struct rte_eth_dev *dev) +{ + struct virtio_hw *hw = dev->data->dev_private; + + /* Add lock to avoid queue contention. */ + rte_spinlock_lock(&hw->state_lock); + hw->started = 0; + /* + * Waitting for datapath to complete before resetting queues. + * 1 ms should be enough for the ongoing Tx/Rx function to finish. + */ + rte_delay_ms(1); + + virtqueue_reset_packed(dev); + + hw->started = 1; + rte_spinlock_unlock(&hw->state_lock); + + return 0; +} + static int virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { diff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h index a10111758..f63266437 100644 --- a/drivers/net/virtio/virtio_ethdev.h +++ b/drivers/net/virtio/virtio_ethdev.h @@ -49,6 +49,8 @@ extern const struct eth_dev_ops virtio_user_secondary_eth_dev_ops; +int virtio_user_reset_device(struct rte_eth_dev *dev); + /* * CQ function prototype */ diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c index 3fc172573..9641a9c71 100644 --- a/drivers/net/virtio/virtio_user_ethdev.c +++ b/drivers/net/virtio/virtio_user_ethdev.c @@ -31,6 +31,7 @@ virtio_user_server_reconnect(struct virtio_user_dev *dev) int ret; int connectfd; struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->port_id]; + struct virtio_hw *hw = eth_dev->data->dev_private; connectfd = accept(dev->listenfd, NULL, NULL); if (connectfd < 0) @@ -51,6 +52,13 @@ virtio_user_server_reconnect(struct virtio_user_dev *dev) dev->features &= dev->device_features; + /* + * * For packed ring, resetting queues + * is required in reconnection. + */ + if (vtpci_packed_queue(hw)) + virtio_user_reset_device(eth_dev); + ret = virtio_user_start_device(dev); if (ret < 0) return -1; diff --git a/drivers/net/virtio/virtqueue.c b/drivers/net/virtio/virtqueue.c index 5ff1e3587..796802b88 100644 --- a/drivers/net/virtio/virtqueue.c +++ b/drivers/net/virtio/virtqueue.c @@ -141,3 +141,74 @@ virtqueue_rxvq_flush(struct virtqueue *vq) else virtqueue_rxvq_flush_split(vq); } + +int +virtqueue_rxvq_reset_packed(struct virtqueue *vq) +{ + struct virtnet_rx *rxvq; + struct vq_desc_extra *dxp; + int size = vq->vq_nentries; + uint16_t desc_idx; + + vq->vq_used_cons_idx = 0; + vq->vq_desc_head_idx = 0; + vq->vq_avail_idx = 0; + vq->vq_desc_tail_idx = (uint16_t)(vq->vq_nentries - 1); + vq->vq_free_cnt = vq->vq_nentries; + + vq->vq_packed.used_wrap_counter = 1; + vq->vq_packed.cached_flags = VRING_PACKED_DESC_F_AVAIL; + vq->vq_packed.event_flags_shadow = 0; + vq->vq_packed.cached_flags |= VRING_DESC_F_WRITE; + + rxvq = &vq->rxq; + memset(rxvq->mz->addr, 0, rxvq->mz->len); + + for (desc_idx = 0; desc_idx < vq->vq_nentries; desc_idx++) { + dxp = &vq->vq_descx[desc_idx]; + if (dxp->cookie != NULL) { + rte_pktmbuf_free(dxp->cookie); + dxp->cookie = NULL; + } + } + + vring_desc_init_packed(vq, size); + + return 0; +} + +int +virtqueue_txvq_reset_packed(struct virtqueue *vq) +{ + struct virtnet_tx *txvq; + struct vq_desc_extra *dxp; + int size = vq->vq_nentries; + uint16_t desc_idx; + + vq->vq_used_cons_idx = 0; + vq->vq_desc_head_idx = 0; + vq->vq_avail_idx = 0; + vq->vq_desc_tail_idx = (uint16_t)(vq->vq_nentries - 1); + vq->vq_free_cnt = vq->vq_nentries; + + vq->vq_packed.used_wrap_counter = 1; + vq->vq_packed.cached_flags = VRING_PACKED_DESC_F_AVAIL; + vq->vq_packed.event_flags_shadow = 0; + + txvq = &vq->txq; + memset(txvq->mz->addr, 0, txvq->mz->len); + memset(txvq->virtio_net_hdr_mz->addr, 0, + txvq->virtio_net_hdr_mz->len); + + for (desc_idx = 0; desc_idx < vq->vq_nentries; desc_idx++) { + dxp = &vq->vq_descx[desc_idx]; + if (dxp->cookie != NULL) { + rte_pktmbuf_free(dxp->cookie); + dxp->cookie = NULL; + } + } + + vring_desc_init_packed(vq, size); + + return 0; +} diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h index 8d7f197b1..58ad7309a 100644 --- a/drivers/net/virtio/virtqueue.h +++ b/drivers/net/virtio/virtqueue.h @@ -443,6 +443,10 @@ struct rte_mbuf *virtqueue_detach_unused(struct virtqueue *vq); /* Flush the elements in the used ring. */ void virtqueue_rxvq_flush(struct virtqueue *vq); +int virtqueue_rxvq_reset_packed(struct virtqueue *vq); + +int virtqueue_txvq_reset_packed(struct virtqueue *vq); + static inline int virtqueue_full(const struct virtqueue *vq) { -- 2.17.1