Re: [Stratos-dev] [PATCH 3/5] vhost-user-rng: backend: Add RNG vhost-user daemon implementation
On Tue, 1 Jun 2021 at 15:01, Joakim Bech wrote: > > On Tue, Jun 01, 2021 at 08:03:20PM +, Mathieu Poirier via Stratos-dev > wrote: > > This patch provides the vhost-user backend implementation to work > > in tandem with the vhost-user-rng implementation of the QEMU VMM. > > > > It uses the vhost-user API so that other VMM can re-use the interface > > without having to write the driver again. > > > > Signed-off-by: Mathieu Poirier > > --- > > tools/meson.build| 8 + > > tools/vhost-user-rng/50-qemu-rng.json.in | 5 + > > tools/vhost-user-rng/main.c | 403 +++ > > tools/vhost-user-rng/meson.build | 10 + > > 4 files changed, 426 insertions(+) > > create mode 100644 tools/vhost-user-rng/50-qemu-rng.json.in > > create mode 100644 tools/vhost-user-rng/main.c > > create mode 100644 tools/vhost-user-rng/meson.build > > > > diff --git a/tools/meson.build b/tools/meson.build > > index 3e5a0abfa29f..66b0a11fbb45 100644 > > --- a/tools/meson.build > > +++ b/tools/meson.build > > @@ -24,3 +24,11 @@ endif > > if have_virtiofsd > >subdir('virtiofsd') > > endif > > + > > +have_virtiorng = (have_system and > > +have_tools and > > +'CONFIG_LINUX' in config_host) > > + > > +if have_virtiorng > > + subdir('vhost-user-rng') > > +endif > > diff --git a/tools/vhost-user-rng/50-qemu-rng.json.in > > b/tools/vhost-user-rng/50-qemu-rng.json.in > > new file mode 100644 > > index ..9186c3c6fe1d > > --- /dev/null > > +++ b/tools/vhost-user-rng/50-qemu-rng.json.in > > @@ -0,0 +1,5 @@ > > +{ > > + "description": "QEMU vhost-user-rng", > > + "type": "bridge", > > + "binary": "@libexecdir@/vhost-user-rng" > > +} > > diff --git a/tools/vhost-user-rng/main.c b/tools/vhost-user-rng/main.c > > new file mode 100644 > > index ..ba7380b12659 > > --- /dev/null > > +++ b/tools/vhost-user-rng/main.c > > @@ -0,0 +1,403 @@ > > +/* > > + * VIRTIO RNG Emulation via vhost-user > > + * > > + * Copyright (c) 2021 Mathieu Poirier > > + * > > + * SPDX-License-Identifier: GPL-2.0-or-later > > + */ > > + > > +#define G_LOG_DOMAIN "vhost-user-rng" > > +#define G_LOG_USE_STRUCTURED 1 > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "qemu/cutils.h" > > +#include "subprojects/libvhost-user/libvhost-user-glib.h" > > +#include "subprojects/libvhost-user/libvhost-user.h" > > + > > +#ifndef container_of > > +#define container_of(ptr, type, member) ({ \ > > +const typeof(((type *) 0)->member) * __mptr = (ptr); \ > > +(type *) ((char *) __mptr - offsetof(type, member)); }) > > +#endif > > + > > +typedef struct { > > +VugDev dev; > > +struct itimerspec ts; > > +timer_t rate_limit_timer; > > +pthread_mutex_t rng_mutex; > > +pthread_cond_t rng_cond; > > +int64_t quota_remaining; > > +bool activate_timer; > > +GMainLoop *loop; > > +} VuRNG; > > + > > +static gboolean print_cap, verbose; > > +static gchar *source_path, *socket_path; > > +static gint source_fd, socket_fd = -1; > > + > > +/* Defaults tailored on virtio-rng.c */ > > +static uint32_t period_ms = 1 << 16; > > +static uint64_t max_bytes = INT64_MAX; > > + > > +static void check_rate_limit(union sigval sv) > > +{ > > +VuRNG *rng = sv.sival_ptr; > > +bool wakeup = false; > > + > > +pthread_mutex_lock(>rng_mutex); > > +/* > > + * The timer has expired and the guest has used all available > > + * antropy, which means function vu_rng_handle_request() is waiting > s/antropy/entropy/ > > I also found 'antropy' at two more locations in this patch (that made me > wonder). > Thanks for pointing that out, will fix for the next revision. Mathieu > > + * on us. As such wake it up once we're done here. > > + */ > > +if (rng->quota_remaining == 0) { > > +wakeup = true; > > +} > > + > > +/* > > + * Reset the antropy available to the guest and tell function > > + * vu_rng_handle_requests() to start the timer before using it. > > + */ > > +rng->quota_remaining = max_bytes; > > +rng->activate_timer = true; > > +pthread_mutex_unlock(>rng_mutex); > > + > > +if (wakeup) { > > +pthread_cond_signal(>rng_cond); > > +} > > +} > > + > > +static void setup_timer(VuRNG *rng) > > +{ > > +struct sigevent sev; > > +int ret; > > + > > +memset(>ts, 0, sizeof(struct itimerspec)); > > +rng->ts.it_value.tv_sec = period_ms / 1000; > > +rng->ts.it_value.tv_nsec = (period_ms % 1000) * 100; > > + > > +/* > > + * Call function check_rate_limit() as if it was the start of > > + * a new thread when the timer expires. > > + */ > > +sev.sigev_notify =
Re: [Stratos-dev] [PATCH 3/5] vhost-user-rng: backend: Add RNG vhost-user daemon implementation
On Tue, Jun 01, 2021 at 08:03:20PM +, Mathieu Poirier via Stratos-dev wrote: > This patch provides the vhost-user backend implementation to work > in tandem with the vhost-user-rng implementation of the QEMU VMM. > > It uses the vhost-user API so that other VMM can re-use the interface > without having to write the driver again. > > Signed-off-by: Mathieu Poirier > --- > tools/meson.build| 8 + > tools/vhost-user-rng/50-qemu-rng.json.in | 5 + > tools/vhost-user-rng/main.c | 403 +++ > tools/vhost-user-rng/meson.build | 10 + > 4 files changed, 426 insertions(+) > create mode 100644 tools/vhost-user-rng/50-qemu-rng.json.in > create mode 100644 tools/vhost-user-rng/main.c > create mode 100644 tools/vhost-user-rng/meson.build > > diff --git a/tools/meson.build b/tools/meson.build > index 3e5a0abfa29f..66b0a11fbb45 100644 > --- a/tools/meson.build > +++ b/tools/meson.build > @@ -24,3 +24,11 @@ endif > if have_virtiofsd >subdir('virtiofsd') > endif > + > +have_virtiorng = (have_system and > +have_tools and > +'CONFIG_LINUX' in config_host) > + > +if have_virtiorng > + subdir('vhost-user-rng') > +endif > diff --git a/tools/vhost-user-rng/50-qemu-rng.json.in > b/tools/vhost-user-rng/50-qemu-rng.json.in > new file mode 100644 > index ..9186c3c6fe1d > --- /dev/null > +++ b/tools/vhost-user-rng/50-qemu-rng.json.in > @@ -0,0 +1,5 @@ > +{ > + "description": "QEMU vhost-user-rng", > + "type": "bridge", > + "binary": "@libexecdir@/vhost-user-rng" > +} > diff --git a/tools/vhost-user-rng/main.c b/tools/vhost-user-rng/main.c > new file mode 100644 > index ..ba7380b12659 > --- /dev/null > +++ b/tools/vhost-user-rng/main.c > @@ -0,0 +1,403 @@ > +/* > + * VIRTIO RNG Emulation via vhost-user > + * > + * Copyright (c) 2021 Mathieu Poirier > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#define G_LOG_DOMAIN "vhost-user-rng" > +#define G_LOG_USE_STRUCTURED 1 > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "qemu/cutils.h" > +#include "subprojects/libvhost-user/libvhost-user-glib.h" > +#include "subprojects/libvhost-user/libvhost-user.h" > + > +#ifndef container_of > +#define container_of(ptr, type, member) ({ \ > +const typeof(((type *) 0)->member) * __mptr = (ptr); \ > +(type *) ((char *) __mptr - offsetof(type, member)); }) > +#endif > + > +typedef struct { > +VugDev dev; > +struct itimerspec ts; > +timer_t rate_limit_timer; > +pthread_mutex_t rng_mutex; > +pthread_cond_t rng_cond; > +int64_t quota_remaining; > +bool activate_timer; > +GMainLoop *loop; > +} VuRNG; > + > +static gboolean print_cap, verbose; > +static gchar *source_path, *socket_path; > +static gint source_fd, socket_fd = -1; > + > +/* Defaults tailored on virtio-rng.c */ > +static uint32_t period_ms = 1 << 16; > +static uint64_t max_bytes = INT64_MAX; > + > +static void check_rate_limit(union sigval sv) > +{ > +VuRNG *rng = sv.sival_ptr; > +bool wakeup = false; > + > +pthread_mutex_lock(>rng_mutex); > +/* > + * The timer has expired and the guest has used all available > + * antropy, which means function vu_rng_handle_request() is waiting s/antropy/entropy/ I also found 'antropy' at two more locations in this patch (that made me wonder). > + * on us. As such wake it up once we're done here. > + */ > +if (rng->quota_remaining == 0) { > +wakeup = true; > +} > + > +/* > + * Reset the antropy available to the guest and tell function > + * vu_rng_handle_requests() to start the timer before using it. > + */ > +rng->quota_remaining = max_bytes; > +rng->activate_timer = true; > +pthread_mutex_unlock(>rng_mutex); > + > +if (wakeup) { > +pthread_cond_signal(>rng_cond); > +} > +} > + > +static void setup_timer(VuRNG *rng) > +{ > +struct sigevent sev; > +int ret; > + > +memset(>ts, 0, sizeof(struct itimerspec)); > +rng->ts.it_value.tv_sec = period_ms / 1000; > +rng->ts.it_value.tv_nsec = (period_ms % 1000) * 100; > + > +/* > + * Call function check_rate_limit() as if it was the start of > + * a new thread when the timer expires. > + */ > +sev.sigev_notify = SIGEV_THREAD; > +sev.sigev_notify_function = check_rate_limit; > +sev.sigev_value.sival_ptr = rng; > +/* Needs to be NULL if defaults attributes are to be used. */ > +sev.sigev_notify_attributes = NULL; > +ret = timer_create(CLOCK_MONOTONIC, , >rate_limit_timer); > +if (ret < 0) { > +fprintf(stderr, "timer_create() failed\n"); > +} > + > +} > + > + > +/* Virtio helpers */ > +static uint64_t
[PATCH 3/5] vhost-user-rng: backend: Add RNG vhost-user daemon implementation
This patch provides the vhost-user backend implementation to work in tandem with the vhost-user-rng implementation of the QEMU VMM. It uses the vhost-user API so that other VMM can re-use the interface without having to write the driver again. Signed-off-by: Mathieu Poirier --- tools/meson.build| 8 + tools/vhost-user-rng/50-qemu-rng.json.in | 5 + tools/vhost-user-rng/main.c | 403 +++ tools/vhost-user-rng/meson.build | 10 + 4 files changed, 426 insertions(+) create mode 100644 tools/vhost-user-rng/50-qemu-rng.json.in create mode 100644 tools/vhost-user-rng/main.c create mode 100644 tools/vhost-user-rng/meson.build diff --git a/tools/meson.build b/tools/meson.build index 3e5a0abfa29f..66b0a11fbb45 100644 --- a/tools/meson.build +++ b/tools/meson.build @@ -24,3 +24,11 @@ endif if have_virtiofsd subdir('virtiofsd') endif + +have_virtiorng = (have_system and +have_tools and +'CONFIG_LINUX' in config_host) + +if have_virtiorng + subdir('vhost-user-rng') +endif diff --git a/tools/vhost-user-rng/50-qemu-rng.json.in b/tools/vhost-user-rng/50-qemu-rng.json.in new file mode 100644 index ..9186c3c6fe1d --- /dev/null +++ b/tools/vhost-user-rng/50-qemu-rng.json.in @@ -0,0 +1,5 @@ +{ + "description": "QEMU vhost-user-rng", + "type": "bridge", + "binary": "@libexecdir@/vhost-user-rng" +} diff --git a/tools/vhost-user-rng/main.c b/tools/vhost-user-rng/main.c new file mode 100644 index ..ba7380b12659 --- /dev/null +++ b/tools/vhost-user-rng/main.c @@ -0,0 +1,403 @@ +/* + * VIRTIO RNG Emulation via vhost-user + * + * Copyright (c) 2021 Mathieu Poirier + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#define G_LOG_DOMAIN "vhost-user-rng" +#define G_LOG_USE_STRUCTURED 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qemu/cutils.h" +#include "subprojects/libvhost-user/libvhost-user-glib.h" +#include "subprojects/libvhost-user/libvhost-user.h" + +#ifndef container_of +#define container_of(ptr, type, member) ({ \ +const typeof(((type *) 0)->member) * __mptr = (ptr); \ +(type *) ((char *) __mptr - offsetof(type, member)); }) +#endif + +typedef struct { +VugDev dev; +struct itimerspec ts; +timer_t rate_limit_timer; +pthread_mutex_t rng_mutex; +pthread_cond_t rng_cond; +int64_t quota_remaining; +bool activate_timer; +GMainLoop *loop; +} VuRNG; + +static gboolean print_cap, verbose; +static gchar *source_path, *socket_path; +static gint source_fd, socket_fd = -1; + +/* Defaults tailored on virtio-rng.c */ +static uint32_t period_ms = 1 << 16; +static uint64_t max_bytes = INT64_MAX; + +static void check_rate_limit(union sigval sv) +{ +VuRNG *rng = sv.sival_ptr; +bool wakeup = false; + +pthread_mutex_lock(>rng_mutex); +/* + * The timer has expired and the guest has used all available + * antropy, which means function vu_rng_handle_request() is waiting + * on us. As such wake it up once we're done here. + */ +if (rng->quota_remaining == 0) { +wakeup = true; +} + +/* + * Reset the antropy available to the guest and tell function + * vu_rng_handle_requests() to start the timer before using it. + */ +rng->quota_remaining = max_bytes; +rng->activate_timer = true; +pthread_mutex_unlock(>rng_mutex); + +if (wakeup) { +pthread_cond_signal(>rng_cond); +} +} + +static void setup_timer(VuRNG *rng) +{ +struct sigevent sev; +int ret; + +memset(>ts, 0, sizeof(struct itimerspec)); +rng->ts.it_value.tv_sec = period_ms / 1000; +rng->ts.it_value.tv_nsec = (period_ms % 1000) * 100; + +/* + * Call function check_rate_limit() as if it was the start of + * a new thread when the timer expires. + */ +sev.sigev_notify = SIGEV_THREAD; +sev.sigev_notify_function = check_rate_limit; +sev.sigev_value.sival_ptr = rng; +/* Needs to be NULL if defaults attributes are to be used. */ +sev.sigev_notify_attributes = NULL; +ret = timer_create(CLOCK_MONOTONIC, , >rate_limit_timer); +if (ret < 0) { +fprintf(stderr, "timer_create() failed\n"); +} + +} + + +/* Virtio helpers */ +static uint64_t rng_get_features(VuDev *dev) +{ +if (verbose) { +g_info("%s: replying", __func__); +} +return 0; +} + +static void rng_set_features(VuDev *dev, uint64_t features) +{ +if (verbose && features) { +g_autoptr(GString) s = g_string_new("Requested un-handled feature"); +g_string_append_printf(s, " 0x%" PRIx64 "", features); +g_info("%s: %s", __func__, s->str); +} +} + +static void vu_rng_handle_requests(VuDev *dev, int qidx) +{ +VuRNG *rng = container_of(dev, VuRNG, dev.parent);