From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 5608691AC for ; Wed, 21 Oct 2015 05:48:10 +0200 (CEST) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 20 Oct 2015 20:48:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.17,709,1437462000"; d="scan'208";a="831786570" Received: from yliu-dev.sh.intel.com ([10.239.66.49]) by fmsmga002.fm.intel.com with ESMTP; 20 Oct 2015 20:48:09 -0700 From: Yuanhan Liu To: dev@dpdk.org Date: Wed, 21 Oct 2015 11:48:13 +0800 Message-Id: <1445399294-18826-8-git-send-email-yuanhan.liu@linux.intel.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1445399294-18826-1-git-send-email-yuanhan.liu@linux.intel.com> References: <1445399294-18826-1-git-send-email-yuanhan.liu@linux.intel.com> Cc: "Michael S. Tsirkin" , marcel@redhat.com, Changchun Ouyang Subject: [dpdk-dev] [PATCH v7 7/8] vhost: add VHOST_USER_SET_VRING_ENABLE message 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: Wed, 21 Oct 2015 03:48:11 -0000 From: Changchun Ouyang This message is used to enable/disable a specific vring queue pair. The first queue pair is enabled by default. Signed-off-by: Changchun Ouyang Signed-off-by: Yuanhan Liu Acked-by: Flavio Leitner --- v7: invoke vring_state_changed() callback once for each queue pair. v6: add a vring state changed callback, for informing the application that a specific vring is enabled/disabled. You could either flush packets haven't been processed yet, or simply just drop them. --- lib/librte_vhost/rte_virtio_net.h | 9 ++++++++- lib/librte_vhost/vhost_rxtx.c | 10 ++++++++++ lib/librte_vhost/vhost_user/vhost-net-user.c | 5 +++++ lib/librte_vhost/vhost_user/vhost-net-user.h | 1 + lib/librte_vhost/vhost_user/virtio-net-user.c | 28 +++++++++++++++++++++++++++ lib/librte_vhost/vhost_user/virtio-net-user.h | 3 +++ lib/librte_vhost/virtio-net.c | 12 +++++++++--- 7 files changed, 64 insertions(+), 4 deletions(-) diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h index 5dd6493..fd87f01 100644 --- a/lib/librte_vhost/rte_virtio_net.h +++ b/lib/librte_vhost/rte_virtio_net.h @@ -89,6 +89,7 @@ struct vhost_virtqueue { volatile uint16_t last_used_idx_res; /**< Used for multiple devices reserving buffers. */ int callfd; /**< Used to notify the guest (trigger interrupt). */ int kickfd; /**< Currently unused as polling mode is enabled. */ + int enabled; struct buf_vector buf_vec[BUF_VECTOR_MAX]; /**< for scatter RX. */ } __rte_cache_aligned; @@ -132,7 +133,7 @@ struct virtio_memory { }; /** - * Device operations to add/remove device. + * Device and vring operations. * * Make sure to set VIRTIO_DEV_RUNNING to the device flags in new_device and * remove it in destroy_device. @@ -141,12 +142,18 @@ struct virtio_memory { struct virtio_net_device_ops { int (*new_device)(struct virtio_net *); /**< Add device. */ void (*destroy_device)(volatile struct virtio_net *); /**< Remove device. */ + + int (*vring_state_changed)(struct virtio_net *dev, uint16_t queue_id, int enable); /**< triggered when a vring is enabled or disabled */ }; static inline uint16_t __attribute__((always_inline)) rte_vring_available_entries(struct virtio_net *dev, uint16_t queue_id) { struct vhost_virtqueue *vq = dev->virtqueue[queue_id]; + + if (vq->enabled) + return 0; + return *(volatile uint16_t *)&vq->avail->idx - vq->last_used_idx_res; } diff --git a/lib/librte_vhost/vhost_rxtx.c b/lib/librte_vhost/vhost_rxtx.c index 14e00ef..400f263 100644 --- a/lib/librte_vhost/vhost_rxtx.c +++ b/lib/librte_vhost/vhost_rxtx.c @@ -86,6 +86,9 @@ virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id, } vq = dev->virtqueue[queue_id]; + if (unlikely(vq->enabled == 0)) + return 0; + count = (count > MAX_PKT_BURST) ? MAX_PKT_BURST : count; /* @@ -278,6 +281,7 @@ copy_from_mbuf_to_vring(struct virtio_net *dev, uint32_t queue_id, * (guest physical addr -> vhost virtual addr) */ vq = dev->virtqueue[queue_id]; + vb_addr = gpa_to_vva(dev, vq->buf_vec[vec_idx].buf_addr); vb_hdr_addr = vb_addr; @@ -485,6 +489,9 @@ virtio_dev_merge_rx(struct virtio_net *dev, uint16_t queue_id, } vq = dev->virtqueue[queue_id]; + if (unlikely(vq->enabled == 0)) + return 0; + count = RTE_MIN((uint32_t)MAX_PKT_BURST, count); if (count == 0) @@ -586,6 +593,9 @@ rte_vhost_dequeue_burst(struct virtio_net *dev, uint16_t queue_id, } vq = dev->virtqueue[queue_id]; + if (unlikely(vq->enabled == 0)) + return 0; + avail_idx = *((volatile uint16_t *)&vq->avail->idx); /* If there are no available buffers then return. */ diff --git a/lib/librte_vhost/vhost_user/vhost-net-user.c b/lib/librte_vhost/vhost_user/vhost-net-user.c index 8675cd4..f681676 100644 --- a/lib/librte_vhost/vhost_user/vhost-net-user.c +++ b/lib/librte_vhost/vhost_user/vhost-net-user.c @@ -99,6 +99,7 @@ static const char *vhost_message_str[VHOST_USER_MAX] = { [VHOST_USER_GET_PROTOCOL_FEATURES] = "VHOST_USER_GET_PROTOCOL_FEATURES", [VHOST_USER_SET_PROTOCOL_FEATURES] = "VHOST_USER_SET_PROTOCOL_FEATURES", [VHOST_USER_GET_QUEUE_NUM] = "VHOST_USER_GET_QUEUE_NUM", + [VHOST_USER_SET_VRING_ENABLE] = "VHOST_USER_SET_VRING_ENABLE", }; /** @@ -428,6 +429,10 @@ vserver_message_handler(int connfd, void *dat, int *remove) send_vhost_message(connfd, &msg); break; + case VHOST_USER_SET_VRING_ENABLE: + user_set_vring_enable(ctx, &msg.payload.state); + break; + default: break; diff --git a/lib/librte_vhost/vhost_user/vhost-net-user.h b/lib/librte_vhost/vhost_user/vhost-net-user.h index 389d21d..38637cc 100644 --- a/lib/librte_vhost/vhost_user/vhost-net-user.h +++ b/lib/librte_vhost/vhost_user/vhost-net-user.h @@ -66,6 +66,7 @@ typedef enum VhostUserRequest { VHOST_USER_GET_PROTOCOL_FEATURES = 15, VHOST_USER_SET_PROTOCOL_FEATURES = 16, VHOST_USER_GET_QUEUE_NUM = 17, + VHOST_USER_SET_VRING_ENABLE = 18, VHOST_USER_MAX } VhostUserRequest; diff --git a/lib/librte_vhost/vhost_user/virtio-net-user.c b/lib/librte_vhost/vhost_user/virtio-net-user.c index e83d279..dfddc43 100644 --- a/lib/librte_vhost/vhost_user/virtio-net-user.c +++ b/lib/librte_vhost/vhost_user/virtio-net-user.c @@ -306,6 +306,34 @@ user_get_vring_base(struct vhost_device_ctx ctx, return 0; } +/* + * when virtio queues are ready to work, qemu will send us to + * enable the virtio queue pair. + */ +int +user_set_vring_enable(struct vhost_device_ctx ctx, + struct vhost_vring_state *state) +{ + struct virtio_net *dev = get_device(ctx); + uint16_t base_idx = state->index; + int enable = (int)state->num; + + RTE_LOG(INFO, VHOST_CONFIG, + "set queue enable: %d to qp idx: %d\n", + enable, state->index); + + if (dev->protocol_features & (1 << VHOST_USER_PROTOCOL_F_MQ) && + notify_ops->vring_state_changed) { + notify_ops->vring_state_changed(dev, base_idx / VIRTIO_QNUM, + enable); + } + + dev->virtqueue[base_idx + VIRTIO_RXQ]->enabled = enable; + dev->virtqueue[base_idx + VIRTIO_TXQ]->enabled = enable; + + return 0; +} + void user_destroy_device(struct vhost_device_ctx ctx) { diff --git a/lib/librte_vhost/vhost_user/virtio-net-user.h b/lib/librte_vhost/vhost_user/virtio-net-user.h index 5f6d667..b82108d 100644 --- a/lib/librte_vhost/vhost_user/virtio-net-user.h +++ b/lib/librte_vhost/vhost_user/virtio-net-user.h @@ -52,5 +52,8 @@ void user_set_protocol_features(struct vhost_device_ctx ctx, int user_get_vring_base(struct vhost_device_ctx, struct vhost_vring_state *); +int user_set_vring_enable(struct vhost_device_ctx ctx, + struct vhost_vring_state *state); + void user_destroy_device(struct vhost_device_ctx); #endif diff --git a/lib/librte_vhost/virtio-net.c b/lib/librte_vhost/virtio-net.c index d644022..b11fd61 100644 --- a/lib/librte_vhost/virtio-net.c +++ b/lib/librte_vhost/virtio-net.c @@ -255,7 +255,7 @@ rm_config_ll_entry(struct virtio_net_config_ll *ll_dev, } static void -init_vring_queue(struct vhost_virtqueue *vq) +init_vring_queue(struct vhost_virtqueue *vq, int qp_idx) { memset(vq, 0, sizeof(struct vhost_virtqueue)); @@ -264,13 +264,19 @@ init_vring_queue(struct vhost_virtqueue *vq) /* Backends are set to -1 indicating an inactive device. */ vq->backend = -1; + + /* always set the default vq pair to enabled */ + if (qp_idx == 0) + vq->enabled = 1; } static void init_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx) { - init_vring_queue(dev->virtqueue[qp_idx * VIRTIO_QNUM + VIRTIO_RXQ]); - init_vring_queue(dev->virtqueue[qp_idx * VIRTIO_QNUM + VIRTIO_TXQ]); + uint32_t base_idx = qp_idx * VIRTIO_QNUM; + + init_vring_queue(dev->virtqueue[base_idx + VIRTIO_RXQ], qp_idx); + init_vring_queue(dev->virtqueue[base_idx + VIRTIO_TXQ], qp_idx); } static int -- 1.9.0