Re: [Stratos-dev] [PATCH 3/5] vhost-user-rng: backend: Add RNG vhost-user daemon implementation

2021-06-02 Thread Mathieu Poirier
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

2021-06-01 Thread Joakim Bech
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

2021-06-01 Thread Mathieu Poirier
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);