[libvirt] [PATCH 9/9] qemu: implement vhost-vsock-pci support

Ján Tomko jtomko at redhat.com
Mon May 21 15:37:19 UTC 2018


Create a new vsock endpoint by opening /dev/vhost-vsock,
set the requested CID via ioctl, pass the file descriptor
to QEMU and build the command line.

Signed-off-by: Ján Tomko <jtomko at redhat.com>
---
 src/qemu/qemu_command.c                            | 37 ++++++++++++++++++----
 src/qemu/qemu_domain.c                             | 10 +++++-
 src/qemu/qemu_domain.h                             |  6 +++-
 src/qemu/qemu_interface.c                          | 31 ++++++++++++++++++
 src/qemu/qemu_interface.h                          |  4 +++
 src/qemu/qemu_process.c                            |  5 +++
 .../vhost-vsock.x86_64-latest.args                 | 32 +++++++++++++++++++
 tests/qemuxml2argvtest.c                           | 15 +++++++++
 8 files changed, 132 insertions(+), 8 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/vhost-vsock.x86_64-latest.args

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index a9c67bbb3b..2aa47f0980 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3375,6 +3375,9 @@ qemuBuildNicDevStr(virDomainDefPtr def,
     bool usingVirtio = false;
     char macaddr[VIR_MAC_STRING_BUFLEN];
 
+    if (net->type == VIR_DOMAIN_NET_TYPE_VSOCK)
+        nic = "vhost-vsock-pci";
+
     if (STREQ_NULLABLE(net->model, "virtio")) {
         if (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW)
             nic = "virtio-net-ccw";
@@ -3514,13 +3517,23 @@ qemuBuildNicDevStr(virDomainDefPtr def,
         virBufferAsprintf(&buf, ",host_mtu=%u", net->mtu);
     }
 
-    if (vlan == -1)
-        virBufferAsprintf(&buf, ",netdev=host%s", net->info.alias);
-    else
-        virBufferAsprintf(&buf, ",vlan=%d", vlan);
+    if (net->type != VIR_DOMAIN_NET_TYPE_VSOCK) {
+        if (vlan == -1)
+            virBufferAsprintf(&buf, ",netdev=host%s", net->info.alias);
+        else
+            virBufferAsprintf(&buf, ",vlan=%d", vlan);
+    }
     virBufferAsprintf(&buf, ",id=%s", net->info.alias);
-    virBufferAsprintf(&buf, ",mac=%s",
-                      virMacAddrFormat(&net->mac, macaddr));
+    if (net->type != VIR_DOMAIN_NET_TYPE_VSOCK) {
+        virBufferAsprintf(&buf, ",mac=%s",
+                          virMacAddrFormat(&net->mac, macaddr));
+    }
+
+    if (net->type == VIR_DOMAIN_NET_TYPE_VSOCK) {
+        virBufferAsprintf(&buf, ",guest-cid=%u", net->data.vsock.guest_cid);
+        virBufferAsprintf(&buf, ",vhostfd=%u",
+                          QEMU_DOMAIN_NET_PRIVATE(net)->vhostfds[0]);
+    }
 
     if (qemuBuildDeviceAddressStr(&buf, def, &net->info, qemuCaps) < 0)
         goto error;
@@ -8375,6 +8388,18 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
             goto cleanup;
     }
 
+    if (actualType == VIR_DOMAIN_NET_TYPE_VSOCK) {
+        if (!(nic = qemuBuildNicDevStr(def, net, -1, bootindex, 0, qemuCaps)))
+            goto cleanup;
+
+        virCommandPassFD(cmd, QEMU_DOMAIN_NET_PRIVATE(net)->vhostfds[0],
+                         VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+        QEMU_DOMAIN_NET_PRIVATE(net)->vhostfds[0] = -1;
+        virCommandAddArgList(cmd, "-device", nic, NULL);
+        ret = 0;
+        goto cleanup;
+    }
+
     /* Possible combinations:
      *
      *  1. Old way:   -net nic,model=e1000,vlan=1 -net tap,vlan=1
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index eb88de83db..33e3bb340f 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1164,8 +1164,16 @@ qemuDomainNetPrivateNew(void)
 
 
 static void
-qemuDomainNetPrivateDispose(void *obj ATTRIBUTE_UNUSED)
+qemuDomainNetPrivateDispose(void *obj)
 {
+    qemuDomainNetPrivatePtr priv = obj;
+    size_t i;
+
+    if (priv->vhostfds) {
+        for (i = 0; i < priv->nvhostfds; i++)
+            VIR_FORCE_CLOSE(priv->vhostfds[i]);
+    }
+    VIR_FREE(priv->vhostfds);
 }
 
 
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index a04ded16ed..f1034a57bf 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -353,6 +353,9 @@ struct _qemuDomainObjPrivate {
 # define QEMU_DOMAIN_DISK_PRIVATE(disk) \
     ((qemuDomainDiskPrivatePtr) (disk)->privateData)
 
+# define QEMU_DOMAIN_NET_PRIVATE(net) \
+    ((qemuDomainNetPrivatePtr) (net)->privateData)
+
 typedef struct _qemuDomainDiskPrivate qemuDomainDiskPrivate;
 typedef qemuDomainDiskPrivate *qemuDomainDiskPrivatePtr;
 struct _qemuDomainDiskPrivate {
@@ -446,7 +449,8 @@ typedef qemuDomainNetPrivate *qemuDomainNetPrivatePtr;
 struct _qemuDomainNetPrivate {
     virObject parent;
 
-    virTristateBool maybe;
+    int *vhostfds;
+    size_t nvhostfds;
 };
 
 
diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
index 60bb6b22ef..fb38ee0d67 100644
--- a/src/qemu/qemu_interface.c
+++ b/src/qemu/qemu_interface.c
@@ -698,3 +698,34 @@ qemuInterfaceOpenVhostNet(virDomainDefPtr def,
 
     return -1;
 }
+
+
+int
+qemuInterfaceOpenVhostVsock(virDomainDefPtr def,
+                            virDomainNetDefPtr net)
+{
+    qemuDomainNetPrivatePtr netPriv = QEMU_DOMAIN_NET_PRIVATE(net);
+    const char *vsock_path = "/dev/vhost-vsock";
+    int fd;
+
+    if (VIR_ALLOC_N(netPriv->vhostfds, 1) < 0)
+        return -1;
+
+    if ((fd = open(vsock_path, O_RDWR)) < 0) {
+        virDomainAuditNetDevice(def, net, vsock_path, false);
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       "%s", _("unable to open vhost-vsock device"));
+        return -1;
+    }
+    if (virNetDevVsockSetGuestCid(fd, net->data.vsock.guest_cid) < 0)
+        goto error;
+
+    virDomainAuditNetDevice(def, net, vsock_path, true);
+    netPriv->vhostfds[0] = fd;
+    netPriv->nvhostfds = 1;
+    return 0;
+
+ error:
+    VIR_FORCE_CLOSE(fd);
+    return -1;
+}
diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h
index 45fdbc4b8e..b327a35f99 100644
--- a/src/qemu/qemu_interface.h
+++ b/src/qemu/qemu_interface.h
@@ -58,4 +58,8 @@ int qemuInterfaceOpenVhostNet(virDomainDefPtr def,
                               virDomainNetDefPtr net,
                               int *vhostfd,
                               size_t *vhostfdSize);
+
+int
+qemuInterfaceOpenVhostVsock(virDomainDefPtr def,
+                            virDomainNetDefPtr net);
 #endif /* __QEMU_INTERFACE_H__ */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index d73f3764f5..0cac864b60 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5348,6 +5348,11 @@ qemuProcessNetworkPrepareDevices(virDomainDefPtr def)
             if (virDomainHostdevInsert(def, hostdev) < 0)
                 goto cleanup;
         }
+
+        if (net->type == VIR_DOMAIN_NET_TYPE_VSOCK) {
+            if (qemuInterfaceOpenVhostVsock(def, net) < 0)
+                goto cleanup;
+        }
     }
     ret = 0;
  cleanup:
diff --git a/tests/qemuxml2argvdata/vhost-vsock.x86_64-latest.args b/tests/qemuxml2argvdata/vhost-vsock.x86_64-latest.args
new file mode 100644
index 0000000000..266144f6f0
--- /dev/null
+++ b/tests/qemuxml2argvdata/vhost-vsock.x86_64-latest.args
@@ -0,0 +1,32 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name guest=test,debug-threads=on \
+-S \
+-object secret,id=masterKey0,format=raw,\
+file=/tmp/lib/domain--1-test/master-key.aes \
+-machine pc-0.13,accel=tcg,usb=off,dump-guest-core=off \
+-m 1024 \
+-realtime mlock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid bba65c0e-c049-934f-b6aa-4e2c0582acdf \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-test/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot menu=on,strict=on \
+-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
+-device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 \
+-device vhost-vsock-pci,id=net0,guest-cid=4,vhostfd=6789,bus=pci.0,addr=0x3 \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
+resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 78454acb1a..761a2628c8 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -532,6 +532,19 @@ testCompareXMLToArgv(const void *data)
         }
     }
 
+    for (i = 0; i < vm->def->nnets; i++) {
+        virDomainNetDefPtr net = vm->def->nets[i];
+
+        if (net->type == VIR_DOMAIN_NET_TYPE_VSOCK) {
+            qemuDomainNetPrivatePtr netPriv = QEMU_DOMAIN_NET_PRIVATE(net);
+            if (VIR_ALLOC_N(netPriv->vhostfds, 1) < 0)
+                goto cleanup;
+
+            netPriv->vhostfds[0] = 6789;
+            netPriv->nvhostfds = 1;
+        }
+    }
+
     if (!(cmd = qemuProcessCreatePretendCmd(&driver, vm, migrateURI,
                                             (flags & FLAG_FIPS), false,
                                             VIR_QEMU_PROCESS_START_COLD))) {
@@ -2848,6 +2861,8 @@ mymain(void)
             QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW,
             QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW);
 
+    DO_TEST_CAPS_LATEST("vhost-vsock");
+
     if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
         virFileDeleteTree(fakerootdir);
 
-- 
2.16.1




More information about the libvir-list mailing list