--- src/network/bridge_driver.c | 208 +++++++++++++++++++++++++++++++++++++------ 1 files changed, 179 insertions(+), 29 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index c49c25b..a2e3119 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -55,6 +55,7 @@ #include "memory.h" #include "uuid.h" #include "iptables.h" +#include "pci.h" #include "logging.h" #include "dnsmasq.h" #include "configmake.h" @@ -2823,8 +2824,11 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) goto cleanup; } else { int ii; - virNetworkForwardIfDefPtr dev = NULL; - + virNetworkForwardVfDefPtr dev = NULL; + unsigned int vf_found = 0; + unsigned int num_virt_fns = 0; + struct pci_config_address **virt_fns = NULL; + /* pick an interface from the pool */ /* PASSTHROUGH mode, and PRIVATE Mode + 802.1Qbh both require @@ -2832,32 +2836,105 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) * 0. Other modes can share, so just search for the one with * the lowest usageCount. */ - if ((netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) || - ((netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE) && - iface->data.network.actual->data.direct.virtPortProfile && - (iface->data.network.actual->data.direct.virtPortProfile->virtPortType - == VIR_NETDEV_VPORT_PROFILE_8021QBH))) { - /* pick first dev with 0 usageCount */ + if (netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) { + if (netdef->nForwardIfs == 1) { + if (netdef->forwardIfs[0].vfs_in_use_count == 0) { + if ((virNetDevGetVirtualFunctions(netdef->forwardIfs[0].dev, + &virt_fns, &num_virt_fns)) < 0){ + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get Virtual functions on %s"), + netdef->forwardIfs[0].dev); + goto out; + } + + netdef->forwardIfs[0].nForwardVfs = num_virt_fns; + + if ((VIR_ALLOC_N(netdef->forwardIfs[0].forwardVfs, + netdef->forwardIfs[0].nForwardVfs)) < 0) { + virReportOOMError(); + goto out; + } + + for (ii = 0; ii < netdef->forwardIfs[0].nForwardVfs; ii++) { + if ((virNetDevGetNetName(virt_fns[ii], + &netdef->forwardIfs[0].forwardVfs[ii].dev)) < 0) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get Interface name")); + goto out; + } + netdef->forwardIfs[0].forwardVfs[ii].usageCount = 0; + } + } + + for (ii = 0; ii < netdef->forwardIfs[0].nForwardVfs; ii++) { + if (netdef->forwardIfs[0].forwardVfs[ii].usageCount == 0) { + netdef->forwardIfs[0].vfs_in_use_count++; + dev = &netdef->forwardIfs[0].forwardVfs[ii]; + vf_found = 1; + break; + } + } + /* If No Vf's are present or if Vf's are in use + * check whether the PF is free and assign PF + * to dev + */ + if(vf_found == 0) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("No Free Vf's on %s, checking if PF is free"), + netdef->forwardIfs[0].dev); + if (netdef->forwardIfs[0].usageCount == 0) { + dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[0]; + } + } + vf_found = 0; + } + /* If more than 1 ForwardIfs are present check usagecount of each + * find the one that is free + */ + else { + for (ii = 0; ii < netdef->nForwardIfs; ii++) { + if (netdef->forwardIfs[ii].usageCount == 0) { + dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[ii]; + break; + } + } + } + } + else if ((netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE) && + iface->data.network.actual->data.direct.virtPortProfile && + (iface->data.network.actual->data.direct.virtPortProfile->virtPortType + == VIR_NETDEV_VPORT_PROFILE_8021QBH)) { + + + /* pick first dev with 0 usageCount */ + for (ii = 0; ii < netdef->nForwardIfs; ii++) { if (netdef->forwardIfs[ii].usageCount == 0) { - dev = &netdef->forwardIfs[ii]; + dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[ii]; break; } } - } else { + } + else { /* pick least used dev */ - dev = &netdef->forwardIfs[0]; + dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[0]; for (ii = 1; ii < netdef->nForwardIfs; ii++) { if (netdef->forwardIfs[ii].usageCount < dev->usageCount) - dev = &netdef->forwardIfs[ii]; + dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[ii]; } } + + out: + for (ii = 0; ii < num_virt_fns; ii++) + VIR_FREE(virt_fns[ii]); + VIR_FREE(virt_fns); + /* dev points at the physical device we want to use */ if (!dev) { networkReportError(VIR_ERR_INTERNAL_ERROR, _("network '%s' requires exclusive access to interfaces, but none are available"), - netdef->name); + netdef->name); goto cleanup; } iface->data.network.actual->data.direct.linkdev = strdup(dev->dev); @@ -2871,7 +2948,7 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) dev->dev, dev->usageCount); } } - + ret = 0; cleanup: if (network) @@ -2935,17 +3012,55 @@ networkNotifyActualDevice(virDomainNetDefPtr iface) netdef->name); goto cleanup; } else { - int ii; - virNetworkForwardIfDefPtr dev = NULL; - + int ii, jj, isVf; + virNetworkForwardVfDefPtr dev = NULL; + char *pfDeviceName; + /* find the matching interface in the pool and increment its usageCount */ + + isVf = virNetDevIsVirtualFunction(actualDev); - for (ii = 0; ii < netdef->nForwardIfs; ii++) { - if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) { - dev = &netdef->forwardIfs[ii]; - break; + if (isVf == 1) { + /*If Vf get PF : pciGetPhysicalFunction */ + if ((virNetDevGetPhysicalFunction(actualDev, &pfDeviceName)) < 0) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get Physical functions for %s"), + actualDev); + goto out; + } + + /* Find the matching PF from the list of netdef->forwardIfs + * Search through the ForwardVfs list of the PF to find the VF + */ + for (ii = 0; ii < netdef->nForwardIfs; ii++) { + if (STREQ(pfDeviceName, netdef->forwardIfs[ii].dev)) { + for (jj = 0; jj < netdef->forwardIfs[ii].nForwardVfs; jj++) { + if (STREQ(actualDev, netdef->forwardIfs[ii].forwardVfs[jj].dev)) { + dev = &netdef->forwardIfs[ii].forwardVfs[jj]; + break; + } + } + } } } + else if (isVf == 0) { + /*If the actual dev is a PF do the following code*/ + for (ii = 0; ii < netdef->nForwardIfs; ii++) { + if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) { + dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[ii]; + break; + } + } + } + else { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not find whether %s is PF or VF"), + actualDev); + goto out; + } + + out: + /* dev points at the physical device we want to use */ if (!dev) { networkReportError(VIR_ERR_INTERNAL_ERROR, @@ -2953,7 +3068,7 @@ networkNotifyActualDevice(virDomainNetDefPtr iface) netdef->name, actualDev); goto cleanup; } - + /* PASSTHROUGH mode, and PRIVATE Mode + 802.1Qbh both require * exclusive access to a device, so current usageCount must be * 0 in those cases. @@ -3036,15 +3151,50 @@ networkReleaseActualDevice(virDomainNetDefPtr iface) netdef->name); goto cleanup; } else { - int ii; - virNetworkForwardIfDefPtr dev = NULL; - - for (ii = 0; ii < netdef->nForwardIfs; ii++) { - if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) { - dev = &netdef->forwardIfs[ii]; - break; + int ii, jj, isVf; + virNetworkForwardVfDefPtr dev = NULL; + char *pfDeviceName; + + isVf = virNetDevIsVirtualFunction(actualDev); + + if (isVf == 1) { + /*If Vf get PF */ + if ((virNetDevGetPhysicalFunction(actualDev, &pfDeviceName)) < 0) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get Physical functions for %s"), + actualDev); + goto out; } + + /* Find the matching PF from the list of netdef->forwardIfs + * search through the ForwardVfs list of the PF to find the VF + */ + for (ii = 0; ii < netdef->nForwardIfs; ii++) { + if (STREQ(pfDeviceName, netdef->forwardIfs[ii].dev)) { + for (jj = 0; jj < netdef->forwardIfs[ii].nForwardVfs; jj++) { + if (STREQ(actualDev, netdef->forwardIfs[ii].forwardVfs[jj].dev)) { + dev = &netdef->forwardIfs[ii].forwardVfs[jj]; + break; + } + } + } + } + } + else if (isVf == 0) { + for (ii = 0; ii < netdef->nForwardIfs; ii++) { + if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) { + dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[ii]; + break; + } + } + } + else { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not find whether %s is PF or VF"), + actualDev); + goto out; } + out: /* dev points at the physical device we've been using */ if (!dev) { networkReportError(VIR_ERR_INTERNAL_ERROR, -- 1.7.4.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list