diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d856377489..d2f37e408b 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -212,17 +212,21 @@ qemuVirCommandGetDevSet(virCommandPtr cmd, int fd) * @def: the definition of the VM (needed by 802.1Qbh and audit) * @driver: pointer to the driver instance * @net: pointer to the VM's interface description with direct device type + * @tapfd: array of file descriptor return value for the new device + * @tapfdSize: number of file descriptors in @tapfd * @vmop: VM operation type * - * Returns a filedescriptor on success or -1 in case of error. + * Returns 0 on success or -1 in case of error. */ int qemuPhysIfaceConnect(virDomainDefPtr def, virQEMUDriverPtr driver, virDomainNetDefPtr net, + int *tapfd, + size_t tapfdSize, virNetDevVPortProfileOp vmop) { - int rc; + int ret = -1; char *res_ifname = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); unsigned int macvlan_create_flags = VIR_NETDEV_MACVLAN_CREATE_WITH_TAP; @@ -238,18 +242,22 @@ qemuPhysIfaceConnect(virDomainDefPtr def, virDomainNetGetActualVirtPortProfile(net), &res_ifname, vmop, cfg->stateDir, - &rc, 1, + tapfd, tapfdSize, macvlan_create_flags) < 0) - return -1; + goto cleanup; - if (rc >= 0) { - virDomainAuditNetDevice(def, net, res_ifname, true); - VIR_FREE(net->ifname); - net->ifname = res_ifname; + virDomainAuditNetDevice(def, net, res_ifname, true); + VIR_FREE(net->ifname); + net->ifname = res_ifname; + ret = 0; + + cleanup: + if (ret < 0) { + while (tapfdSize--) + VIR_FORCE_CLOSE(tapfd[tapfdSize]); } - virObjectUnref(cfg); - return rc; + return ret; } @@ -8746,7 +8754,8 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd, /* Currently nothing besides TAP devices supports multiqueue. */ if (net->driver.virtio.queues > 0 && !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || - actualType == VIR_DOMAIN_NET_TYPE_BRIDGE)) { + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || + actualType == VIR_DOMAIN_NET_TYPE_DIRECT)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Multiqueue network is not supported for: %s"), virDomainNetTypeToString(actualType)); @@ -8791,11 +8800,17 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd, tapfd, &tapfdSize) < 0) goto cleanup; } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) { - if (VIR_ALLOC(tapfd) < 0 || VIR_ALLOC(tapfdName) < 0) + tapfdSize = net->driver.virtio.queues; + if (!tapfdSize) + tapfdSize = 1; + + if (VIR_ALLOC_N(tapfd, tapfdSize) < 0 || + VIR_ALLOC_N(tapfdName, tapfdSize) < 0) goto cleanup; - tapfdSize = 1; - tapfd[0] = qemuPhysIfaceConnect(def, driver, net, vmop); - if (tapfd[0] < 0) + + memset(tapfd, -1, tapfdSize * sizeof(tapfd[0])); + + if (qemuPhysIfaceConnect(def, driver, net, tapfd, tapfdSize, vmop) < 0) goto cleanup; } diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index bebdd27f98..f0d6900b46 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -232,6 +232,8 @@ int qemuNetworkIfaceConnect(virDomainDefPtr def, int qemuPhysIfaceConnect(virDomainDefPtr def, virQEMUDriverPtr driver, virDomainNetDefPtr net, + int *tapfd, + size_t tapfdSize, virNetDevVPortProfileOp vmop); int qemuOpenVhostNet(virDomainDefPtr def, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 1a61701c49..a88c2f2de7 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -951,15 +951,17 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0) goto cleanup; } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) { - tapfdSize = vhostfdSize = 1; - if (VIR_ALLOC(tapfd) < 0) + tapfdSize = vhostfdSize = net->driver.virtio.queues; + if (!tapfdSize) + tapfdSize = vhostfdSize = 1; + if (VIR_ALLOC_N(tapfd, tapfdSize) < 0) goto cleanup; - *tapfd = -1; - if (VIR_ALLOC(vhostfd) < 0) + memset(tapfd, -1, sizeof(*tapfd) * tapfdSize); + if (VIR_ALLOC_N(vhostfd, vhostfdSize) < 0) goto cleanup; - *vhostfd = -1; - if ((tapfd[0] = qemuPhysIfaceConnect(vm->def, driver, net, - VIR_NETDEV_VPORT_PROFILE_OP_CREATE)) < 0) + memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize); + if (qemuPhysIfaceConnect(vm->def, driver, net, tapfd, tapfdSize, + VIR_NETDEV_VPORT_PROFILE_OP_CREATE) < 0) goto cleanup; iface_connected = true; if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0)