From 77d20126b4c21c57eb52caa8261a607704ed50f3 Mon Sep 17 00:00:00 2001 From: Changchun Ouyang Date: Thu, 22 Oct 2015 20:35:54 +0800 Subject: [PATCH] vhost-user: handle message to enable vring 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 Acked-by: Huawei Xie --- 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 | 27 +++++++++++++++++++ lib/librte_vhost/vhost_user/virtio-net-user.h | 3 +++ lib/librte_vhost/virtio-net.c | 12 ++++++--- 7 files changed, 63 insertions(+), 4 deletions(-) diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h index 9a32a95aed..426a70daca 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 1ec885003f..9322ce6e84 100644 --- a/lib/librte_vhost/vhost_rxtx.c +++ b/lib/librte_vhost/vhost_rxtx.c @@ -83,6 +83,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; /* @@ -275,6 +278,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; @@ -482,6 +486,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) @@ -583,6 +590,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 8675cd4d72..f681676ef6 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 389d21de20..38637cc2bb 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 7fc38053c9..a998ad8112 100644 --- a/lib/librte_vhost/vhost_user/virtio-net-user.c +++ b/lib/librte_vhost/vhost_user/virtio-net-user.c @@ -312,6 +312,33 @@ 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 (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 e7a6ff46a3..d46057e03b 100644 --- a/lib/librte_vhost/vhost_user/virtio-net-user.h +++ b/lib/librte_vhost/vhost_user/virtio-net-user.h @@ -50,5 +50,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 772f835067..48629d0449 100644 --- a/lib/librte_vhost/virtio-net.c +++ b/lib/librte_vhost/virtio-net.c @@ -254,7 +254,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)); @@ -263,13 +263,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 -- 2.20.1