---
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