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(a)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