[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 5/5] If a system has 64 or more VF's, it is quite tedious to mention each VF in the interface pool. The following modification find a Free VF given a Physical Function when mode=passthrough. We also save the state of each VF. Hence modifications to networkAllocateActualDevice, networkNotifyActualDevice and networkReleaseActualDevice were required. The following patch does just that.



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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]