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
---
src/network/bridge_driver.c | 212 ++++++++++++++++++++++----------------------
1 file changed, 107 insertions(+), 105 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 918de29..4653d53 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -2180,16 +2180,121 @@ static int networkShutdownNetworkVirtual(virNetworkDriverStatePtr
driver ATTRIBU
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
networkStartNetworkExternal(virNetworkDriverStatePtr driver ATTRIBUTE_UNUSED,
- virNetworkObjPtr network ATTRIBUTE_UNUSED)
+ virNetworkObjPtr network)
{
/* put anything here that needs to be done each time a network of
* type BRIDGE, PRIVATE, VEPA, HOSTDEV or PASSTHROUGH is started. On
* failure, undo anything you've done, and return -1. On success
* return 0.
*/
- return 0;
+ return networkCreateInterfacePool(network->def);
}
static int networkShutdownNetworkExternal(virNetworkDriverStatePtr driver
ATTRIBUTE_UNUSED,
@@ -3600,109 +3705,6 @@ int networkRegister(void)
* "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:
* @dom: domain definition that @iface belongs to
* @iface: the original NetDef from the domain
--
1.9.3