From 5f4e42b80b62344b43c63a097b4ee2c383db460e Mon Sep 17 00:00:00 2001 From: Nikos Dragazis Date: Fri, 10 May 2019 14:37:54 +0300 Subject: [PATCH] vhost: abstract vring call mechanism as it is transport-specific vring notification mechanism is transport-specific. At present, vhost dataplane code in `lib/vhost/vhost.c` triggers guest notifications with `eventfd_write()` system call. But this is an AF_UNIX specific notification mechanism. This patch replaces `eventfd_write()` with the existing generic `rte_vhost_vring_call()` function that is part of DPDK's librte_vhost public API. `rte_vhost_vring_call()` takes a vring_idx as an argument to associate the `struct spdk_vhost_virtqueue` instance with the relevant `struct vhost_virtqueue` instance. We introduce a new `vring_idx` field in `struct spdk_vhost_virtqueue` to enable this association. This field is initialized in `start_device()`. In addition, a stub for `rte_vhost_vring_call()` is added in the vhost unit test file. SPDK's internal `rte_vhost` copy will not be updated in order to support the virtio-vhost-user transport. However, an `rte_vhost_vring_call()` function is introduced in SPDK's `rte_vhost` in order to have a solid API. This function is just a wrapper of `eventfd_write()`. Change-Id: Ic93e25cd3f06e92f04766521bc850f1ee80b8ec8 Signed-off-by: Nikos Dragazis Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454373 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Darek Stojaczyk --- lib/vhost/rte_vhost/rte_vhost.h | 12 ++++++++++++ lib/vhost/rte_vhost/vhost.c | 25 +++++++++++++++++++++++++ lib/vhost/vhost.c | 15 ++++++++++----- lib/vhost/vhost_internal.h | 2 ++ test/unit/lib/vhost/vhost.c/vhost_ut.c | 1 + 5 files changed, 50 insertions(+), 5 deletions(-) diff --git a/lib/vhost/rte_vhost/rte_vhost.h b/lib/vhost/rte_vhost/rte_vhost.h index b99cfb740..05b69e17f 100644 --- a/lib/vhost/rte_vhost/rte_vhost.h +++ b/lib/vhost/rte_vhost/rte_vhost.h @@ -472,4 +472,16 @@ int rte_vhost_set_vring_base(int vid, uint16_t queue_id, int rte_vhost_get_vring_base(int vid, uint16_t queue_id, uint16_t *last_avail_idx, uint16_t *last_used_idx); +/** + * Notify the guest that used descriptors have been added to the vring. + * + * @param vid + * vhost device ID + * @param vring_idx + * vring index + * @return + * 0 on success, -1 on failure + */ +int rte_vhost_vring_call(int vid, uint16_t vring_idx); + #endif /* _RTE_VHOST_H_ */ diff --git a/lib/vhost/rte_vhost/vhost.c b/lib/vhost/rte_vhost/vhost.c index 8e78bf9a0..61cbb1209 100644 --- a/lib/vhost/rte_vhost/vhost.c +++ b/lib/vhost/rte_vhost/vhost.c @@ -503,3 +503,28 @@ rte_vhost_get_vring_base(int vid, uint16_t vring_idx, return 0; } + +int +rte_vhost_vring_call(int vid, uint16_t vring_idx) +{ + struct virtio_net *dev; + struct vhost_virtqueue *vq; + + dev = get_device(vid); + if(!dev) + return -1; + + if (vring_idx >= VHOST_MAX_VRING) + return -1; + + vq = dev->virtqueue[vring_idx]; + if (!vq) + return -1; + + if (vq->callfd != -1) { + eventfd_write(vq->callfd, (eventfd_t)1); + return 0; + } + + return -1; +} diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index 1a9b05b79..2fbb34ada 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -278,8 +278,13 @@ spdk_vhost_vq_used_signal(struct spdk_vhost_session *vsession, "Queue %td - USED RING: sending IRQ: last used %"PRIu16"\n", virtqueue - vsession->virtqueue, virtqueue->last_used_idx); - eventfd_write(virtqueue->vring.callfd, (eventfd_t)1); - return 1; + if (rte_vhost_vring_call(vsession->vid, virtqueue->vring_idx) == 0) { + /* interrupt signalled */ + return 1; + } else { + /* interrupt not signalled */ + return 0; + } } @@ -1118,9 +1123,11 @@ start_device(int vid) for (i = 0; i < SPDK_VHOST_MAX_VQUEUES; i++) { struct spdk_vhost_virtqueue *q = &vsession->virtqueue[i]; + q->vring_idx = -1; if (rte_vhost_get_vhost_vring(vid, i, &q->vring)) { continue; } + q->vring_idx = i; if (q->vring.desc == NULL || q->vring.size == 0) { continue; @@ -1160,9 +1167,7 @@ start_device(int vid) * Tested on QEMU 2.10.91 and 2.11.50. */ for (i = 0; i < vsession->max_queues; i++) { - if (vsession->virtqueue[i].vring.callfd != -1) { - eventfd_write(vsession->virtqueue[i].vring.callfd, (eventfd_t)1); - } + rte_vhost_vring_call(vsession->vid, vsession->virtqueue[i].vring_idx); } spdk_vhost_session_set_coalescing(vdev, vsession, NULL); diff --git a/lib/vhost/vhost_internal.h b/lib/vhost/vhost_internal.h index 0e926d951..b52fb79d3 100644 --- a/lib/vhost/vhost_internal.h +++ b/lib/vhost/vhost_internal.h @@ -113,6 +113,8 @@ struct spdk_vhost_virtqueue { /* Next time when we need to send event */ uint64_t next_event_time; + /* Associated vhost_virtqueue in the virtio device's virtqueue list */ + uint32_t vring_idx; } __attribute((aligned(SPDK_CACHE_LINE_SIZE))); struct spdk_vhost_session { diff --git a/test/unit/lib/vhost/vhost.c/vhost_ut.c b/test/unit/lib/vhost/vhost.c/vhost_ut.c index f5fd2ea23..ce040e619 100644 --- a/test/unit/lib/vhost/vhost.c/vhost_ut.c +++ b/test/unit/lib/vhost/vhost.c/vhost_ut.c @@ -55,6 +55,7 @@ DEFINE_STUB(spdk_event_allocate, struct spdk_event *, (uint32_t lcore, spdk_event_fn fn, void *arg1, void *arg2), NULL); DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0); DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0); +DEFINE_STUB(rte_vhost_vring_call, int, (int vid, uint16_t vring_idx), 0); static struct spdk_cpuset *g_app_core_mask; struct spdk_cpuset *spdk_app_get_core_mask(void)