diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8245e11ddafe3b3e0dc9c31b622895fafba14a0c..b44b431698778f4aac1f52176e32ad0f368df3d8 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -258,100 +258,6 @@ qemuBuildObjectCommandlineFromJSON(const char *type, } -/** - * qemuOpenVhostNet: - * @def: domain definition - * @net: network definition - * @qemuCaps: qemu binary capabilities - * @vhostfd: array of opened vhost-net device - * @vhostfdSize: number of file descriptors in @vhostfd array - * - * Open vhost-net, multiple times - if requested. - * In case, no vhost-net is needed, @vhostfdSize is set to 0 - * and 0 is returned. - * - * Returns: 0 on success - * -1 on failure - */ -int -qemuOpenVhostNet(virDomainDefPtr def, - virDomainNetDefPtr net, - virQEMUCapsPtr qemuCaps, - int *vhostfd, - size_t *vhostfdSize) -{ - size_t i; - const char *vhostnet_path = net->backend.vhost; - - if (!vhostnet_path) - vhostnet_path = "/dev/vhost-net"; - - /* If running a plain QEMU guest, or - * if the config says explicitly to not use vhost, return now*/ - if (def->virtType != VIR_DOMAIN_VIRT_KVM || - net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_QEMU) { - *vhostfdSize = 0; - return 0; - } - - /* If qemu doesn't support vhost-net mode (including the -netdev command - * option), don't try to open the device. - */ - if (!(virQEMUCapsGet(qemuCaps, QEMU_CAPS_VHOST_NET) && - qemuDomainSupportsNetdev(def, qemuCaps, net))) { - if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - "%s", _("vhost-net is not supported with " - "this QEMU binary")); - return -1; - } - *vhostfdSize = 0; - return 0; - } - - /* If the nic model isn't virtio, don't try to open. */ - if (!(net->model && STREQ(net->model, "virtio"))) { - if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - "%s", _("vhost-net is only supported for " - "virtio network interfaces")); - return -1; - } - *vhostfdSize = 0; - return 0; - } - - for (i = 0; i < *vhostfdSize; i++) { - vhostfd[i] = open(vhostnet_path, O_RDWR); - - /* If the config says explicitly to use vhost and we couldn't open it, - * report an error. - */ - if (vhostfd[i] < 0) { - virDomainAuditNetDevice(def, net, vhostnet_path, false); - if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - "%s", _("vhost-net was requested for an interface, " - "but is unavailable")); - goto error; - } - VIR_WARN("Unable to open vhost-net. Opened so far %zu, requested %zu", - i, *vhostfdSize); - *vhostfdSize = i; - break; - } - } - virDomainAuditNetDevice(def, net, vhostnet_path, *vhostfdSize); - return 0; - - error: - while (i--) - VIR_FORCE_CLOSE(vhostfd[i]); - - return -1; -} - - int qemuNetworkPrepareDevices(virDomainDefPtr def) { @@ -6696,7 +6602,8 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd, memset(vhostfd, -1, vhostfdSize * sizeof(vhostfd[0])); - if (qemuOpenVhostNet(def, net, qemuCaps, vhostfd, &vhostfdSize) < 0) + if (qemuInterfaceOpenVhostNet(def, net, qemuCaps, + vhostfd, &vhostfdSize) < 0) goto cleanup; } diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 0407121db5d6851e12bc1a2698f9cbe0ca6f0188..1efed5ddfeb1455b2af40dafdec5bce5c114e239 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -225,12 +225,6 @@ char *qemuBuildRedirdevDevStr(virDomainDefPtr def, virDomainRedirdevDefPtr dev, virQEMUCapsPtr qemuCaps); -int qemuOpenVhostNet(virDomainDefPtr def, - virDomainNetDefPtr net, - virQEMUCapsPtr qemuCaps, - int *vhostfd, - size_t *vhostfdSize); - int qemuNetworkPrepareDevices(virDomainDefPtr def); int qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index fa256cff3a3b94737edff72c03560c55e1530074..da4ca32cf8c656bd20b7e9aaac3d8f3f7f4b9b5e 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -927,7 +927,8 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, tapfd, &tapfdSize) < 0) goto cleanup; iface_connected = true; - if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0) + if (qemuInterfaceOpenVhostNet(vm->def, net, priv->qemuCaps, + vhostfd, &vhostfdSize) < 0) goto cleanup; } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) { tapfdSize = vhostfdSize = net->driver.virtio.queues; @@ -944,14 +945,16 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, VIR_NETDEV_VPORT_PROFILE_OP_CREATE) < 0) goto cleanup; iface_connected = true; - if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0) + if (qemuInterfaceOpenVhostNet(vm->def, net, priv->qemuCaps, + vhostfd, &vhostfdSize) < 0) goto cleanup; } else if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) { vhostfdSize = 1; if (VIR_ALLOC(vhostfd) < 0) goto cleanup; *vhostfd = -1; - if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0) + if (qemuInterfaceOpenVhostNet(vm->def, net, priv->qemuCaps, + vhostfd, &vhostfdSize) < 0) goto cleanup; } diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index a36da9206ae3eb5e27f759ed4f315c80115953de..08af13358113b5e778c0e9b6c9ce9bbf8b72c90c 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -38,6 +38,9 @@ #include "virnetdevbridge.h" #include "virnetdevvportprofile.h" +#include +#include + #define VIR_FROM_THIS VIR_FROM_QEMU VIR_LOG_INIT("qemu.qemu_interface"); @@ -500,3 +503,97 @@ qemuInterfaceBridgeConnect(virDomainDefPtr def, return ret; } + + +/** + * qemuInterfaceOpenVhostNet: + * @def: domain definition + * @net: network definition + * @qemuCaps: qemu binary capabilities + * @vhostfd: array of opened vhost-net device + * @vhostfdSize: number of file descriptors in @vhostfd array + * + * Open vhost-net, multiple times - if requested. + * In case, no vhost-net is needed, @vhostfdSize is set to 0 + * and 0 is returned. + * + * Returns: 0 on success + * -1 on failure + */ +int +qemuInterfaceOpenVhostNet(virDomainDefPtr def, + virDomainNetDefPtr net, + virQEMUCapsPtr qemuCaps, + int *vhostfd, + size_t *vhostfdSize) +{ + size_t i; + const char *vhostnet_path = net->backend.vhost; + + if (!vhostnet_path) + vhostnet_path = "/dev/vhost-net"; + + /* If running a plain QEMU guest, or + * if the config says explicitly to not use vhost, return now*/ + if (def->virtType != VIR_DOMAIN_VIRT_KVM || + net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_QEMU) { + *vhostfdSize = 0; + return 0; + } + + /* If qemu doesn't support vhost-net mode (including the -netdev command + * option), don't try to open the device. + */ + if (!(virQEMUCapsGet(qemuCaps, QEMU_CAPS_VHOST_NET) && + qemuDomainSupportsNetdev(def, qemuCaps, net))) { + if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("vhost-net is not supported with " + "this QEMU binary")); + return -1; + } + *vhostfdSize = 0; + return 0; + } + + /* If the nic model isn't virtio, don't try to open. */ + if (!(net->model && STREQ(net->model, "virtio"))) { + if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("vhost-net is only supported for " + "virtio network interfaces")); + return -1; + } + *vhostfdSize = 0; + return 0; + } + + for (i = 0; i < *vhostfdSize; i++) { + vhostfd[i] = open(vhostnet_path, O_RDWR); + + /* If the config says explicitly to use vhost and we couldn't open it, + * report an error. + */ + if (vhostfd[i] < 0) { + virDomainAuditNetDevice(def, net, vhostnet_path, false); + if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("vhost-net was requested for an interface, " + "but is unavailable")); + goto error; + } + VIR_WARN("Unable to open vhost-net. Opened so far %zu, requested %zu", + i, *vhostfdSize); + *vhostfdSize = i; + break; + } + } + virDomainAuditNetDevice(def, net, vhostnet_path, *vhostfdSize); + return 0; + + error: + while (i--) + VIR_FORCE_CLOSE(vhostfd[i]); + + return -1; +} diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h index 3dae305edc59e9e943484df9e2dfcac0d6d4c306..bf4dedf84ac9dd600a6073d587d111c582ed63ec 100644 --- a/src/qemu/qemu_interface.h +++ b/src/qemu/qemu_interface.h @@ -27,6 +27,7 @@ # include "domain_conf.h" # include "qemu_conf.h" +# include "qemu_domain.h" int qemuInterfaceStartDevice(virDomainNetDefPtr net); int qemuInterfaceStartDevices(virDomainDefPtr def); @@ -46,4 +47,10 @@ int qemuInterfaceBridgeConnect(virDomainDefPtr def, int *tapfd, size_t *tapfdSize) ATTRIBUTE_NONNULL(2); + +int qemuInterfaceOpenVhostNet(virDomainDefPtr def, + virDomainNetDefPtr net, + virQEMUCapsPtr qemuCaps, + int *vhostfd, + size_t *vhostfdSize); #endif /* __QEMU_INTERFACE_H__ */