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

Shradha Shah sshah at solarflare.com
Fri Nov 25 16:55:08 UTC 2011


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




More information about the libvir-list mailing list