network: introduce networkAllocatePort

Separate network port allocation code from the domain driver network
callback implementation.

Reviewed-by: Laine Stump <laine@laine.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2018-12-20 14:01:18 +00:00
parent f02e21cb33
commit 7475562d5b

View File

@ -4359,60 +4359,38 @@ networkLogAllocation(virNetworkDefPtr netdef,
* "backend" function table. * "backend" function table.
*/ */
/* networkAllocateActualDevice: /* networkAllocatePort:
* @dom: domain definition that @iface belongs to * @obj: the network to allocate from
* @iface: the original NetDef from the domain * @port: the port definition to allocate
* *
* Looks up the network reference by iface, allocates a physical * Looks up the network reference by port, allocates a physical
* device from that network (if appropriate), and returns with the * device from that network (if appropriate), and returns with the
* virDomainActualNetDef filled in accordingly. If there are no * port configuration filled in accordingly.
* changes to be made in the netdef, then just leave the actualdef
* empty.
* *
* Returns 0 on success, -1 on failure. * Returns 0 on success, -1 on failure.
*/ */
static int static int
networkAllocateActualDevice(virNetworkPtr net, networkAllocatePort(virNetworkObjPtr obj,
virDomainDefPtr dom, virNetworkPortDefPtr port)
virDomainNetDefPtr iface)
{ {
virNetworkDriverStatePtr driver = networkGetDriver(); virNetworkDriverStatePtr driver = networkGetDriver();
virNetworkObjPtr obj = NULL;
virNetworkDefPtr netdef = NULL; virNetworkDefPtr netdef = NULL;
virPortGroupDefPtr portgroup = NULL; virPortGroupDefPtr portgroup = NULL;
virNetworkForwardIfDefPtr dev = NULL; virNetworkForwardIfDefPtr dev = NULL;
size_t i; size_t i;
int ret = -1; int ret = -1;
virNetDevVPortProfilePtr portprofile = NULL; virNetDevVPortProfilePtr portprofile = NULL;
virNetworkPortDefPtr port = NULL;
VIR_DEBUG("Allocating port from net %s", net->name);
obj = virNetworkObjFindByName(driver->networks, net->name);
if (!obj) {
virReportError(VIR_ERR_NO_NETWORK,
_("no network with matching name '%s'"),
net->name);
goto error;
}
if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Expected an interface for a virtual network"));
goto error;
}
netdef = virNetworkObjGetDef(obj); netdef = virNetworkObjGetDef(obj);
VIR_DEBUG("Allocating port from net %s", netdef->name);
if (!virNetworkObjIsActive(obj)) { if (!virNetworkObjIsActive(obj)) {
virReportError(VIR_ERR_OPERATION_INVALID, virReportError(VIR_ERR_OPERATION_INVALID,
_("network '%s' is not active"), _("network '%s' is not active"),
netdef->name); netdef->name);
goto error; goto cleanup;
} }
if (!(port = virDomainNetDefToNetworkPort(dom, iface)))
goto error;
VIR_DEBUG("Interface port group %s", port->group); VIR_DEBUG("Interface port group %s", port->group);
/* portgroup can be present for any type of network, in particular /* portgroup can be present for any type of network, in particular
* for bandwidth information, so we need to check for that and * for bandwidth information, so we need to check for that and
@ -4424,7 +4402,7 @@ networkAllocateActualDevice(virNetworkPtr net,
if (portgroup && portgroup->bandwidth && if (portgroup && portgroup->bandwidth &&
virNetDevBandwidthCopy(&port->bandwidth, virNetDevBandwidthCopy(&port->bandwidth,
portgroup->bandwidth) < 0) portgroup->bandwidth) < 0)
goto error; goto cleanup;
} }
if (port->vlan.nTags == 0) { if (port->vlan.nTags == 0) {
@ -4435,7 +4413,7 @@ networkAllocateActualDevice(virNetworkPtr net,
vlan = &netdef->vlan; vlan = &netdef->vlan;
if (vlan && virNetDevVlanCopy(&port->vlan, vlan) < 0) if (vlan && virNetDevVlanCopy(&port->vlan, vlan) < 0)
goto error; goto cleanup;
} }
if (!port->trustGuestRxFilters) { if (!port->trustGuestRxFilters) {
@ -4453,7 +4431,7 @@ networkAllocateActualDevice(virNetworkPtr net,
netdef->virtPortProfile, netdef->virtPortProfile,
portgroup portgroup
? portgroup->virtPortProfile : NULL) < 0) { ? portgroup->virtPortProfile : NULL) < 0) {
goto error; goto cleanup;
} }
if (portprofile) { if (portprofile) {
VIR_FREE(port->virtPortProfile); VIR_FREE(port->virtPortProfile);
@ -4473,7 +4451,7 @@ networkAllocateActualDevice(virNetworkPtr net,
port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_NETWORK; port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_NETWORK;
if (VIR_STRDUP(port->plug.bridge.brname, netdef->bridge) < 0) if (VIR_STRDUP(port->plug.bridge.brname, netdef->bridge) < 0)
goto error; goto cleanup;
port->plug.bridge.macTableManager = netdef->macTableManager; port->plug.bridge.macTableManager = netdef->macTableManager;
if (port->virtPortProfile) { if (port->virtPortProfile) {
@ -4482,18 +4460,18 @@ networkAllocateActualDevice(virNetworkPtr net,
"'%s' which uses IP forwarding"), "'%s' which uses IP forwarding"),
virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType),
netdef->name); netdef->name);
goto error; goto cleanup;
} }
if (networkPlugBandwidth(obj, &port->mac, port->bandwidth, &port->class_id) < 0) if (networkPlugBandwidth(obj, &port->mac, port->bandwidth, &port->class_id) < 0)
goto error; goto cleanup;
break; break;
case VIR_NETWORK_FORWARD_HOSTDEV: { case VIR_NETWORK_FORWARD_HOSTDEV: {
port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI; port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI;
if (networkCreateInterfacePool(netdef) < 0) if (networkCreateInterfacePool(netdef) < 0)
goto error; goto cleanup;
/* pick first dev with 0 connections */ /* pick first dev with 0 connections */
for (i = 0; i < netdef->forward.nifs; i++) { for (i = 0; i < netdef->forward.nifs; i++) {
@ -4507,7 +4485,7 @@ networkAllocateActualDevice(virNetworkPtr net,
_("network '%s' requires exclusive access " _("network '%s' requires exclusive access "
"to interfaces, but none are available"), "to interfaces, but none are available"),
netdef->name); netdef->name);
goto error; goto cleanup;
} }
port->plug.hostdevpci.addr = dev->device.pci; port->plug.hostdevpci.addr = dev->device.pci;
port->plug.hostdevpci.driver = netdef->forward.driverName; port->plug.hostdevpci.driver = netdef->forward.driverName;
@ -4523,7 +4501,7 @@ networkAllocateActualDevice(virNetworkPtr net,
"via PCI passthrough"), "via PCI passthrough"),
virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType),
netdef->name); netdef->name);
goto error; goto cleanup;
} }
} }
break; break;
@ -4537,7 +4515,7 @@ networkAllocateActualDevice(virNetworkPtr net,
port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE; port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE;
if (VIR_STRDUP(port->plug.bridge.brname, netdef->bridge) < 0) if (VIR_STRDUP(port->plug.bridge.brname, netdef->bridge) < 0)
goto error; goto cleanup;
port->plug.bridge.macTableManager = netdef->macTableManager; port->plug.bridge.macTableManager = netdef->macTableManager;
if (port->virtPortProfile) { if (port->virtPortProfile) {
@ -4548,12 +4526,12 @@ networkAllocateActualDevice(virNetworkPtr net,
"'%s' which uses a bridge device"), "'%s' which uses a bridge device"),
virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType),
netdef->name); netdef->name);
goto error; goto cleanup;
} }
} }
if (networkPlugBandwidth(obj, &port->mac, port->bandwidth, &port->class_id) < 0) if (networkPlugBandwidth(obj, &port->mac, port->bandwidth, &port->class_id) < 0)
goto error; goto cleanup;
break; break;
} }
@ -4587,7 +4565,7 @@ networkAllocateActualDevice(virNetworkPtr net,
"'%s' which uses a macvtap device"), "'%s' which uses a macvtap device"),
virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType),
netdef->name); netdef->name);
goto error; goto cleanup;
} }
} }
@ -4599,12 +4577,12 @@ networkAllocateActualDevice(virNetworkPtr net,
_("network '%s' uses a direct mode, but " _("network '%s' uses a direct mode, but "
"has no forward dev and no interface pool"), "has no forward dev and no interface pool"),
netdef->name); netdef->name);
goto error; goto cleanup;
} else { } else {
/* pick an interface from the pool */ /* pick an interface from the pool */
if (networkCreateInterfacePool(netdef) < 0) if (networkCreateInterfacePool(netdef) < 0)
goto error; goto cleanup;
/* PASSTHROUGH mode, and PRIVATE Mode + 802.1Qbh both /* PASSTHROUGH mode, and PRIVATE Mode + 802.1Qbh both
* require exclusive access to a device, so current * require exclusive access to a device, so current
@ -4639,26 +4617,26 @@ networkAllocateActualDevice(virNetworkPtr net,
_("network '%s' requires exclusive access " _("network '%s' requires exclusive access "
"to interfaces, but none are available"), "to interfaces, but none are available"),
netdef->name); netdef->name);
goto error; goto cleanup;
} }
if (VIR_STRDUP(port->plug.direct.linkdev, if (VIR_STRDUP(port->plug.direct.linkdev,
dev->device.dev) < 0) dev->device.dev) < 0)
goto error; goto cleanup;
} }
break; break;
case VIR_NETWORK_FORWARD_LAST: case VIR_NETWORK_FORWARD_LAST:
default: default:
virReportEnumRangeError(virNetworkForwardType, netdef->forward.type); virReportEnumRangeError(virNetworkForwardType, netdef->forward.type);
goto error; goto cleanup;
} }
if (virNetworkObjMacMgrAdd(obj, driver->dnsmasqStateDir, if (virNetworkObjMacMgrAdd(obj, driver->dnsmasqStateDir,
dom->name, &port->mac) < 0) port->ownername, &port->mac) < 0)
goto error; goto cleanup;
if (virNetDevVPortProfileCheckComplete(port->virtPortProfile, true) < 0) if (virNetDevVPortProfileCheckComplete(port->virtPortProfile, true) < 0)
goto error; goto cleanup;
/* make sure that everything now specified for the device is /* make sure that everything now specified for the device is
* actually supported on this type of network. NB: network, * actually supported on this type of network. NB: network,
@ -4683,7 +4661,7 @@ networkAllocateActualDevice(virNetworkPtr net,
"is requesting a vlan tag, but that is not " "is requesting a vlan tag, but that is not "
"supported for this type of network"), "supported for this type of network"),
netdef->name); netdef->name);
goto error; goto cleanup;
} }
} }
@ -4694,7 +4672,7 @@ networkAllocateActualDevice(virNetworkPtr net,
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("bandwidth settings are not supported " _("bandwidth settings are not supported "
"for hostdev interfaces")); "for hostdev interfaces"));
goto error; goto cleanup;
} }
netdef->connections++; netdef->connections++;
@ -4708,28 +4686,61 @@ networkAllocateActualDevice(virNetworkPtr net,
netdef->connections--; netdef->connections--;
if (dev) if (dev)
dev->connections--; dev->connections--;
goto error; goto cleanup;
} }
networkLogAllocation(netdef, dev, &iface->mac, true); networkLogAllocation(netdef, dev, &port->mac, true);
VIR_DEBUG("Port allocated");
ret = 0;
cleanup:
return ret;
}
static int
networkAllocateActualDevice(virNetworkPtr net,
virDomainDefPtr dom,
virDomainNetDefPtr iface)
{
virNetworkDriverStatePtr driver = networkGetDriver();
virNetworkPortDefPtr port = NULL;
virNetworkObjPtr obj;
int ret = -1;
obj = virNetworkObjFindByName(driver->networks, net->name);
if (!obj) {
virReportError(VIR_ERR_NO_NETWORK,
_("no network with matching name '%s'"),
net->name);
return -1;
}
if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Expected an interface for a virtual network"));
goto cleanup;
}
if (!(port = virDomainNetDefToNetworkPort(dom, iface)))
goto cleanup;
if (networkAllocatePort(obj, port) < 0)
goto cleanup;
VIR_DEBUG("Populating net def"); VIR_DEBUG("Populating net def");
if (virDomainNetDefActualFromNetworkPort(iface, port) < 0) if (virDomainNetDefActualFromNetworkPort(iface, port) < 0)
goto error; goto cleanup;
VIR_DEBUG("Port allocated");
ret = 0; ret = 0;
cleanup: cleanup:
virNetworkPortDefFree(port); if (ret < 0) {
virNetworkObjEndAPI(&obj);
return ret;
error:
if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
virDomainActualNetDefFree(iface->data.network.actual); virDomainActualNetDefFree(iface->data.network.actual);
iface->data.network.actual = NULL; iface->data.network.actual = NULL;
} }
goto cleanup; virNetworkPortDefFree(port);
virNetworkObjEndAPI(&obj);
return ret;
} }