Blame SOURCES/kvm-vhost-user-bridge-support-host-notifier.patch

1bdc94
From c331104889ecc51581ead4a154d37ad4d054ca73 Mon Sep 17 00:00:00 2001
1bdc94
From: "plai@redhat.com" <plai@redhat.com>
1bdc94
Date: Thu, 21 Jun 2018 18:54:40 +0200
1bdc94
Subject: [PATCH 31/57] vhost-user-bridge: support host notifier
1bdc94
1bdc94
RH-Author: plai@redhat.com
1bdc94
Message-id: <1529607285-9942-6-git-send-email-plai@redhat.com>
1bdc94
Patchwork-id: 80934
1bdc94
O-Subject: [RHEL7.6 PATCH BZ 1526645 05/10] vhost-user-bridge: support host notifier
1bdc94
Bugzilla: 1526645
1bdc94
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
1bdc94
RH-Acked-by: Maxime Coquelin <maxime.coquelin@redhat.com>
1bdc94
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
1bdc94
1bdc94
From: Tiwei Bie <tiwei.bie@intel.com>
1bdc94
1bdc94
This patch introduces the host notifier support in
1bdc94
vhost-user-bridge. A new option (-H) is added to use
1bdc94
the host notifier. This is mainly used to test the
1bdc94
host notifier implementation in vhost user.
1bdc94
1bdc94
Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
1bdc94
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
1bdc94
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
1bdc94
(cherry picked from commit e3af2928f8270498097af163bb023b633c0d8d1c)
1bdc94
Signed-off-by: Paul Lai <plai@redhat.com>
1bdc94
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
1bdc94
---
1bdc94
 tests/vhost-user-bridge.c | 98 +++++++++++++++++++++++++++++++++++++++++++++--
1bdc94
 1 file changed, 95 insertions(+), 3 deletions(-)
1bdc94
1bdc94
diff --git a/tests/vhost-user-bridge.c b/tests/vhost-user-bridge.c
1bdc94
index e0605a5..0884294 100644
1bdc94
--- a/tests/vhost-user-bridge.c
1bdc94
+++ b/tests/vhost-user-bridge.c
1bdc94
@@ -29,6 +29,7 @@
1bdc94
 
1bdc94
 #define _FILE_OFFSET_BITS 64
1bdc94
 
1bdc94
+#include "qemu/atomic.h"
1bdc94
 #include "qemu/osdep.h"
1bdc94
 #include "qemu/iov.h"
1bdc94
 #include "standard-headers/linux/virtio_net.h"
1bdc94
@@ -65,6 +66,11 @@ typedef struct VubrDev {
1bdc94
     int sock;
1bdc94
     int ready;
1bdc94
     int quit;
1bdc94
+    struct {
1bdc94
+        int fd;
1bdc94
+        void *addr;
1bdc94
+        pthread_t thread;
1bdc94
+    } notifier;
1bdc94
 } VubrDev;
1bdc94
 
1bdc94
 static void
1bdc94
@@ -445,14 +451,22 @@ static uint64_t
1bdc94
 vubr_get_features(VuDev *dev)
1bdc94
 {
1bdc94
     return 1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE |
1bdc94
-        1ULL << VIRTIO_NET_F_MRG_RXBUF;
1bdc94
+        1ULL << VIRTIO_NET_F_MRG_RXBUF |
1bdc94
+        1ULL << VIRTIO_F_VERSION_1;
1bdc94
 }
1bdc94
 
1bdc94
 static void
1bdc94
 vubr_queue_set_started(VuDev *dev, int qidx, bool started)
1bdc94
 {
1bdc94
+    VubrDev *vubr = container_of(dev, VubrDev, vudev);
1bdc94
     VuVirtq *vq = vu_get_queue(dev, qidx);
1bdc94
 
1bdc94
+    if (started && vubr->notifier.fd >= 0) {
1bdc94
+        vu_set_queue_host_notifier(dev, vq, vubr->notifier.fd,
1bdc94
+                                   getpagesize(),
1bdc94
+                                   qidx * getpagesize());
1bdc94
+    }
1bdc94
+
1bdc94
     if (qidx % 2 == 1) {
1bdc94
         vu_set_queue_handler(dev, vq, started ? vubr_handle_tx : NULL);
1bdc94
     }
1bdc94
@@ -522,6 +536,8 @@ vubr_new(const char *path, bool client)
1bdc94
         vubr_die("socket");
1bdc94
     }
1bdc94
 
1bdc94
+    dev->notifier.fd = -1;
1bdc94
+
1bdc94
     un.sun_family = AF_UNIX;
1bdc94
     strcpy(un.sun_path, path);
1bdc94
     len = sizeof(un.sun_family) + strlen(path);
1bdc94
@@ -559,6 +575,73 @@ vubr_new(const char *path, bool client)
1bdc94
     return dev;
1bdc94
 }
1bdc94
 
1bdc94
+static void *notifier_thread(void *arg)
1bdc94
+{
1bdc94
+    VuDev *dev = (VuDev *)arg;
1bdc94
+    VubrDev *vubr = container_of(dev, VubrDev, vudev);
1bdc94
+    int pagesize = getpagesize();
1bdc94
+    int qidx;
1bdc94
+
1bdc94
+    while (true) {
1bdc94
+        for (qidx = 0; qidx < VHOST_MAX_NR_VIRTQUEUE; qidx++) {
1bdc94
+            uint16_t *n = vubr->notifier.addr + pagesize * qidx;
1bdc94
+
1bdc94
+            if (*n == qidx) {
1bdc94
+                *n = 0xffff;
1bdc94
+                /* We won't miss notifications if we reset
1bdc94
+                 * the memory first. */
1bdc94
+                smp_mb();
1bdc94
+
1bdc94
+                DPRINT("Got a notification for queue%d via host notifier.\n",
1bdc94
+                       qidx);
1bdc94
+
1bdc94
+                if (qidx % 2 == 1) {
1bdc94
+                    vubr_handle_tx(dev, qidx);
1bdc94
+                }
1bdc94
+            }
1bdc94
+            usleep(1000);
1bdc94
+        }
1bdc94
+    }
1bdc94
+
1bdc94
+    return NULL;
1bdc94
+}
1bdc94
+
1bdc94
+static void
1bdc94
+vubr_host_notifier_setup(VubrDev *dev)
1bdc94
+{
1bdc94
+    char template[] = "/tmp/vubr-XXXXXX";
1bdc94
+    pthread_t thread;
1bdc94
+    size_t length;
1bdc94
+    void *addr;
1bdc94
+    int fd;
1bdc94
+
1bdc94
+    length = getpagesize() * VHOST_MAX_NR_VIRTQUEUE;
1bdc94
+
1bdc94
+    fd = mkstemp(template);
1bdc94
+    if (fd < 0) {
1bdc94
+        vubr_die("mkstemp()");
1bdc94
+    }
1bdc94
+
1bdc94
+    if (posix_fallocate(fd, 0, length) != 0) {
1bdc94
+        vubr_die("posix_fallocate()");
1bdc94
+    }
1bdc94
+
1bdc94
+    addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1bdc94
+    if (addr == MAP_FAILED) {
1bdc94
+        vubr_die("mmap()");
1bdc94
+    }
1bdc94
+
1bdc94
+    memset(addr, 0xff, length);
1bdc94
+
1bdc94
+    if (pthread_create(&thread, NULL, notifier_thread, &dev->vudev) != 0) {
1bdc94
+        vubr_die("pthread_create()");
1bdc94
+    }
1bdc94
+
1bdc94
+    dev->notifier.fd = fd;
1bdc94
+    dev->notifier.addr = addr;
1bdc94
+    dev->notifier.thread = thread;
1bdc94
+}
1bdc94
+
1bdc94
 static void
1bdc94
 vubr_set_host(struct sockaddr_in *saddr, const char *host)
1bdc94
 {
1bdc94
@@ -673,8 +756,9 @@ main(int argc, char *argv[])
1bdc94
     VubrDev *dev;
1bdc94
     int opt;
1bdc94
     bool client = false;
1bdc94
+    bool host_notifier = false;
1bdc94
 
1bdc94
-    while ((opt = getopt(argc, argv, "l:r:u:c")) != -1) {
1bdc94
+    while ((opt = getopt(argc, argv, "l:r:u:cH")) != -1) {
1bdc94
 
1bdc94
         switch (opt) {
1bdc94
         case 'l':
1bdc94
@@ -693,6 +777,9 @@ main(int argc, char *argv[])
1bdc94
         case 'c':
1bdc94
             client = true;
1bdc94
             break;
1bdc94
+        case 'H':
1bdc94
+            host_notifier = true;
1bdc94
+            break;
1bdc94
         default:
1bdc94
             goto out;
1bdc94
         }
1bdc94
@@ -708,6 +795,10 @@ main(int argc, char *argv[])
1bdc94
         return 1;
1bdc94
     }
1bdc94
 
1bdc94
+    if (host_notifier) {
1bdc94
+        vubr_host_notifier_setup(dev);
1bdc94
+    }
1bdc94
+
1bdc94
     vubr_backend_udp_setup(dev, lhost, lport, rhost, rport);
1bdc94
     vubr_run(dev);
1bdc94
 
1bdc94
@@ -717,7 +808,7 @@ main(int argc, char *argv[])
1bdc94
 
1bdc94
 out:
1bdc94
     fprintf(stderr, "Usage: %s ", argv[0]);
1bdc94
-    fprintf(stderr, "[-c] [-u ud_socket_path] [-l lhost:lport] [-r rhost:rport]\n");
1bdc94
+    fprintf(stderr, "[-c] [-H] [-u ud_socket_path] [-l lhost:lport] [-r rhost:rport]\n");
1bdc94
     fprintf(stderr, "\t-u path to unix doman socket. default: %s\n",
1bdc94
             DEFAULT_UD_SOCKET);
1bdc94
     fprintf(stderr, "\t-l local host and port. default: %s:%s\n",
1bdc94
@@ -725,6 +816,7 @@ out:
1bdc94
     fprintf(stderr, "\t-r remote host and port. default: %s:%s\n",
1bdc94
             DEFAULT_RHOST, DEFAULT_RPORT);
1bdc94
     fprintf(stderr, "\t-c client mode\n");
1bdc94
+    fprintf(stderr, "\t-H use host notifier\n");
1bdc94
 
1bdc94
     return 1;
1bdc94
 }
1bdc94
-- 
1bdc94
1.8.3.1
1bdc94