qemu: Enable multiqueue for macvtaps

https://bugzilla.redhat.com/show_bug.cgi?id=1240439

Ta-da! Now that we know how to open a macvtap device multiple
times, we can finally enable the multiqueue feature. Everything
else is already prepared (e.g. command line generation) from the
previous iteration where the feature was implemented for
TUN/TAP devices.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Michal Privoznik 2015-12-04 11:47:22 +01:00
parent 08da97bfb9
commit 81a110edc7
3 changed files with 41 additions and 22 deletions

View File

@ -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;
}

View File

@ -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,

View File

@ -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)