1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

qemu: Move opening of vhost file descriptors for net devices into qemuBuildInterfaceConnect

Use the new infrastructure which stores the fds inside 'qemuFDPass'
objects in the private data.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Jonathon Jongsma <jjongsma@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa 2022-05-09 17:42:08 +02:00
parent 18f863a4da
commit f59a707d2c
5 changed files with 67 additions and 84 deletions

View File

@ -8693,23 +8693,27 @@ qemuInterfaceVhostuserConnect(virCommand *cmd,
int int
qemuBuildInterfaceConnect(virDomainObj *vm, qemuBuildInterfaceConnect(virDomainObj *vm,
virDomainNetDef *net, virDomainNetDef *net,
bool standalone G_GNUC_UNUSED) bool standalone)
{ {
qemuDomainObjPrivate *priv = vm->privateData; qemuDomainObjPrivate *priv = vm->privateData;
virDomainNetType actualType = virDomainNetGetActualType(net); virDomainNetType actualType = virDomainNetGetActualType(net);
qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net); qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
VIR_AUTOCLOSE vdpafd = -1; VIR_AUTOCLOSE vdpafd = -1;
bool vhostfd = false;
switch (actualType) { switch (actualType) {
case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_NETWORK:
case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_BRIDGE:
vhostfd = true;
break; break;
case VIR_DOMAIN_NET_TYPE_DIRECT: case VIR_DOMAIN_NET_TYPE_DIRECT:
vhostfd = true;
break; break;
case VIR_DOMAIN_NET_TYPE_ETHERNET: case VIR_DOMAIN_NET_TYPE_ETHERNET:
vhostfd = true;
break; break;
case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
@ -8734,6 +8738,11 @@ qemuBuildInterfaceConnect(virDomainObj *vm,
break; break;
} }
if (vhostfd && !standalone) {
if (qemuInterfaceOpenVhostNet(vm, net) < 0)
return -1;
}
return 0; return 0;
} }
@ -8930,26 +8939,6 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver,
virNetDevSetMTU(net->ifname, net->mtu) < 0) virNetDevSetMTU(net->ifname, net->mtu) < 0)
goto cleanup; goto cleanup;
if ((actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
actualType == VIR_DOMAIN_NET_TYPE_ETHERNET ||
actualType == VIR_DOMAIN_NET_TYPE_DIRECT) &&
!standalone) {
/* Attempt to use vhost-net mode for these types of
network device */
vhostfdSize = net->driver.virtio.queues;
if (!vhostfdSize)
vhostfdSize = 1;
vhostfd = g_new0(int, vhostfdSize);
vhostfdName = g_new0(char *, vhostfdSize);
memset(vhostfd, -1, vhostfdSize * sizeof(vhostfd[0]));
if (qemuInterfaceOpenVhostNet(def, net, vhostfd, &vhostfdSize) < 0)
goto cleanup;
}
slirp = QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp; slirp = QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp;
if (slirp && !standalone) { if (slirp && !standalone) {
int slirpfd = qemuSlirpGetFD(slirp); int slirpfd = qemuSlirpGetFD(slirp);

View File

@ -1283,52 +1283,40 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
switch (actualType) { switch (actualType) {
case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_BRIDGE:
case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_NETWORK:
tapfdSize = vhostfdSize = net->driver.virtio.queues; tapfdSize = net->driver.virtio.queues;
if (!tapfdSize) if (!tapfdSize)
tapfdSize = vhostfdSize = 1; tapfdSize = 1;
tapfd = g_new0(int, tapfdSize); tapfd = g_new0(int, tapfdSize);
memset(tapfd, -1, sizeof(*tapfd) * tapfdSize); memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
vhostfd = g_new0(int, vhostfdSize);
memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
if (qemuInterfaceBridgeConnect(vm->def, driver, net, if (qemuInterfaceBridgeConnect(vm->def, driver, net,
tapfd, &tapfdSize) < 0) tapfd, &tapfdSize) < 0)
goto cleanup; goto cleanup;
iface_connected = true; iface_connected = true;
if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
goto cleanup;
break; break;
case VIR_DOMAIN_NET_TYPE_DIRECT: case VIR_DOMAIN_NET_TYPE_DIRECT:
tapfdSize = vhostfdSize = net->driver.virtio.queues; tapfdSize = net->driver.virtio.queues;
if (!tapfdSize) if (!tapfdSize)
tapfdSize = vhostfdSize = 1; tapfdSize = 1;
tapfd = g_new0(int, tapfdSize); tapfd = g_new0(int, tapfdSize);
memset(tapfd, -1, sizeof(*tapfd) * tapfdSize); memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
vhostfd = g_new0(int, vhostfdSize);
memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
if (qemuInterfaceDirectConnect(vm->def, driver, net, if (qemuInterfaceDirectConnect(vm->def, driver, net,
tapfd, tapfdSize, tapfd, tapfdSize,
VIR_NETDEV_VPORT_PROFILE_OP_CREATE) < 0) VIR_NETDEV_VPORT_PROFILE_OP_CREATE) < 0)
goto cleanup; goto cleanup;
iface_connected = true; iface_connected = true;
if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
goto cleanup;
break; break;
case VIR_DOMAIN_NET_TYPE_ETHERNET: case VIR_DOMAIN_NET_TYPE_ETHERNET:
tapfdSize = vhostfdSize = net->driver.virtio.queues; tapfdSize = net->driver.virtio.queues;
if (!tapfdSize) if (!tapfdSize)
tapfdSize = vhostfdSize = 1; tapfdSize = 1;
tapfd = g_new0(int, tapfdSize); tapfd = g_new0(int, tapfdSize);
memset(tapfd, -1, sizeof(*tapfd) * tapfdSize); memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
vhostfd = g_new0(int, vhostfdSize);
memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
if (qemuInterfaceEthernetConnect(vm->def, driver, net, if (qemuInterfaceEthernetConnect(vm->def, driver, net,
tapfd, tapfdSize) < 0) tapfd, tapfdSize) < 0)
goto cleanup; goto cleanup;
iface_connected = true; iface_connected = true;
if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
goto cleanup;
break; break;
case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
@ -1445,7 +1433,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
if (!(netprops = qemuBuildHostNetProps(net, if (!(netprops = qemuBuildHostNetProps(net,
tapfdName, tapfdSize, tapfdName, tapfdSize,
vhostfdName, vhostfdSize, NULL, 0,
slirpfdName))) slirpfdName)))
goto cleanup; goto cleanup;
@ -1481,7 +1469,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
if (qemuMonitorAddNetdev(priv->mon, &netprops, if (qemuMonitorAddNetdev(priv->mon, &netprops,
tapfd, tapfdName, tapfdSize, tapfd, tapfdName, tapfdSize,
vhostfd, vhostfdName, vhostfdSize, NULL, NULL, 0,
slirpfd, slirpfdName) < 0) { slirpfd, slirpfdName) < 0) {
qemuDomainObjExitMonitor(vm); qemuDomainObjExitMonitor(vm);
virDomainAuditNet(vm, NULL, net, "attach", false); virDomainAuditNet(vm, NULL, net, "attach", false);

View File

@ -688,49 +688,46 @@ qemuInterfacePrepareSlirp(virQEMUDriver *driver,
/** /**
* qemuInterfaceOpenVhostNet: * qemuInterfaceOpenVhostNet:
* @def: domain definition * @vm: domain object
* @net: network 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. * 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 * Returns: 0 on success
* -1 on failure * -1 on failure
*/ */
int int
qemuInterfaceOpenVhostNet(virDomainDef *def, qemuInterfaceOpenVhostNet(virDomainObj *vm,
virDomainNetDef *net, virDomainNetDef *net)
int *vhostfd,
size_t *vhostfdSize)
{ {
qemuDomainObjPrivate *priv = vm->privateData;
qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
size_t i; size_t i;
const char *vhostnet_path = net->backend.vhost; const char *vhostnet_path = net->backend.vhost;
size_t vhostfdSize = net->driver.virtio.queues;
g_autofree char *prefix = g_strdup_printf("vhostfd-%s", net->info.alias);
if (!vhostfdSize)
vhostfdSize = 1;
if (!vhostnet_path) if (!vhostnet_path)
vhostnet_path = "/dev/vhost-net"; vhostnet_path = "/dev/vhost-net";
/* If running a plain QEMU guest, or /* If running a plain QEMU guest, or
* if the config says explicitly to not use vhost, return now */ * if the config says explicitly to not use vhost, return now */
if (def->virtType != VIR_DOMAIN_VIRT_KVM || if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM ||
net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_QEMU) { net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_QEMU)
*vhostfdSize = 0;
return 0; return 0;
}
/* If qemu doesn't support vhost-net mode (including the -netdev and /* If qemu doesn't support vhost-net mode (including the -netdev and
* -device command options), don't try to open the device. * -device command options), don't try to open the device.
*/ */
if (!qemuDomainSupportsNicdev(def, net)) { if (!qemuDomainSupportsNicdev(vm->def, net)) {
if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) { if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("vhost-net is not supported with this QEMU binary")); _("vhost-net is not supported with this QEMU binary"));
return -1; return -1;
} }
*vhostfdSize = 0;
return 0; return 0;
} }
@ -741,35 +738,34 @@ qemuInterfaceOpenVhostNet(virDomainDef *def,
_("vhost-net is only supported for virtio network interfaces")); _("vhost-net is only supported for virtio network interfaces"));
return -1; return -1;
} }
*vhostfdSize = 0;
return 0; return 0;
} }
for (i = 0; i < *vhostfdSize; i++) { for (i = 0; i < vhostfdSize; i++) {
vhostfd[i] = open(vhostnet_path, O_RDWR); VIR_AUTOCLOSE fd = open(vhostnet_path, O_RDWR);
g_autoptr(qemuFDPass) pass = qemuFDPassNewDirect(prefix, priv);
g_autofree char *suffix = g_strdup_printf("%zu", i);
/* If the config says explicitly to use vhost and we couldn't open it, /* If the config says explicitly to use vhost and we couldn't open it,
* report an error. * report an error.
*/ */
if (vhostfd[i] < 0) { if (fd < 0) {
virDomainAuditNetDevice(def, net, vhostnet_path, false); virDomainAuditNetDevice(vm->def, net, vhostnet_path, false);
if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) { if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("vhost-net was requested for an interface, but is unavailable")); _("vhost-net was requested for an interface, but is unavailable"));
goto error; return -1;
} }
VIR_WARN("Unable to open vhost-net. Opened so far %zu, requested %zu", VIR_WARN("Unable to open vhost-net. Opened so far %zu, requested %zu",
i, *vhostfdSize); i, vhostfdSize);
*vhostfdSize = i;
break; break;
} }
qemuFDPassAddFD(pass, &fd, suffix);
netpriv->vhostfds = g_slist_prepend(netpriv->vhostfds, g_steal_pointer(&pass));
} }
virDomainAuditNetDevice(def, net, vhostnet_path, *vhostfdSize);
netpriv->vhostfds = g_slist_reverse(netpriv->vhostfds);
virDomainAuditNetDevice(vm->def, net, vhostnet_path, vhostfdSize);
return 0; return 0;
error:
while (i--)
VIR_FORCE_CLOSE(vhostfd[i]);
return -1;
} }

View File

@ -51,10 +51,8 @@ int qemuInterfaceBridgeConnect(virDomainDef *def,
size_t *tapfdSize) size_t *tapfdSize)
ATTRIBUTE_NONNULL(2); ATTRIBUTE_NONNULL(2);
int qemuInterfaceOpenVhostNet(virDomainDef *def, int qemuInterfaceOpenVhostNet(virDomainObj *def,
virDomainNetDef *net, virDomainNetDef *net) G_GNUC_NO_INLINE;
int *vhostfd,
size_t *vhostfdSize) G_GNUC_NO_INLINE;
int qemuInterfacePrepareSlirp(virQEMUDriver *driver, int qemuInterfacePrepareSlirp(virQEMUDriver *driver,
virDomainNetDef *net, virDomainNetDef *net,

View File

@ -226,20 +226,32 @@ virNetDevOpenvswitchGetVhostuserIfname(const char *path G_GNUC_UNUSED,
} }
int int
qemuInterfaceOpenVhostNet(virDomainDef *def G_GNUC_UNUSED, qemuInterfaceOpenVhostNet(virDomainObj *vm,
virDomainNetDef *net, virDomainNetDef *net)
int *vhostfd,
size_t *vhostfdSize)
{ {
qemuDomainObjPrivate *priv = vm->privateData;
qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
g_autofree char *prefix = g_strdup_printf("vhostfd-%s", net->info.alias);
size_t vhostfdSize = net->driver.virtio.queues;
size_t i; size_t i;
if (!virDomainNetIsVirtioModel(net)) { if (!vhostfdSize)
*vhostfdSize = 0; vhostfdSize = 1;
if (!virDomainNetIsVirtioModel(net))
return 0; return 0;
for (i = 0; i < vhostfdSize; i++) {
g_autoptr(qemuFDPass) pass = qemuFDPassNewDirect(prefix, priv);
g_autofree char *suffix = g_strdup_printf("%zu", i);
int fd = STDERR_FILENO + 42 + i;
qemuFDPassAddFD(pass, &fd, suffix);
netpriv->vhostfds = g_slist_prepend(netpriv->vhostfds, g_steal_pointer(&pass));
} }
for (i = 0; i < *vhostfdSize; i++) netpriv->vhostfds = g_slist_reverse(netpriv->vhostfds);
vhostfd[i] = STDERR_FILENO + 42 + i;
return 0; return 0;
} }