mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 20:45:18 +00:00
qemu: Adapt qemuBuildInterfaceCommandLine to to multiqueue net
In order to learn libvirt multiqueue several things must be done: 1) The '/dev/net/tun' device needs to be opened multiple times with IFF_MULTI_QUEUE flag passed to ioctl(fd, TUNSETIFF, &ifr); 2) Similarly, '/dev/vhost-net' must be opened as many times as in 1) in order to keep 1:1 ratio recommended by qemu and kernel folks. 3) The command line construction code needs to switch from 'fd=X' to 'fds=X:Y:...:Z' and from 'vhostfd=X' to 'vhostfds=X:Y:...:Z'. 4) The monitor handling code needs to learn to pass multiple FDs.
This commit is contained in:
parent
565c07f171
commit
1f24f68225
@ -2495,7 +2495,7 @@ networkStartNetworkVirtual(struct network_driver *driver,
|
||||
/* Keep tun fd open and interface up to allow for IPv6 DAD to happen */
|
||||
if (virNetDevTapCreateInBridgePort(network->def->bridge,
|
||||
&macTapIfName, &network->def->mac,
|
||||
NULL, &tapfd, NULL, NULL,
|
||||
NULL, &tapfd, 1, NULL, NULL,
|
||||
VIR_NETDEV_TAP_CREATE_USE_MAC_FOR_BRIDGE |
|
||||
VIR_NETDEV_TAP_CREATE_IFUP |
|
||||
VIR_NETDEV_TAP_CREATE_PERSIST) < 0) {
|
||||
|
@ -281,11 +281,12 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
|
||||
virConnectPtr conn,
|
||||
virQEMUDriverPtr driver,
|
||||
virDomainNetDefPtr net,
|
||||
virQEMUCapsPtr qemuCaps)
|
||||
virQEMUCapsPtr qemuCaps,
|
||||
int *tapfd,
|
||||
int *tapfdSize)
|
||||
{
|
||||
char *brname = NULL;
|
||||
int err;
|
||||
int tapfd = -1;
|
||||
int ret = -1;
|
||||
unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
|
||||
bool template_ifname = false;
|
||||
int actualType = virDomainNetGetActualType(net);
|
||||
@ -297,7 +298,7 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
|
||||
virNetworkPtr network = virNetworkLookupByName(conn,
|
||||
net->data.network.name);
|
||||
if (!network)
|
||||
return -1;
|
||||
return ret;
|
||||
|
||||
active = virNetworkIsActive(network);
|
||||
if (active != 1) {
|
||||
@ -322,18 +323,18 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
|
||||
virFreeError(errobj);
|
||||
|
||||
if (fail)
|
||||
return -1;
|
||||
return ret;
|
||||
|
||||
} else if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
|
||||
if (!(brname = strdup(virDomainNetGetActualBridgeName(net)))) {
|
||||
virReportOOMError();
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Network type %d is not supported"),
|
||||
virDomainNetGetActualType(net));
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!net->ifname ||
|
||||
@ -353,69 +354,98 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
|
||||
tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
|
||||
}
|
||||
|
||||
if (cfg->privileged)
|
||||
err = virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac,
|
||||
def->uuid, &tapfd,
|
||||
virDomainNetGetActualVirtPortProfile(net),
|
||||
virDomainNetGetActualVlan(net),
|
||||
tap_create_flags);
|
||||
else
|
||||
err = qemuCreateInBridgePortWithHelper(cfg, brname,
|
||||
&net->ifname,
|
||||
&tapfd, tap_create_flags);
|
||||
|
||||
virDomainAuditNetDevice(def, net, "/dev/net/tun", tapfd >= 0);
|
||||
if (err < 0) {
|
||||
if (template_ifname)
|
||||
VIR_FREE(net->ifname);
|
||||
tapfd = -1;
|
||||
}
|
||||
|
||||
if (cfg->macFilter) {
|
||||
if ((err = networkAllowMacOnPort(driver, net->ifname, &net->mac))) {
|
||||
virReportSystemError(err,
|
||||
_("failed to add ebtables rule to allow MAC address on '%s'"),
|
||||
net->ifname);
|
||||
if (cfg->privileged) {
|
||||
if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac,
|
||||
def->uuid, tapfd, *tapfdSize,
|
||||
virDomainNetGetActualVirtPortProfile(net),
|
||||
virDomainNetGetActualVlan(net),
|
||||
tap_create_flags) < 0) {
|
||||
virDomainAuditNetDevice(def, net, "/dev/net/tun", false);
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
if (qemuCreateInBridgePortWithHelper(cfg, brname,
|
||||
&net->ifname,
|
||||
tapfd, tap_create_flags) < 0) {
|
||||
virDomainAuditNetDevice(def, net, "/dev/net/tun", false);
|
||||
goto cleanup;
|
||||
}
|
||||
/* qemuCreateInBridgePortWithHelper can only create a single FD */
|
||||
if (*tapfdSize > 1) {
|
||||
VIR_WARN("Ignoring multiqueue network request");
|
||||
*tapfdSize = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tapfd >= 0 &&
|
||||
virNetDevBandwidthSet(net->ifname,
|
||||
virDomainAuditNetDevice(def, net, "/dev/net/tun", true);
|
||||
|
||||
if (cfg->macFilter &&
|
||||
(ret = networkAllowMacOnPort(driver, net->ifname, &net->mac)) < 0) {
|
||||
virReportSystemError(ret,
|
||||
_("failed to add ebtables rule "
|
||||
"to allow MAC address on '%s'"),
|
||||
net->ifname);
|
||||
}
|
||||
|
||||
if (virNetDevBandwidthSet(net->ifname,
|
||||
virDomainNetGetActualBandwidth(net),
|
||||
false) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot set bandwidth limits on %s"),
|
||||
net->ifname);
|
||||
VIR_FORCE_CLOSE(tapfd);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (tapfd >= 0) {
|
||||
if ((net->filter) && (net->ifname)) {
|
||||
if (virDomainConfNWFilterInstantiate(conn, def->uuid, net) < 0)
|
||||
VIR_FORCE_CLOSE(tapfd);
|
||||
}
|
||||
if (net->filter && net->ifname &&
|
||||
virDomainConfNWFilterInstantiate(conn, def->uuid, net) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
if (ret < 0) {
|
||||
int i;
|
||||
for (i = 0; i < *tapfdSize; i++)
|
||||
VIR_FORCE_CLOSE(tapfd[i]);
|
||||
if (template_ifname)
|
||||
VIR_FREE(net->ifname);
|
||||
}
|
||||
VIR_FREE(brname);
|
||||
virObjectUnref(cfg);
|
||||
|
||||
return tapfd;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
int *vhostfd,
|
||||
int *vhostfdSize)
|
||||
{
|
||||
*vhostfd = -1; /* assume we won't use vhost */
|
||||
int i;
|
||||
|
||||
/* If the config says explicitly to not use vhost, return now */
|
||||
if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_QEMU) {
|
||||
return 0;
|
||||
*vhostfdSize = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If qemu doesn't support vhost-net mode (including the -netdev command
|
||||
@ -430,6 +460,7 @@ qemuOpenVhostNet(virDomainDefPtr def,
|
||||
"this QEMU binary"));
|
||||
return -1;
|
||||
}
|
||||
*vhostfdSize = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -441,23 +472,34 @@ qemuOpenVhostNet(virDomainDefPtr def,
|
||||
"virtio network interfaces"));
|
||||
return -1;
|
||||
}
|
||||
*vhostfdSize = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*vhostfd = open("/dev/vhost-net", O_RDWR);
|
||||
virDomainAuditNetDevice(def, net, "/dev/vhost-net", *vhostfd >= 0);
|
||||
for (i = 0; i < *vhostfdSize; i++) {
|
||||
vhostfd[i] = open("/dev/vhost-net", O_RDWR);
|
||||
|
||||
/* If the config says explicitly to use vhost and we couldn't open it,
|
||||
* report an error.
|
||||
*/
|
||||
if ((*vhostfd < 0) &&
|
||||
(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"));
|
||||
return -1;
|
||||
/* If the config says explicitly to use vhost and we couldn't open it,
|
||||
* report an error.
|
||||
*/
|
||||
if (vhostfd[i] < 0) {
|
||||
virDomainAuditNetDevice(def, net, "/dev/vhost-net", 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
virDomainAuditNetDevice(def, net, "/dev/vhost-net", *vhostfdSize);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
while (i--)
|
||||
VIR_FORCE_CLOSE(vhostfd[i]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
@ -4109,13 +4151,16 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
|
||||
virQEMUDriverPtr driver,
|
||||
char type_sep,
|
||||
int vlan,
|
||||
const char *tapfd,
|
||||
const char *vhostfd)
|
||||
char **tapfd,
|
||||
int tapfdSize,
|
||||
char **vhostfd,
|
||||
int vhostfdSize)
|
||||
{
|
||||
bool is_tap = false;
|
||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||
enum virDomainNetType netType = virDomainNetGetActualType(net);
|
||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||
int i;
|
||||
|
||||
if (net->script && netType != VIR_DOMAIN_NET_TYPE_ETHERNET) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
@ -4134,7 +4179,19 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
|
||||
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
||||
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
||||
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
||||
virBufferAsprintf(&buf, "tap%cfd=%s", type_sep, tapfd);
|
||||
virBufferAsprintf(&buf, "tap%c", type_sep);
|
||||
/* for one tapfd 'fd=' shall be used,
|
||||
* for more than one 'fds=' is the right choice */
|
||||
if (tapfdSize == 1) {
|
||||
virBufferAsprintf(&buf, "fd=%s", tapfd[0]);
|
||||
} else {
|
||||
virBufferAddLit(&buf, "fds=");
|
||||
for (i = 0; i < tapfdSize; i++) {
|
||||
if (i)
|
||||
virBufferAddChar(&buf, ':');
|
||||
virBufferAdd(&buf, tapfd[i], -1);
|
||||
}
|
||||
}
|
||||
type_sep = ',';
|
||||
is_tap = true;
|
||||
break;
|
||||
@ -4194,8 +4251,19 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
|
||||
}
|
||||
|
||||
if (is_tap) {
|
||||
if (vhostfd && *vhostfd)
|
||||
virBufferAsprintf(&buf, ",vhost=on,vhostfd=%s", vhostfd);
|
||||
if (vhostfdSize) {
|
||||
virBufferAddLit(&buf, ",vhost=on,");
|
||||
if (vhostfdSize == 1) {
|
||||
virBufferAsprintf(&buf, "vhostfd=%s", vhostfd[0]);
|
||||
} else {
|
||||
virBufferAddLit(&buf, "vhostfds=");
|
||||
for (i = 0; i < vhostfdSize; i++) {
|
||||
if (i)
|
||||
virBufferAddChar(&buf, ':');
|
||||
virBufferAdd(&buf, vhostfd[i], -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (net->tune.sndbuf_specified)
|
||||
virBufferAsprintf(&buf, ",sndbuf=%lu", net->tune.sndbuf);
|
||||
}
|
||||
@ -6431,12 +6499,15 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
|
||||
enum virNetDevVPortProfileOp vmop)
|
||||
{
|
||||
int ret = -1;
|
||||
int tapfd = -1;
|
||||
int vhostfd = -1;
|
||||
char *nic = NULL, *host = NULL;
|
||||
char *tapfdName = NULL;
|
||||
char *vhostfdName = NULL;
|
||||
int *tapfd = NULL;
|
||||
int tapfdSize = 0;
|
||||
int *vhostfd = NULL;
|
||||
int vhostfdSize = 0;
|
||||
char **tapfdName = NULL;
|
||||
char **vhostfdName = NULL;
|
||||
int actualType = virDomainNetGetActualType(net);
|
||||
int i;
|
||||
|
||||
if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
|
||||
/* NET_TYPE_HOSTDEV devices are really hostdev devices, so
|
||||
@ -6450,12 +6521,24 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
|
||||
|
||||
if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
|
||||
actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
|
||||
tapfd = qemuNetworkIfaceConnect(def, conn, driver, net, qemuCaps);
|
||||
if (tapfd < 0)
|
||||
if (VIR_ALLOC(tapfd) < 0 || VIR_ALLOC(tapfdName) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
tapfdSize = 1;
|
||||
if (qemuNetworkIfaceConnect(def, conn, driver, net,
|
||||
qemuCaps, tapfd, &tapfdSize) < 0)
|
||||
goto cleanup;
|
||||
} else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||
tapfd = qemuPhysIfaceConnect(def, driver, net, qemuCaps, vmop);
|
||||
if (tapfd < 0)
|
||||
if (VIR_ALLOC(tapfd) < 0 || VIR_ALLOC(tapfdName) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
tapfdSize = 1;
|
||||
tapfd[0] = qemuPhysIfaceConnect(def, driver, net,
|
||||
qemuCaps, vmop);
|
||||
if (tapfd[0] < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -6465,23 +6548,31 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
|
||||
actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||
/* Attempt to use vhost-net mode for these types of
|
||||
network device */
|
||||
if (qemuOpenVhostNet(def, net, qemuCaps, &vhostfd) < 0)
|
||||
if (VIR_ALLOC(vhostfd) < 0 || VIR_ALLOC(vhostfdName)) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
vhostfdSize = 1;
|
||||
|
||||
if (qemuOpenVhostNet(def, net, qemuCaps, vhostfd, &vhostfdSize) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (tapfd >= 0) {
|
||||
virCommandTransferFD(cmd, tapfd);
|
||||
if (virAsprintf(&tapfdName, "%d", tapfd) < 0) {
|
||||
for (i = 0; i < tapfdSize; i++) {
|
||||
virCommandTransferFD(cmd, tapfd[i]);
|
||||
if (virAsprintf(&tapfdName[i], "%d", tapfd[i]) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (vhostfd >= 0) {
|
||||
virCommandTransferFD(cmd, vhostfd);
|
||||
if (virAsprintf(&vhostfdName, "%d", vhostfd) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
for (i = 0; i < vhostfdSize; i++) {
|
||||
if (vhostfd[i] >= 0) {
|
||||
virCommandTransferFD(cmd, vhostfd[i]);
|
||||
if (virAsprintf(&vhostfdName[i], "%d", vhostfd[i]) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6496,8 +6587,9 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
|
||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV) &&
|
||||
virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
|
||||
if (!(host = qemuBuildHostNetStr(net, driver,
|
||||
',', vlan, tapfdName,
|
||||
vhostfdName)))
|
||||
',', vlan,
|
||||
tapfdName, tapfdSize,
|
||||
vhostfdName, vhostfdSize)))
|
||||
goto cleanup;
|
||||
virCommandAddArgList(cmd, "-netdev", host, NULL);
|
||||
}
|
||||
@ -6513,8 +6605,9 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
|
||||
if (!(virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV) &&
|
||||
virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE))) {
|
||||
if (!(host = qemuBuildHostNetStr(net, driver,
|
||||
',', vlan, tapfdName,
|
||||
vhostfdName)))
|
||||
',', vlan,
|
||||
tapfdName, tapfdSize,
|
||||
vhostfdName, vhostfdSize)))
|
||||
goto cleanup;
|
||||
virCommandAddArgList(cmd, "-net", host, NULL);
|
||||
}
|
||||
@ -6523,6 +6616,18 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
|
||||
cleanup:
|
||||
if (ret < 0)
|
||||
virDomainConfNWFilterTeardown(net);
|
||||
for (i = 0; i < tapfdSize; i++) {
|
||||
if (ret < 0)
|
||||
VIR_FORCE_CLOSE(tapfd[i]);
|
||||
VIR_FREE(tapfdName[i]);
|
||||
}
|
||||
for (i = 0; i < vhostfdSize; i++) {
|
||||
if (ret < 0)
|
||||
VIR_FORCE_CLOSE(vhostfd[i]);
|
||||
VIR_FREE(vhostfdName[i]);
|
||||
}
|
||||
VIR_FREE(tapfd);
|
||||
VIR_FREE(vhostfd);
|
||||
VIR_FREE(nic);
|
||||
VIR_FREE(host);
|
||||
VIR_FREE(tapfdName);
|
||||
|
@ -87,8 +87,10 @@ char * qemuBuildHostNetStr(virDomainNetDefPtr net,
|
||||
virQEMUDriverPtr driver,
|
||||
char type_sep,
|
||||
int vlan,
|
||||
const char *tapfd,
|
||||
const char *vhostfd);
|
||||
char **tapfd,
|
||||
int tapfdSize,
|
||||
char **vhostfd,
|
||||
int vhostfdSize);
|
||||
|
||||
/* Legacy, pre device support */
|
||||
char * qemuBuildNicStr(virDomainNetDefPtr net,
|
||||
@ -169,7 +171,9 @@ int qemuNetworkIfaceConnect(virDomainDefPtr def,
|
||||
virConnectPtr conn,
|
||||
virQEMUDriverPtr driver,
|
||||
virDomainNetDefPtr net,
|
||||
virQEMUCapsPtr qemuCaps)
|
||||
virQEMUCapsPtr qemuCaps,
|
||||
int *tapfd,
|
||||
int *tapfdSize)
|
||||
ATTRIBUTE_NONNULL(2);
|
||||
|
||||
int qemuPhysIfaceConnect(virDomainDefPtr def,
|
||||
@ -181,7 +185,8 @@ int qemuPhysIfaceConnect(virDomainDefPtr def,
|
||||
int qemuOpenVhostNet(virDomainDefPtr def,
|
||||
virDomainNetDefPtr net,
|
||||
virQEMUCapsPtr qemuCaps,
|
||||
int *vhostfd);
|
||||
int *vhostfd,
|
||||
int *vhostfdSize);
|
||||
|
||||
int qemuNetworkPrepareDevices(virDomainDefPtr def);
|
||||
|
||||
|
@ -690,10 +690,12 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
|
||||
virDomainNetDefPtr net)
|
||||
{
|
||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
char *tapfd_name = NULL;
|
||||
int tapfd = -1;
|
||||
char *vhostfd_name = NULL;
|
||||
int vhostfd = -1;
|
||||
char **tapfdName = NULL;
|
||||
int *tapfd = NULL;
|
||||
int tapfdSize = 0;
|
||||
char **vhostfdName = NULL;
|
||||
int *vhostfd = NULL;
|
||||
int vhostfdSize = 0;
|
||||
char *nicstr = NULL;
|
||||
char *netstr = NULL;
|
||||
virNetDevVPortProfilePtr vport = NULL;
|
||||
@ -704,6 +706,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
|
||||
bool iface_connected = false;
|
||||
int actualType;
|
||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||
int i;
|
||||
|
||||
/* preallocate new slot for device */
|
||||
if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0) {
|
||||
@ -739,22 +742,37 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
|
||||
|
||||
if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
|
||||
actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
||||
if ((tapfd = qemuNetworkIfaceConnect(vm->def, conn, driver, net,
|
||||
priv->qemuCaps)) < 0)
|
||||
if (VIR_ALLOC(tapfd) < 0 || VIR_ALLOC(vhostfd) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
tapfdSize = vhostfdSize = 1;
|
||||
if (qemuNetworkIfaceConnect(vm->def, conn, driver, net,
|
||||
priv->qemuCaps, tapfd, &tapfdSize) < 0)
|
||||
goto cleanup;
|
||||
iface_connected = true;
|
||||
if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0)
|
||||
if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0)
|
||||
goto cleanup;
|
||||
} else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||
if ((tapfd = qemuPhysIfaceConnect(vm->def, driver, net,
|
||||
priv->qemuCaps,
|
||||
VIR_NETDEV_VPORT_PROFILE_OP_CREATE)) < 0)
|
||||
if (VIR_ALLOC(tapfd) < 0 || VIR_ALLOC(vhostfd) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
tapfdSize = vhostfdSize = 1;
|
||||
if ((tapfd[0] = qemuPhysIfaceConnect(vm->def, driver, net,
|
||||
priv->qemuCaps,
|
||||
VIR_NETDEV_VPORT_PROFILE_OP_CREATE)) < 0)
|
||||
goto cleanup;
|
||||
iface_connected = true;
|
||||
if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0)
|
||||
if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0)
|
||||
goto cleanup;
|
||||
} else if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
|
||||
if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0)
|
||||
if (VIR_ALLOC(vhostfd) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
vhostfdSize = 1;
|
||||
if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -792,41 +810,51 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
|
||||
}
|
||||
}
|
||||
|
||||
if (tapfd != -1) {
|
||||
if (virAsprintf(&tapfd_name, "fd-%s", net->info.alias) < 0)
|
||||
if (VIR_ALLOC_N(tapfdName, tapfdSize) < 0 ||
|
||||
VIR_ALLOC_N(vhostfdName, vhostfdSize) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < tapfdSize; i++) {
|
||||
if (virAsprintf(&tapfdName[i], "fd-%s%d", net->info.alias, i) < 0)
|
||||
goto no_memory;
|
||||
}
|
||||
|
||||
if (vhostfd != -1) {
|
||||
if (virAsprintf(&vhostfd_name, "vhostfd-%s", net->info.alias) < 0)
|
||||
for (i = 0; i < vhostfdSize; i++) {
|
||||
if (virAsprintf(&vhostfdName[i], "vhostfd-%s%d", net->info.alias, i) < 0)
|
||||
goto no_memory;
|
||||
}
|
||||
|
||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV) &&
|
||||
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
||||
if (!(netstr = qemuBuildHostNetStr(net, driver,
|
||||
',', -1, tapfd_name,
|
||||
vhostfd_name)))
|
||||
',', -1,
|
||||
tapfdName, tapfdSize,
|
||||
vhostfdName, vhostfdSize)))
|
||||
goto cleanup;
|
||||
} else {
|
||||
if (!(netstr = qemuBuildHostNetStr(net, driver,
|
||||
' ', vlan, tapfd_name,
|
||||
vhostfd_name)))
|
||||
' ', vlan,
|
||||
tapfdName, tapfdSize,
|
||||
vhostfdName, vhostfdSize)))
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV) &&
|
||||
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
||||
if (qemuMonitorAddNetdev(priv->mon, netstr, tapfd, tapfd_name,
|
||||
vhostfd, vhostfd_name) < 0) {
|
||||
if (qemuMonitorAddNetdev(priv->mon, netstr,
|
||||
tapfd, tapfdName, tapfdSize,
|
||||
vhostfd, vhostfdName, vhostfdSize) < 0) {
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
virDomainAuditNet(vm, NULL, net, "attach", false);
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
if (qemuMonitorAddHostNetwork(priv->mon, netstr, tapfd, tapfd_name,
|
||||
vhostfd, vhostfd_name) < 0) {
|
||||
if (qemuMonitorAddHostNetwork(priv->mon, netstr,
|
||||
tapfd, tapfdName, tapfdSize,
|
||||
vhostfd, vhostfdName, vhostfdSize) < 0) {
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
virDomainAuditNet(vm, NULL, net, "attach", false);
|
||||
goto cleanup;
|
||||
@ -834,8 +862,10 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
|
||||
}
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
|
||||
VIR_FORCE_CLOSE(tapfd);
|
||||
VIR_FORCE_CLOSE(vhostfd);
|
||||
for (i = 0; i < tapfdSize; i++)
|
||||
VIR_FORCE_CLOSE(tapfd[i]);
|
||||
for (i = 0; i < vhostfdSize; i++)
|
||||
VIR_FORCE_CLOSE(vhostfd[i]);
|
||||
|
||||
if (!virDomainObjIsActive(vm)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
@ -931,10 +961,18 @@ cleanup:
|
||||
|
||||
VIR_FREE(nicstr);
|
||||
VIR_FREE(netstr);
|
||||
VIR_FREE(tapfd_name);
|
||||
VIR_FORCE_CLOSE(tapfd);
|
||||
VIR_FREE(vhostfd_name);
|
||||
VIR_FORCE_CLOSE(vhostfd);
|
||||
for (i = 0; i < tapfdSize; i++) {
|
||||
VIR_FORCE_CLOSE(tapfd[i]);
|
||||
VIR_FREE(tapfdName[i]);
|
||||
}
|
||||
VIR_FREE(tapfd);
|
||||
VIR_FREE(tapfdName);
|
||||
for (i = 0; i < vhostfdSize; i++) {
|
||||
VIR_FORCE_CLOSE(vhostfd[i]);
|
||||
VIR_FREE(vhostfdName[i]);
|
||||
}
|
||||
VIR_FREE(vhostfd);
|
||||
VIR_FREE(vhostfdName);
|
||||
virObjectUnref(cfg);
|
||||
|
||||
return ret;
|
||||
|
@ -2477,14 +2477,16 @@ cleanup:
|
||||
|
||||
int qemuMonitorAddHostNetwork(qemuMonitorPtr mon,
|
||||
const char *netstr,
|
||||
int tapfd, const char *tapfd_name,
|
||||
int vhostfd, const char *vhostfd_name)
|
||||
int *tapfd, char **tapfdName, int tapfdSize,
|
||||
int *vhostfd, char **vhostfdName, int vhostfdSize)
|
||||
{
|
||||
int ret = -1;
|
||||
VIR_DEBUG("mon=%p netstr=%s tapfd=%d tapfd_name=%s "
|
||||
"vhostfd=%d vhostfd_name=%s",
|
||||
mon, netstr, tapfd, NULLSTR(tapfd_name),
|
||||
vhostfd, NULLSTR(vhostfd_name));
|
||||
int i = 0, j = 0;
|
||||
|
||||
VIR_DEBUG("mon=%p netstr=%s tapfd=%p tapfdName=%p tapfdSize=%d "
|
||||
"vhostfd=%p vhostfdName=%p vhostfdSize=%d",
|
||||
mon, netstr, tapfd, tapfdName, tapfdSize,
|
||||
vhostfd, vhostfdName, vhostfdSize);
|
||||
|
||||
if (!mon) {
|
||||
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||
@ -2492,12 +2494,13 @@ int qemuMonitorAddHostNetwork(qemuMonitorPtr mon,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tapfd >= 0 && qemuMonitorSendFileHandle(mon, tapfd_name, tapfd) < 0)
|
||||
return -1;
|
||||
if (vhostfd >= 0 &&
|
||||
qemuMonitorSendFileHandle(mon, vhostfd_name, vhostfd) < 0) {
|
||||
vhostfd = -1;
|
||||
goto cleanup;
|
||||
for (i = 0; i < tapfdSize; i++) {
|
||||
if (qemuMonitorSendFileHandle(mon, tapfdName[i], tapfd[i]) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
for (j = 0; j < vhostfdSize; j++) {
|
||||
if (qemuMonitorSendFileHandle(mon, vhostfdName[j], vhostfd[j]) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (mon->json)
|
||||
@ -2508,10 +2511,14 @@ int qemuMonitorAddHostNetwork(qemuMonitorPtr mon,
|
||||
|
||||
cleanup:
|
||||
if (ret < 0) {
|
||||
if (tapfd >= 0 && qemuMonitorCloseFileHandle(mon, tapfd_name) < 0)
|
||||
VIR_WARN("failed to close device handle '%s'", tapfd_name);
|
||||
if (vhostfd >= 0 && qemuMonitorCloseFileHandle(mon, vhostfd_name) < 0)
|
||||
VIR_WARN("failed to close device handle '%s'", vhostfd_name);
|
||||
while (i--) {
|
||||
if (qemuMonitorCloseFileHandle(mon, tapfdName[i]) < 0)
|
||||
VIR_WARN("failed to close device handle '%s'", tapfdName[i]);
|
||||
}
|
||||
while (j--) {
|
||||
if (qemuMonitorCloseFileHandle(mon, vhostfdName[j]) < 0)
|
||||
VIR_WARN("failed to close device handle '%s'", vhostfdName[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -2543,14 +2550,16 @@ int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon,
|
||||
|
||||
int qemuMonitorAddNetdev(qemuMonitorPtr mon,
|
||||
const char *netdevstr,
|
||||
int tapfd, const char *tapfd_name,
|
||||
int vhostfd, const char *vhostfd_name)
|
||||
int *tapfd, char **tapfdName, int tapfdSize,
|
||||
int *vhostfd, char **vhostfdName, int vhostfdSize)
|
||||
{
|
||||
int ret = -1;
|
||||
VIR_DEBUG("mon=%p netdevstr=%s tapfd=%d tapfd_name=%s "
|
||||
"vhostfd=%d vhostfd_name=%s",
|
||||
mon, netdevstr, tapfd, NULLSTR(tapfd_name),
|
||||
vhostfd, NULLSTR(vhostfd_name));
|
||||
int i = 0, j = 0;
|
||||
|
||||
VIR_DEBUG("mon=%p netdevstr=%s tapfd=%p tapfdName=%p tapfdSize=%d"
|
||||
"vhostfd=%p vhostfdName=%p vhostfdSize=%d",
|
||||
mon, netdevstr, tapfd, tapfdName, tapfdSize,
|
||||
vhostfd, vhostfdName, tapfdSize);
|
||||
|
||||
if (!mon) {
|
||||
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||
@ -2558,12 +2567,13 @@ int qemuMonitorAddNetdev(qemuMonitorPtr mon,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tapfd >= 0 && qemuMonitorSendFileHandle(mon, tapfd_name, tapfd) < 0)
|
||||
return -1;
|
||||
if (vhostfd >= 0 &&
|
||||
qemuMonitorSendFileHandle(mon, vhostfd_name, vhostfd) < 0) {
|
||||
vhostfd = -1;
|
||||
goto cleanup;
|
||||
for (i = 0; i < tapfdSize; i++) {
|
||||
if (qemuMonitorSendFileHandle(mon, tapfdName[i], tapfd[i]) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
for (j = 0; j < vhostfdSize; j++) {
|
||||
if (qemuMonitorSendFileHandle(mon, vhostfdName[j], vhostfd[j]) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (mon->json)
|
||||
@ -2573,10 +2583,14 @@ int qemuMonitorAddNetdev(qemuMonitorPtr mon,
|
||||
|
||||
cleanup:
|
||||
if (ret < 0) {
|
||||
if (tapfd >= 0 && qemuMonitorCloseFileHandle(mon, tapfd_name) < 0)
|
||||
VIR_WARN("failed to close device handle '%s'", tapfd_name);
|
||||
if (vhostfd >= 0 && qemuMonitorCloseFileHandle(mon, vhostfd_name) < 0)
|
||||
VIR_WARN("failed to close device handle '%s'", vhostfd_name);
|
||||
while (i--) {
|
||||
if (qemuMonitorCloseFileHandle(mon, tapfdName[i]) < 0)
|
||||
VIR_WARN("failed to close device handle '%s'", tapfdName[i]);
|
||||
}
|
||||
while (j--) {
|
||||
if (qemuMonitorCloseFileHandle(mon, vhostfdName[j]) < 0)
|
||||
VIR_WARN("failed to close device handle '%s'", vhostfdName[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -501,8 +501,8 @@ int qemuMonitorRemoveFd(qemuMonitorPtr mon, int fdset, int fd);
|
||||
*/
|
||||
int qemuMonitorAddHostNetwork(qemuMonitorPtr mon,
|
||||
const char *netstr,
|
||||
int tapfd, const char *tapfd_name,
|
||||
int vhostfd, const char *vhostfd_name);
|
||||
int *tapfd, char **tapfdName, int tapfdSize,
|
||||
int *vhostfd, char **vhostfdName, int vhostfdSize);
|
||||
|
||||
int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon,
|
||||
int vlan,
|
||||
@ -510,8 +510,8 @@ int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon,
|
||||
|
||||
int qemuMonitorAddNetdev(qemuMonitorPtr mon,
|
||||
const char *netdevstr,
|
||||
int tapfd, const char *tapfd_name,
|
||||
int vhostfd, const char *vhostfd_name);
|
||||
int *tapfd, char **tapfdName, int tapfdSize,
|
||||
int *vhostfd, char **vhostfdName, int vhostfdSize);
|
||||
|
||||
int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
|
||||
const char *alias);
|
||||
|
@ -109,6 +109,7 @@ umlConnectTapDevice(virConnectPtr conn,
|
||||
const char *bridge)
|
||||
{
|
||||
bool template_ifname = false;
|
||||
int tapfd;
|
||||
|
||||
if (!net->ifname ||
|
||||
STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) ||
|
||||
@ -121,7 +122,7 @@ umlConnectTapDevice(virConnectPtr conn,
|
||||
}
|
||||
|
||||
if (virNetDevTapCreateInBridgePort(bridge, &net->ifname, &net->mac,
|
||||
vm->uuid, NULL,
|
||||
vm->uuid, &tapfd, 1,
|
||||
virDomainNetGetActualVirtPortProfile(net),
|
||||
virDomainNetGetActualVlan(net),
|
||||
VIR_NETDEV_TAP_CREATE_IFUP |
|
||||
@ -139,9 +140,11 @@ umlConnectTapDevice(virConnectPtr conn,
|
||||
}
|
||||
}
|
||||
|
||||
VIR_FORCE_CLOSE(tapfd);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
VIR_FORCE_CLOSE(tapfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,8 @@ virNetDevProbeVnetHdr(int tapfd)
|
||||
/**
|
||||
* virNetDevTapCreate:
|
||||
* @ifname: the interface name
|
||||
* @tapfd: file descriptor return value for the new tap device
|
||||
* @tapfds: array of file descriptors return value for the new tap device
|
||||
* @tapfdSize: number of file descriptors in @tapfd
|
||||
* @flags: OR of virNetDevTapCreateFlags. Only one flag is recognized:
|
||||
*
|
||||
* VIR_NETDEV_TAP_CREATE_VNET_HDR
|
||||
@ -148,76 +149,85 @@ virNetDevProbeVnetHdr(int tapfd)
|
||||
* VIR_NETDEV_TAP_CREATE_PERSIST
|
||||
* - The device will persist after the file descriptor is closed
|
||||
*
|
||||
* Creates a tap interface.
|
||||
* If the @tapfd parameter is supplied, the open tap device file descriptor
|
||||
* will be returned, otherwise the TAP device will be closed. The caller must
|
||||
* use virNetDevTapDelete to remove a persistent TAP device when it is no
|
||||
* longer needed.
|
||||
* Creates a tap interface. The caller must use virNetDevTapDelete to
|
||||
* remove a persistent TAP device when it is no longer needed. In case
|
||||
* @tapfdSize is greater than one, multiqueue extension is requested
|
||||
* from kernel.
|
||||
*
|
||||
* Returns 0 in case of success or -1 on failure.
|
||||
*/
|
||||
int virNetDevTapCreate(char **ifname,
|
||||
int *tapfd,
|
||||
int tapfdSize,
|
||||
unsigned int flags)
|
||||
{
|
||||
int fd;
|
||||
int i;
|
||||
struct ifreq ifr;
|
||||
int ret = -1;
|
||||
|
||||
if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to open /dev/net/tun, is tun module loaded?"));
|
||||
return -1;
|
||||
}
|
||||
int fd;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
for (i = 0; i < tapfdSize; i++) {
|
||||
if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to open /dev/net/tun, is tun module loaded?"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
||||
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
||||
/* If tapfdSize is greater than one, request multiqueue */
|
||||
if (tapfdSize > 1)
|
||||
ifr.ifr_flags |= IFF_MULTI_QUEUE;
|
||||
|
||||
# ifdef IFF_VNET_HDR
|
||||
if ((flags & VIR_NETDEV_TAP_CREATE_VNET_HDR) &&
|
||||
virNetDevProbeVnetHdr(fd))
|
||||
ifr.ifr_flags |= IFF_VNET_HDR;
|
||||
if ((flags & VIR_NETDEV_TAP_CREATE_VNET_HDR) &&
|
||||
virNetDevProbeVnetHdr(fd))
|
||||
ifr.ifr_flags |= IFF_VNET_HDR;
|
||||
# endif
|
||||
|
||||
if (virStrcpyStatic(ifr.ifr_name, *ifname) == NULL) {
|
||||
virReportSystemError(ERANGE,
|
||||
_("Network interface name '%s' is too long"),
|
||||
*ifname);
|
||||
goto cleanup;
|
||||
if (virStrcpyStatic(ifr.ifr_name, *ifname) == NULL) {
|
||||
virReportSystemError(ERANGE,
|
||||
_("Network interface name '%s' is too long"),
|
||||
*ifname);
|
||||
goto cleanup;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to create tap device %s"),
|
||||
NULLSTR(*ifname));
|
||||
goto cleanup;
|
||||
}
|
||||
if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to create tap device %s"),
|
||||
NULLSTR(*ifname));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((flags & VIR_NETDEV_TAP_CREATE_PERSIST) &&
|
||||
(errno = ioctl(fd, TUNSETPERSIST, 1))) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to set tap device %s to persistent"),
|
||||
NULLSTR(*ifname));
|
||||
goto cleanup;
|
||||
}
|
||||
if (i == 0) {
|
||||
/* In case we are looping more than once, set other
|
||||
* TAPs to have the same name */
|
||||
VIR_FREE(*ifname);
|
||||
if (ifr.ifr_name && VIR_STRDUP(*ifname, ifr.ifr_name) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_FREE(*ifname);
|
||||
if (!(*ifname = strdup(ifr.ifr_name))) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
if ((flags & VIR_NETDEV_TAP_CREATE_PERSIST) &&
|
||||
(errno = ioctl(fd, TUNSETPERSIST, 1))) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to set tap device %s to persistent"),
|
||||
NULLSTR(*ifname));
|
||||
goto cleanup;
|
||||
}
|
||||
tapfd[i] = fd;
|
||||
}
|
||||
if (tapfd)
|
||||
*tapfd = fd;
|
||||
else
|
||||
VIR_FORCE_CLOSE(fd);
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
VIR_FORCE_CLOSE(fd);
|
||||
while (i--)
|
||||
VIR_FORCE_CLOSE(tapfd[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -266,6 +276,7 @@ cleanup:
|
||||
#else /* ! TUNSETIFF */
|
||||
int virNetDevTapCreate(char **ifname ATTRIBUTE_UNUSED,
|
||||
int *tapfd ATTRIBUTE_UNUSED,
|
||||
int tapfdSize ATTRIBUTE_UNUSED,
|
||||
unsigned int flags ATTRIBUTE_UNUSED)
|
||||
{
|
||||
virReportSystemError(ENOSYS, "%s",
|
||||
@ -286,7 +297,8 @@ int virNetDevTapDelete(const char *ifname ATTRIBUTE_UNUSED)
|
||||
* @brname: the bridge name
|
||||
* @ifname: the interface name (or name template)
|
||||
* @macaddr: desired MAC address
|
||||
* @tapfd: file descriptor return value for the new tap device
|
||||
* @tapfd: array of file descriptor return value for the new tap device
|
||||
* @tapfdSize: number of file descriptors in @tapfd
|
||||
* @virtPortProfile: bridge/port specific configuration
|
||||
* @flags: OR of virNetDevTapCreateFlags:
|
||||
|
||||
@ -314,6 +326,7 @@ int virNetDevTapCreateInBridgePort(const char *brname,
|
||||
const virMacAddrPtr macaddr,
|
||||
const unsigned char *vmuuid,
|
||||
int *tapfd,
|
||||
int tapfdSize,
|
||||
virNetDevVPortProfilePtr virtPortProfile,
|
||||
virNetDevVlanPtr virtVlan,
|
||||
unsigned int flags)
|
||||
@ -321,7 +334,7 @@ int virNetDevTapCreateInBridgePort(const char *brname,
|
||||
virMacAddr tapmac;
|
||||
char macaddrstr[VIR_MAC_STRING_BUFLEN];
|
||||
|
||||
if (virNetDevTapCreate(ifname, tapfd, flags) < 0)
|
||||
if (virNetDevTapCreate(ifname, tapfd, tapfdSize, flags) < 0)
|
||||
return -1;
|
||||
|
||||
/* We need to set the interface MAC before adding it
|
||||
@ -372,9 +385,9 @@ int virNetDevTapCreateInBridgePort(const char *brname,
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (tapfd)
|
||||
VIR_FORCE_CLOSE(*tapfd);
|
||||
error:
|
||||
while (tapfdSize)
|
||||
VIR_FORCE_CLOSE(tapfd[--tapfdSize]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
int virNetDevTapCreate(char **ifname,
|
||||
int *tapfd,
|
||||
int tapfdSize,
|
||||
unsigned int flags)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
|
||||
|
||||
@ -55,6 +56,7 @@ int virNetDevTapCreateInBridgePort(const char *brname,
|
||||
const virMacAddrPtr macaddr,
|
||||
const unsigned char *vmuuid,
|
||||
int *tapfd,
|
||||
int tapfdSize,
|
||||
virNetDevVPortProfilePtr virtPortProfile,
|
||||
virNetDevVlanPtr virtVlan,
|
||||
unsigned int flags)
|
||||
|
Loading…
x
Reference in New Issue
Block a user