mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-11-09 23:10:08 +00:00
network: populate interface pool immediately when network is started
When a network is defined with "<pf dev='xyz'/>", libvirt will query sysfs to learn the list of all virtual functions (VF) associated with that Physical Function (PF) then populate the network's interface pool accordingly. This action was previously done only when the first guest actually requested an interface from the network. This patch changes it to populate the pool immediately when the network is started. This way any problems with the PF or its VFs will become apparent sooner. Note that we can't remove the old calls to networkCreateInterfacePool that happen whenever a guest requests an interface - doing so would be asking for failures on hosts that had libvirt upgraded with a network that had been started but not yet used. This resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1047818
This commit is contained in:
parent
cd7759cb96
commit
2a193f6458
@ -2180,16 +2180,121 @@ static int networkShutdownNetworkVirtual(virNetworkDriverStatePtr driver ATTRIBU
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* networkCreateInterfacePool:
|
||||||
|
* @netdef: the original NetDef from the network
|
||||||
|
*
|
||||||
|
* Creates an implicit interface pool of VF's when a PF dev is given
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
networkCreateInterfacePool(virNetworkDefPtr netdef)
|
||||||
|
{
|
||||||
|
size_t numVirtFns = 0;
|
||||||
|
char **vfNames = NULL;
|
||||||
|
virPCIDeviceAddressPtr *virtFns;
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if ((virNetDevGetVirtualFunctions(netdef->forward.pfs->dev,
|
||||||
|
&vfNames, &virtFns, &numVirtFns)) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Could not get Virtual functions on %s"),
|
||||||
|
netdef->forward.pfs->dev);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
netdef->forward.nifs = 0;
|
||||||
|
if (VIR_ALLOC_N(netdef->forward.ifs, numVirtFns) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < numVirtFns; i++) {
|
||||||
|
virPCIDeviceAddressPtr thisVirtFn = virtFns[i];
|
||||||
|
const char *thisName = vfNames[i];
|
||||||
|
virNetworkForwardIfDefPtr thisIf
|
||||||
|
= &netdef->forward.ifs[netdef->forward.nifs];
|
||||||
|
|
||||||
|
switch (netdef->forward.type) {
|
||||||
|
case VIR_NETWORK_FORWARD_BRIDGE:
|
||||||
|
case VIR_NETWORK_FORWARD_PRIVATE:
|
||||||
|
case VIR_NETWORK_FORWARD_VEPA:
|
||||||
|
case VIR_NETWORK_FORWARD_PASSTHROUGH:
|
||||||
|
if (thisName) {
|
||||||
|
if (VIR_STRDUP(thisIf->device.dev, thisName) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
thisIf->type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
|
||||||
|
netdef->forward.nifs++;
|
||||||
|
} else {
|
||||||
|
VIR_WARN("VF %zu of SRIOV PF %s couldn't be added to the "
|
||||||
|
"interface pool because it isn't bound "
|
||||||
|
"to a network driver - possibly in use elsewhere",
|
||||||
|
i, netdef->forward.pfs->dev);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIR_NETWORK_FORWARD_HOSTDEV:
|
||||||
|
/* VF's are always PCI devices */
|
||||||
|
thisIf->type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI;
|
||||||
|
thisIf->device.pci.domain = thisVirtFn->domain;
|
||||||
|
thisIf->device.pci.bus = thisVirtFn->bus;
|
||||||
|
thisIf->device.pci.slot = thisVirtFn->slot;
|
||||||
|
thisIf->device.pci.function = thisVirtFn->function;
|
||||||
|
netdef->forward.nifs++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIR_NETWORK_FORWARD_NONE:
|
||||||
|
case VIR_NETWORK_FORWARD_NAT:
|
||||||
|
case VIR_NETWORK_FORWARD_ROUTE:
|
||||||
|
case VIR_NETWORK_FORWARD_LAST:
|
||||||
|
/* by definition these will never be encountered here */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (netdef->forward.nifs == 0) {
|
||||||
|
/* If we don't get at least one interface in the pool, declare
|
||||||
|
* failure
|
||||||
|
*/
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("No usable Vf's present on SRIOV PF %s"),
|
||||||
|
netdef->forward.pfs->dev);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
if (ret < 0) {
|
||||||
|
/* free all the entries made before error */
|
||||||
|
for (i = 0; i < netdef->forward.nifs; i++) {
|
||||||
|
if (netdef->forward.ifs[i].type
|
||||||
|
== VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV)
|
||||||
|
VIR_FREE(netdef->forward.ifs[i].device.dev);
|
||||||
|
}
|
||||||
|
netdef->forward.nifs = 0;
|
||||||
|
}
|
||||||
|
if (netdef->forward.nifs == 0)
|
||||||
|
VIR_FREE(netdef->forward.ifs);
|
||||||
|
|
||||||
|
for (i = 0; i < numVirtFns; i++) {
|
||||||
|
VIR_FREE(vfNames[i]);
|
||||||
|
VIR_FREE(virtFns[i]);
|
||||||
|
}
|
||||||
|
VIR_FREE(vfNames);
|
||||||
|
VIR_FREE(virtFns);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
networkStartNetworkExternal(virNetworkDriverStatePtr driver ATTRIBUTE_UNUSED,
|
networkStartNetworkExternal(virNetworkDriverStatePtr driver ATTRIBUTE_UNUSED,
|
||||||
virNetworkObjPtr network ATTRIBUTE_UNUSED)
|
virNetworkObjPtr network)
|
||||||
{
|
{
|
||||||
/* put anything here that needs to be done each time a network of
|
/* put anything here that needs to be done each time a network of
|
||||||
* type BRIDGE, PRIVATE, VEPA, HOSTDEV or PASSTHROUGH is started. On
|
* type BRIDGE, PRIVATE, VEPA, HOSTDEV or PASSTHROUGH is started. On
|
||||||
* failure, undo anything you've done, and return -1. On success
|
* failure, undo anything you've done, and return -1. On success
|
||||||
* return 0.
|
* return 0.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return networkCreateInterfacePool(network->def);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int networkShutdownNetworkExternal(virNetworkDriverStatePtr driver ATTRIBUTE_UNUSED,
|
static int networkShutdownNetworkExternal(virNetworkDriverStatePtr driver ATTRIBUTE_UNUSED,
|
||||||
@ -3600,109 +3705,6 @@ int networkRegister(void)
|
|||||||
* "backend" function table.
|
* "backend" function table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* networkCreateInterfacePool:
|
|
||||||
* @netdef: the original NetDef from the network
|
|
||||||
*
|
|
||||||
* Creates an implicit interface pool of VF's when a PF dev is given
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
networkCreateInterfacePool(virNetworkDefPtr netdef)
|
|
||||||
{
|
|
||||||
size_t numVirtFns = 0;
|
|
||||||
char **vfNames = NULL;
|
|
||||||
virPCIDeviceAddressPtr *virtFns;
|
|
||||||
|
|
||||||
int ret = -1;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if ((virNetDevGetVirtualFunctions(netdef->forward.pfs->dev,
|
|
||||||
&vfNames, &virtFns, &numVirtFns)) < 0) {
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("Could not get Virtual functions on %s"),
|
|
||||||
netdef->forward.pfs->dev);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
netdef->forward.nifs = 0;
|
|
||||||
if (VIR_ALLOC_N(netdef->forward.ifs, numVirtFns) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
for (i = 0; i < numVirtFns; i++) {
|
|
||||||
virPCIDeviceAddressPtr thisVirtFn = virtFns[i];
|
|
||||||
const char *thisName = vfNames[i];
|
|
||||||
virNetworkForwardIfDefPtr thisIf
|
|
||||||
= &netdef->forward.ifs[netdef->forward.nifs];
|
|
||||||
|
|
||||||
switch (netdef->forward.type) {
|
|
||||||
case VIR_NETWORK_FORWARD_BRIDGE:
|
|
||||||
case VIR_NETWORK_FORWARD_PRIVATE:
|
|
||||||
case VIR_NETWORK_FORWARD_VEPA:
|
|
||||||
case VIR_NETWORK_FORWARD_PASSTHROUGH:
|
|
||||||
if (thisName) {
|
|
||||||
if (VIR_STRDUP(thisIf->device.dev, thisName) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
thisIf->type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
|
|
||||||
netdef->forward.nifs++;
|
|
||||||
} else {
|
|
||||||
VIR_WARN("VF %zu of SRIOV PF %s couldn't be added to the "
|
|
||||||
"interface pool because it isn't bound "
|
|
||||||
"to a network driver - possibly in use elsewhere",
|
|
||||||
i, netdef->forward.pfs->dev);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIR_NETWORK_FORWARD_HOSTDEV:
|
|
||||||
/* VF's are always PCI devices */
|
|
||||||
thisIf->type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI;
|
|
||||||
thisIf->device.pci.domain = thisVirtFn->domain;
|
|
||||||
thisIf->device.pci.bus = thisVirtFn->bus;
|
|
||||||
thisIf->device.pci.slot = thisVirtFn->slot;
|
|
||||||
thisIf->device.pci.function = thisVirtFn->function;
|
|
||||||
netdef->forward.nifs++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIR_NETWORK_FORWARD_NONE:
|
|
||||||
case VIR_NETWORK_FORWARD_NAT:
|
|
||||||
case VIR_NETWORK_FORWARD_ROUTE:
|
|
||||||
case VIR_NETWORK_FORWARD_LAST:
|
|
||||||
/* by definition these will never be encountered here */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (netdef->forward.nifs == 0) {
|
|
||||||
/* If we don't get at least one interface in the pool, declare
|
|
||||||
* failure
|
|
||||||
*/
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("No usable Vf's present on SRIOV PF %s"),
|
|
||||||
netdef->forward.pfs->dev);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
cleanup:
|
|
||||||
if (ret < 0) {
|
|
||||||
/* free all the entries made before error */
|
|
||||||
for (i = 0; i < netdef->forward.nifs; i++) {
|
|
||||||
if (netdef->forward.ifs[i].type
|
|
||||||
== VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV)
|
|
||||||
VIR_FREE(netdef->forward.ifs[i].device.dev);
|
|
||||||
}
|
|
||||||
netdef->forward.nifs = 0;
|
|
||||||
}
|
|
||||||
if (netdef->forward.nifs == 0)
|
|
||||||
VIR_FREE(netdef->forward.ifs);
|
|
||||||
|
|
||||||
for (i = 0; i < numVirtFns; i++) {
|
|
||||||
VIR_FREE(vfNames[i]);
|
|
||||||
VIR_FREE(virtFns[i]);
|
|
||||||
}
|
|
||||||
VIR_FREE(vfNames);
|
|
||||||
VIR_FREE(virtFns);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* networkAllocateActualDevice:
|
/* networkAllocateActualDevice:
|
||||||
* @dom: domain definition that @iface belongs to
|
* @dom: domain definition that @iface belongs to
|
||||||
* @iface: the original NetDef from the domain
|
* @iface: the original NetDef from the domain
|
||||||
|
Loading…
Reference in New Issue
Block a user