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:
parent
18f863a4da
commit
f59a707d2c
@ -8693,23 +8693,27 @@ qemuInterfaceVhostuserConnect(virCommand *cmd,
|
||||
int
|
||||
qemuBuildInterfaceConnect(virDomainObj *vm,
|
||||
virDomainNetDef *net,
|
||||
bool standalone G_GNUC_UNUSED)
|
||||
bool standalone)
|
||||
{
|
||||
|
||||
qemuDomainObjPrivate *priv = vm->privateData;
|
||||
virDomainNetType actualType = virDomainNetGetActualType(net);
|
||||
qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
|
||||
VIR_AUTOCLOSE vdpafd = -1;
|
||||
bool vhostfd = false;
|
||||
|
||||
switch (actualType) {
|
||||
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
||||
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
||||
vhostfd = true;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
||||
vhostfd = true;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
||||
vhostfd = true;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
@ -8734,6 +8738,11 @@ qemuBuildInterfaceConnect(virDomainObj *vm,
|
||||
break;
|
||||
}
|
||||
|
||||
if (vhostfd && !standalone) {
|
||||
if (qemuInterfaceOpenVhostNet(vm, net) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -8930,26 +8939,6 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver,
|
||||
virNetDevSetMTU(net->ifname, net->mtu) < 0)
|
||||
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;
|
||||
if (slirp && !standalone) {
|
||||
int slirpfd = qemuSlirpGetFD(slirp);
|
||||
|
@ -1283,52 +1283,40 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
|
||||
switch (actualType) {
|
||||
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
||||
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
||||
tapfdSize = vhostfdSize = net->driver.virtio.queues;
|
||||
tapfdSize = net->driver.virtio.queues;
|
||||
if (!tapfdSize)
|
||||
tapfdSize = vhostfdSize = 1;
|
||||
tapfdSize = 1;
|
||||
tapfd = g_new0(int, tapfdSize);
|
||||
memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
|
||||
vhostfd = g_new0(int, vhostfdSize);
|
||||
memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
|
||||
if (qemuInterfaceBridgeConnect(vm->def, driver, net,
|
||||
tapfd, &tapfdSize) < 0)
|
||||
goto cleanup;
|
||||
iface_connected = true;
|
||||
if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
||||
tapfdSize = vhostfdSize = net->driver.virtio.queues;
|
||||
tapfdSize = net->driver.virtio.queues;
|
||||
if (!tapfdSize)
|
||||
tapfdSize = vhostfdSize = 1;
|
||||
tapfdSize = 1;
|
||||
tapfd = g_new0(int, tapfdSize);
|
||||
memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
|
||||
vhostfd = g_new0(int, vhostfdSize);
|
||||
memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
|
||||
if (qemuInterfaceDirectConnect(vm->def, driver, net,
|
||||
tapfd, tapfdSize,
|
||||
VIR_NETDEV_VPORT_PROFILE_OP_CREATE) < 0)
|
||||
goto cleanup;
|
||||
iface_connected = true;
|
||||
if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
||||
tapfdSize = vhostfdSize = net->driver.virtio.queues;
|
||||
tapfdSize = net->driver.virtio.queues;
|
||||
if (!tapfdSize)
|
||||
tapfdSize = vhostfdSize = 1;
|
||||
tapfdSize = 1;
|
||||
tapfd = g_new0(int, tapfdSize);
|
||||
memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
|
||||
vhostfd = g_new0(int, vhostfdSize);
|
||||
memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
|
||||
if (qemuInterfaceEthernetConnect(vm->def, driver, net,
|
||||
tapfd, tapfdSize) < 0)
|
||||
goto cleanup;
|
||||
iface_connected = true;
|
||||
if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
@ -1445,7 +1433,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
|
||||
|
||||
if (!(netprops = qemuBuildHostNetProps(net,
|
||||
tapfdName, tapfdSize,
|
||||
vhostfdName, vhostfdSize,
|
||||
NULL, 0,
|
||||
slirpfdName)))
|
||||
goto cleanup;
|
||||
|
||||
@ -1481,7 +1469,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
|
||||
|
||||
if (qemuMonitorAddNetdev(priv->mon, &netprops,
|
||||
tapfd, tapfdName, tapfdSize,
|
||||
vhostfd, vhostfdName, vhostfdSize,
|
||||
NULL, NULL, 0,
|
||||
slirpfd, slirpfdName) < 0) {
|
||||
qemuDomainObjExitMonitor(vm);
|
||||
virDomainAuditNet(vm, NULL, net, "attach", false);
|
||||
|
@ -688,49 +688,46 @@ qemuInterfacePrepareSlirp(virQEMUDriver *driver,
|
||||
|
||||
/**
|
||||
* qemuInterfaceOpenVhostNet:
|
||||
* @def: domain definition
|
||||
* @vm: domain object
|
||||
* @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(virDomainDef *def,
|
||||
virDomainNetDef *net,
|
||||
int *vhostfd,
|
||||
size_t *vhostfdSize)
|
||||
qemuInterfaceOpenVhostNet(virDomainObj *vm,
|
||||
virDomainNetDef *net)
|
||||
{
|
||||
qemuDomainObjPrivate *priv = vm->privateData;
|
||||
qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
|
||||
size_t i;
|
||||
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)
|
||||
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;
|
||||
if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM ||
|
||||
net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_QEMU)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If qemu doesn't support vhost-net mode (including the -netdev and
|
||||
* -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) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("vhost-net is not supported with this QEMU binary"));
|
||||
return -1;
|
||||
}
|
||||
*vhostfdSize = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -741,35 +738,34 @@ qemuInterfaceOpenVhostNet(virDomainDef *def,
|
||||
_("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);
|
||||
for (i = 0; i < vhostfdSize; i++) {
|
||||
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,
|
||||
* report an error.
|
||||
*/
|
||||
if (vhostfd[i] < 0) {
|
||||
virDomainAuditNetDevice(def, net, vhostnet_path, false);
|
||||
if (fd < 0) {
|
||||
virDomainAuditNetDevice(vm->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;
|
||||
return -1;
|
||||
}
|
||||
VIR_WARN("Unable to open vhost-net. Opened so far %zu, requested %zu",
|
||||
i, *vhostfdSize);
|
||||
*vhostfdSize = i;
|
||||
i, vhostfdSize);
|
||||
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;
|
||||
|
||||
error:
|
||||
while (i--)
|
||||
VIR_FORCE_CLOSE(vhostfd[i]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -51,10 +51,8 @@ int qemuInterfaceBridgeConnect(virDomainDef *def,
|
||||
size_t *tapfdSize)
|
||||
ATTRIBUTE_NONNULL(2);
|
||||
|
||||
int qemuInterfaceOpenVhostNet(virDomainDef *def,
|
||||
virDomainNetDef *net,
|
||||
int *vhostfd,
|
||||
size_t *vhostfdSize) G_GNUC_NO_INLINE;
|
||||
int qemuInterfaceOpenVhostNet(virDomainObj *def,
|
||||
virDomainNetDef *net) G_GNUC_NO_INLINE;
|
||||
|
||||
int qemuInterfacePrepareSlirp(virQEMUDriver *driver,
|
||||
virDomainNetDef *net,
|
||||
|
@ -226,20 +226,32 @@ virNetDevOpenvswitchGetVhostuserIfname(const char *path G_GNUC_UNUSED,
|
||||
}
|
||||
|
||||
int
|
||||
qemuInterfaceOpenVhostNet(virDomainDef *def G_GNUC_UNUSED,
|
||||
virDomainNetDef *net,
|
||||
int *vhostfd,
|
||||
size_t *vhostfdSize)
|
||||
qemuInterfaceOpenVhostNet(virDomainObj *vm,
|
||||
virDomainNetDef *net)
|
||||
{
|
||||
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;
|
||||
|
||||
if (!virDomainNetIsVirtioModel(net)) {
|
||||
*vhostfdSize = 0;
|
||||
if (!vhostfdSize)
|
||||
vhostfdSize = 1;
|
||||
|
||||
if (!virDomainNetIsVirtioModel(net))
|
||||
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++)
|
||||
vhostfd[i] = STDERR_FILENO + 42 + i;
|
||||
netpriv->vhostfds = g_slist_reverse(netpriv->vhostfds);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user