network: convert networkAllocateActualDevice to virNetworkPortDef

Convert the virDomainNetDef object into a virNetworkPortDef object
at the start of networkAllocateActualDevice. This largely decouples
the method impl from the domain object type.

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-09-03 17:34:22 +01:00
parent 200bfd43ba
commit 6cb0ec48bd

View File

@ -67,6 +67,7 @@
#include "network_event.h" #include "network_event.h"
#include "virhook.h" #include "virhook.h"
#include "virjson.h" #include "virjson.h"
#include "virnetworkportdef.h"
#define VIR_FROM_THIS VIR_FROM_NETWORK #define VIR_FROM_THIS VIR_FROM_NETWORK
#define MAX_BRIDGE_ID 256 #define MAX_BRIDGE_ID 256
@ -4381,17 +4382,16 @@ networkAllocateActualDevice(virNetworkPtr net,
virDomainNetDefPtr iface) virDomainNetDefPtr iface)
{ {
virNetworkDriverStatePtr driver = networkGetDriver(); virNetworkDriverStatePtr driver = networkGetDriver();
virDomainNetType actualType = iface->type;
virNetworkObjPtr obj = NULL; virNetworkObjPtr obj = NULL;
virNetworkDefPtr netdef = NULL; virNetworkDefPtr netdef = NULL;
virNetDevBandwidthPtr bandwidth = NULL;
virPortGroupDefPtr portgroup = NULL; virPortGroupDefPtr portgroup = NULL;
virNetDevVPortProfilePtr virtport = iface->virtPortProfile;
virNetDevVlanPtr vlan = NULL;
virNetworkForwardIfDefPtr dev = NULL; virNetworkForwardIfDefPtr dev = NULL;
size_t i; size_t i;
int ret = -1; int ret = -1;
virNetDevVPortProfilePtr portprofile = NULL;
virNetworkPortDefPtr port = NULL;
VIR_DEBUG("Allocating port from net %s", net->name);
obj = virNetworkObjFindByName(driver->networks, net->name); obj = virNetworkObjFindByName(driver->networks, net->name);
if (!obj) { if (!obj) {
virReportError(VIR_ERR_NO_NETWORK, virReportError(VIR_ERR_NO_NETWORK,
@ -4406,9 +4406,6 @@ networkAllocateActualDevice(virNetworkPtr net,
goto error; goto error;
} }
virDomainActualNetDefFree(iface->data.network.actual);
iface->data.network.actual = NULL;
netdef = virNetworkObjGetDef(obj); netdef = virNetworkObjGetDef(obj);
if (!virNetworkObjIsActive(obj)) { if (!virNetworkObjIsActive(obj)) {
@ -4418,62 +4415,57 @@ networkAllocateActualDevice(virNetworkPtr net,
goto error; goto error;
} }
if (VIR_ALLOC(iface->data.network.actual) < 0) if (!(port = virDomainNetDefToNetworkPort(dom, iface)))
goto error; goto error;
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
* fill it in appropriately for all forward types. * fill it in appropriately for all forward types.
*/ */
portgroup = virPortGroupFindByName(netdef, iface->data.network.portgroup); portgroup = virPortGroupFindByName(netdef, port->group);
/* If there is already interface-specific bandwidth, just use that if (!port->bandwidth) {
* (already in NetDef). Otherwise, if there is bandwidth info in if (portgroup && portgroup->bandwidth &&
* the portgroup, fill that into the ActualDef. virNetDevBandwidthCopy(&port->bandwidth,
*/ portgroup->bandwidth) < 0)
goto error;
}
if (iface->bandwidth) if (port->vlan.nTags == 0) {
bandwidth = iface->bandwidth; virNetDevVlanPtr vlan = NULL;
else if (portgroup && portgroup->bandwidth) if (portgroup && portgroup->vlan.nTags > 0)
bandwidth = portgroup->bandwidth; vlan = &portgroup->vlan;
else if (netdef->vlan.nTags > 0)
vlan = &netdef->vlan;
if (bandwidth && virNetDevBandwidthCopy(&iface->data.network.actual->bandwidth, if (vlan && virNetDevVlanCopy(&port->vlan, vlan) < 0)
bandwidth) < 0) goto error;
goto error; }
/* copy appropriate vlan info to actualNet */ if (!port->trustGuestRxFilters) {
if (iface->vlan.nTags > 0) if (portgroup && portgroup->trustGuestRxFilters)
vlan = &iface->vlan; port->trustGuestRxFilters = portgroup->trustGuestRxFilters;
else if (portgroup && portgroup->vlan.nTags > 0) else if (netdef->trustGuestRxFilters)
vlan = &portgroup->vlan; port->trustGuestRxFilters = netdef->trustGuestRxFilters;
else if (netdef->vlan.nTags > 0) }
vlan = &netdef->vlan;
if (vlan && virNetDevVlanCopy(&iface->data.network.actual->vlan, vlan) < 0)
goto error;
if (iface->trustGuestRxFilters)
iface->data.network.actual->trustGuestRxFilters
= iface->trustGuestRxFilters;
else if (portgroup && portgroup->trustGuestRxFilters)
iface->data.network.actual->trustGuestRxFilters
= portgroup->trustGuestRxFilters;
else if (netdef->trustGuestRxFilters)
iface->data.network.actual->trustGuestRxFilters
= netdef->trustGuestRxFilters;
/* merge virtualports from interface, network, and portgroup to /* merge virtualports from interface, network, and portgroup to
* arrive at actual virtualport to use * arrive at actual virtualport to use
*/ */
if (virNetDevVPortProfileMerge3(&iface->data.network.actual->virtPortProfile, if (virNetDevVPortProfileMerge3(&portprofile,
iface->virtPortProfile, port->virtPortProfile,
netdef->virtPortProfile, netdef->virtPortProfile,
portgroup portgroup
? portgroup->virtPortProfile : NULL) < 0) { ? portgroup->virtPortProfile : NULL) < 0) {
goto error; goto error;
}
if (portprofile) {
VIR_FREE(port->virtPortProfile);
port->virtPortProfile = portprofile;
} }
virtport = iface->data.network.actual->virtPortProfile;
VIR_DEBUG("Processing forward type %d", netdef->forward.type);
switch ((virNetworkForwardType) netdef->forward.type) { switch ((virNetworkForwardType) netdef->forward.type) {
case VIR_NETWORK_FORWARD_NONE: case VIR_NETWORK_FORWARD_NONE:
case VIR_NETWORK_FORWARD_NAT: case VIR_NETWORK_FORWARD_NAT:
@ -4483,38 +4475,28 @@ networkAllocateActualDevice(virNetworkPtr net,
* NETWORK; we just keep the info from the portgroup in * NETWORK; we just keep the info from the portgroup in
* iface->data.network.actual * iface->data.network.actual
*/ */
iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_NETWORK; port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_NETWORK;
/* we also store the bridge device and macTableManager settings if (VIR_STRDUP(port->plug.bridge.brname, netdef->bridge) < 0)
* in iface->data.network.actual->data.bridge for later use
* after the domain's tap device is created (to attach to the
* bridge and set flood/learning mode on the tap device)
*/
if (VIR_STRDUP(iface->data.network.actual->data.bridge.brname,
netdef->bridge) < 0)
goto error; goto error;
iface->data.network.actual->data.bridge.macTableManager port->plug.bridge.macTableManager = netdef->macTableManager;
= netdef->macTableManager;
if (virtport) { if (port->virtPortProfile) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("<virtualport type='%s'> not supported for network " _("<virtualport type='%s'> not supported for network "
"'%s' which uses IP forwarding"), "'%s' which uses IP forwarding"),
virNetDevVPortTypeToString(virtport->virtPortType), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType),
netdef->name); netdef->name);
goto error; goto error;
} }
if (networkPlugBandwidth(obj, &iface->mac, iface->bandwidth, if (networkPlugBandwidth(obj, &port->mac, port->bandwidth, &port->class_id) < 0)
iface->data.network.actual ?
&iface->data.network.actual->class_id : NULL) < 0)
goto error; goto error;
break; break;
case VIR_NETWORK_FORWARD_HOSTDEV: { case VIR_NETWORK_FORWARD_HOSTDEV: {
virDomainHostdevSubsysPCIBackendType backend; port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI;
iface->data.network.actual->type = actualType = VIR_DOMAIN_NET_TYPE_HOSTDEV;
if (networkCreateInterfacePool(netdef) < 0) if (networkCreateInterfacePool(netdef) < 0)
goto error; goto error;
@ -4532,42 +4514,19 @@ networkAllocateActualDevice(virNetworkPtr net,
netdef->name); netdef->name);
goto error; goto error;
} }
iface->data.network.actual->data.hostdev.def.parentnet = iface; port->plug.hostdevpci.addr = dev->device.pci;
iface->data.network.actual->data.hostdev.def.info = &iface->info; port->plug.hostdevpci.driver = netdef->forward.driverName;
iface->data.network.actual->data.hostdev.def.mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; port->plug.hostdevpci.managed = netdef->forward.managed;
iface->data.network.actual->data.hostdev.def.managed = netdef->forward.managed ? 1 : 0;
iface->data.network.actual->data.hostdev.def.source.subsys.type = dev->type;
iface->data.network.actual->data.hostdev.def.source.subsys.u.pci.addr = dev->device.pci;
switch (netdef->forward.driverName) { if (port->virtPortProfile) {
case VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT:
backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT;
break;
case VIR_NETWORK_FORWARD_DRIVER_NAME_KVM:
backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM;
break;
case VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO:
backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
break;
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unrecognized driver name value %d "
" in network '%s'"),
netdef->forward.driverName, netdef->name);
goto error;
}
iface->data.network.actual->data.hostdev.def.source.subsys.u.pci.backend
= backend;
if (virtport) {
/* make sure type is supported for hostdev connections */ /* make sure type is supported for hostdev connections */
if (virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG && if (port->virtPortProfile->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG &&
virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBH) { port->virtPortProfile->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBH) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("<virtualport type='%s'> not supported for network " _("<virtualport type='%s'> not supported for network "
"'%s' which uses an SR-IOV Virtual Function " "'%s' which uses an SR-IOV Virtual Function "
"via PCI passthrough"), "via PCI passthrough"),
virNetDevVPortTypeToString(virtport->virtPortType), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType),
netdef->name); netdef->name);
goto error; goto error;
} }
@ -4581,28 +4540,24 @@ networkAllocateActualDevice(virNetworkPtr net,
* is VIR_DOMAIN_NET_TYPE_BRIDGE * is VIR_DOMAIN_NET_TYPE_BRIDGE
*/ */
iface->data.network.actual->type = actualType = VIR_DOMAIN_NET_TYPE_BRIDGE; port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE;
if (VIR_STRDUP(iface->data.network.actual->data.bridge.brname, if (VIR_STRDUP(port->plug.bridge.brname, netdef->bridge) < 0)
netdef->bridge) < 0)
goto error; goto error;
iface->data.network.actual->data.bridge.macTableManager port->plug.bridge.macTableManager = netdef->macTableManager;
= netdef->macTableManager;
if (virtport) { if (port->virtPortProfile) {
/* only type='openvswitch' is allowed for bridges */ /* only type='openvswitch' is allowed for bridges */
if (virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) { if (port->virtPortProfile->virtPortType != VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("<virtualport type='%s'> not supported for network " _("<virtualport type='%s'> not supported for network "
"'%s' which uses a bridge device"), "'%s' which uses a bridge device"),
virNetDevVPortTypeToString(virtport->virtPortType), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType),
netdef->name); netdef->name);
goto error; goto error;
} }
} }
if (networkPlugBandwidth(obj, &iface->mac, iface->bandwidth, if (networkPlugBandwidth(obj, &port->mac, port->bandwidth, &port->class_id) < 0)
iface->data.network.actual ?
&iface->data.network.actual->class_id : NULL) < 0)
goto error; goto error;
break; break;
} }
@ -4620,22 +4575,22 @@ networkAllocateActualDevice(virNetworkPtr net,
*/ */
/* Set type=direct and appropriate <source mode='xxx'/> */ /* Set type=direct and appropriate <source mode='xxx'/> */
iface->data.network.actual->type = actualType = VIR_DOMAIN_NET_TYPE_DIRECT; port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_DIRECT;
/* NO need to check the value returned from virNetDevMacVLanModeTypeFromString /* NO need to check the value returned from virNetDevMacVLanModeTypeFromString
* it must be valid for these forward type(bridge|private|vepa|passthrough) * it must be valid for these forward type(bridge|private|vepa|passthrough)
*/ */
iface->data.network.actual->data.direct.mode = port->plug.direct.mode =
virNetDevMacVLanModeTypeFromString(virNetworkForwardTypeToString(netdef->forward.type)); virNetDevMacVLanModeTypeFromString(virNetworkForwardTypeToString(netdef->forward.type));
if (virtport) { if (port->virtPortProfile) {
/* make sure type is supported for macvtap connections */ /* make sure type is supported for macvtap connections */
if (virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG && if (port->virtPortProfile->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG &&
virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBH) { port->virtPortProfile->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBH) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("<virtualport type='%s'> not supported for network " _("<virtualport type='%s'> not supported for network "
"'%s' which uses a macvtap device"), "'%s' which uses a macvtap device"),
virNetDevVPortTypeToString(virtport->virtPortType), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType),
netdef->name); netdef->name);
goto error; goto error;
} }
@ -4664,8 +4619,8 @@ networkAllocateActualDevice(virNetworkPtr net,
*/ */
if ((netdef->forward.type == VIR_NETWORK_FORWARD_PASSTHROUGH) || if ((netdef->forward.type == VIR_NETWORK_FORWARD_PASSTHROUGH) ||
((netdef->forward.type == VIR_NETWORK_FORWARD_PRIVATE) && ((netdef->forward.type == VIR_NETWORK_FORWARD_PRIVATE) &&
iface->data.network.actual->virtPortProfile && port->virtPortProfile &&
(iface->data.network.actual->virtPortProfile->virtPortType (port->virtPortProfile->virtPortType
== VIR_NETDEV_VPORT_PROFILE_8021QBH))) { == VIR_NETDEV_VPORT_PROFILE_8021QBH))) {
/* pick first dev with 0 connections */ /* pick first dev with 0 connections */
@ -4691,7 +4646,7 @@ networkAllocateActualDevice(virNetworkPtr net,
netdef->name); netdef->name);
goto error; goto error;
} }
if (VIR_STRDUP(iface->data.network.actual->data.direct.linkdev, if (VIR_STRDUP(port->plug.direct.linkdev,
dev->device.dev) < 0) dev->device.dev) < 0)
goto error; goto error;
} }
@ -4704,30 +4659,30 @@ networkAllocateActualDevice(virNetworkPtr net,
} }
if (virNetworkObjMacMgrAdd(obj, driver->dnsmasqStateDir, if (virNetworkObjMacMgrAdd(obj, driver->dnsmasqStateDir,
dom->name, &iface->mac) < 0) dom->name, &port->mac) < 0)
goto error; goto error;
if (virNetDevVPortProfileCheckComplete(virtport, true) < 0) if (virNetDevVPortProfileCheckComplete(port->virtPortProfile, true) < 0)
goto error; goto error;
/* 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,
* netdev, and iface->data.network.actual may all be NULL. * netdev, and iface->data.network.actual may all be NULL.
*/ */
VIR_DEBUG("Sanity check port config");
if (virDomainNetGetActualVlan(iface)) { if (port->vlan.nTags) {
/* vlan configuration via libvirt is only supported for PCI /* vlan configuration via libvirt is only supported for PCI
* Passthrough SR-IOV devices (hostdev or macvtap passthru * Passthrough SR-IOV devices (hostdev or macvtap passthru
* mode) and openvswitch bridges. Otherwise log an error and * mode) and openvswitch bridges. Otherwise log an error and
* fail * fail
*/ */
if (!(actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV || if (!(port->plugtype == VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI ||
(actualType == VIR_DOMAIN_NET_TYPE_DIRECT && (port->plugtype == VIR_NETWORK_PORT_PLUG_TYPE_DIRECT &&
virDomainNetGetActualDirectMode(iface) port->plug.direct.mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) ||
== VIR_NETDEV_MACVLAN_MODE_PASSTHRU) || (port->plugtype == VIR_DOMAIN_NET_TYPE_BRIDGE &&
(actualType == VIR_DOMAIN_NET_TYPE_BRIDGE && port->virtPortProfile &&
virtport && virtport->virtPortType port->virtPortProfile->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH))) {
== VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH))) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("an interface connecting to network '%s' " _("an interface connecting to network '%s' "
"is requesting a vlan tag, but that is not " "is requesting a vlan tag, but that is not "
@ -4736,16 +4691,15 @@ networkAllocateActualDevice(virNetworkPtr net,
goto error; goto error;
} }
} }
if (virDomainNetGetActualBandwidth(iface)) {
/* bandwidth configuration via libvirt is not supported for /* bandwidth configuration via libvirt is not supported for
* hostdev network devices * hostdev network devices
*/ */
if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) { if (port->bandwidth && port->plugtype == VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI) {
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 error;
}
} }
netdef->connections++; netdef->connections++;
@ -4763,9 +4717,15 @@ networkAllocateActualDevice(virNetworkPtr net,
} }
networkLogAllocation(netdef, dev, &iface->mac, true); networkLogAllocation(netdef, dev, &iface->mac, true);
VIR_DEBUG("Populating net def");
if (virDomainNetDefActualFromNetworkPort(iface, port) < 0)
goto error;
VIR_DEBUG("Port allocated");
ret = 0; ret = 0;
cleanup: cleanup:
virNetworkPortDefFree(port);
virNetworkObjEndAPI(&obj); virNetworkObjEndAPI(&obj);
return ret; return ret;