qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH RFC 11/14] vhost-user: add slave-fd support


From: marcandre . lureau
Subject: [Qemu-devel] [PATCH RFC 11/14] vhost-user: add slave-fd support
Date: Wed, 9 Sep 2015 01:10:03 +0200

From: Marc-André Lureau <address@hidden>

Learn to give a socket to the slave to let him make requests to the
master.

Signed-off-by: Marc-André Lureau <address@hidden>
---
 docs/specs/vhost-user.txt | 23 +++++++++++++++
 hw/virtio/vhost-user.c    | 71 ++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
index 1bc6adb..5e00bd3 100644
--- a/docs/specs/vhost-user.txt
+++ b/docs/specs/vhost-user.txt
@@ -136,10 +136,23 @@ As older slaves don't support negotiating protocol 
features,
 a feature bit was dedicated for this purpose:
 #define VHOST_USER_F_PROTOCOL_FEATURES 30
 
+Slave communication
+-------------------
+
+Since the vhost-user protocol do not let slave make requests back to
+the master, an optional communication channel is provided if the slave
+declares VHOST_USER_PROTOCOL_F_SLAVE_REQ feature.
+
+The fd is provided via VHOST_USER_SET_SLAVE_FD ancillary data.
+
+A slave may then send VHOST_USER_SLAVE_* messages to the master by
+using this fd.
+
 Protocol features
 -----------------
 
 #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 0
+#define VHOST_USER_PROTOCOL_F_SLAVE_REQ 1
 
 Message types
 -------------
@@ -308,6 +321,16 @@ Message types
       invalid FD flag. This flag is set when there is no file descriptor
       in the ancillary data.
 
+ * VHOST_USER_SET_SLAVE_FD
+      Id: 17
+      Equivalent ioctl: N/A
+      Master payload: N/A
+
+      Set the file descriptor for the salve to make VHOST_USER_SLAVE_*
+      request to the master. It is passed in the ancillary data.
+      This message is only sent if VHOST_USER_PROTOCOL_F_SLAVE_REQ
+      feature is available.
+
 Migration
 ---------
 
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 2875b69..49f566c 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -27,8 +27,9 @@
 
 #define VHOST_USER_F_PROTOCOL_FEATURES 30
 
-#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x1ULL
+#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x3ULL
 #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 0
+#define VHOST_USER_PROTOCOL_F_SLAVE_REQ 1
 
 typedef enum VhostUserRequest {
     VHOST_USER_NONE = 0,
@@ -48,9 +49,15 @@ typedef enum VhostUserRequest {
     VHOST_USER_SET_VRING_ERR = 14,
     VHOST_USER_GET_PROTOCOL_FEATURES = 15,
     VHOST_USER_SET_PROTOCOL_FEATURES = 16,
+    VHOST_USER_SET_SLAVE_FD = 17,
     VHOST_USER_MAX
 } VhostUserRequest;
 
+typedef enum VhostUserSlaveRequest {
+    VHOST_USER_SLAVE_NONE = 0,
+    VHOST_USER_SLAVE_MAX
+}  VhostUserSlaveRequest;
+
 typedef struct VhostUserMemoryRegion {
     uint64_t guest_phys_addr;
     uint64_t memory_size;
@@ -93,6 +100,7 @@ static VhostUserMsg m __attribute__ ((unused));
 
 struct vhost_user {
     CharDriverState *chr;
+    CharDriverState *slave_chr;
 };
 
 static bool ioeventfd_enabled(void)
@@ -277,6 +285,7 @@ static int vhost_user_call(struct vhost_dev *dev,
 
         break;
 
+    case VHOST_USER_SET_SLAVE_FD:
     case VHOST_USER_SET_LOG_FD:
         fds[fd_num++] = *((int *) arg);
         break;
@@ -361,6 +370,43 @@ end:
     return ret;
 }
 
+static int slave_can_receive(void *opaque)
+{
+    return VHOST_USER_HDR_SIZE;
+}
+
+static void slave_receive(void *opaque, const uint8_t *buf, int size)
+{
+    struct vhost_dev *dev = opaque;
+    VhostUserMsg *msg = (VhostUserMsg *)buf;
+
+    if (size != VHOST_USER_HDR_SIZE) {
+        error_report("Failed to read from slave.");
+        return;
+    }
+
+    switch (msg->request) {
+    default:
+        error_report("Received unexpected msg type.");
+    }
+}
+
+static void slave_event(void *opaque, int event)
+{
+    struct vhost_dev *dev = opaque;
+    struct vhost_user *u = dev->opaque;
+    CharDriverState *slave_chr = u->slave_chr;
+
+    switch (event) {
+    case CHR_EVENT_CLOSED:
+        if (slave_chr) {
+            u->slave_chr = NULL;
+            qemu_chr_free(slave_chr);
+        }
+        break;
+    }
+}
+
 static int vhost_user_init(struct vhost_dev *dev, void *opaque)
 {
     VhostUserMsg msg = { 0 };
@@ -417,16 +463,39 @@ static int vhost_user_init(struct vhost_dev *dev, void 
*opaque)
         }
     }
 
+    if (__virtio_has_feature(dev->protocol_features,
+                             VHOST_USER_PROTOCOL_F_SLAVE_REQ)) {
+        int sv[2];
+
+        if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
+            error_report("socketpair() failed");
+            return -1;
+        }
+
+        vhost_user_call(dev, VHOST_USER_SET_SLAVE_FD, &sv[1]);
+
+        u->slave_chr = qemu_chr_open_eventfd(sv[0]);
+        qemu_chr_add_handlers(u->slave_chr, slave_can_receive, slave_receive,
+                              slave_event, dev);
+    }
+
+
     return 0;
 }
 
 static int vhost_user_cleanup(struct vhost_dev *dev)
 {
     struct vhost_user *u;
+    CharDriverState *slave_chr;
 
     assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
 
     u = dev->opaque;
+    if (u->slave_chr) {
+        slave_chr = u->slave_chr;
+        u->slave_chr = NULL;
+        qemu_chr_free(slave_chr);
+    }
     g_free(u);
     dev->opaque = 0;
 
-- 
2.4.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]