[libvirt] [PATCH 12/15] Hostdev-hybrid network driver Implementation

Shradha Shah sshah at solarflare.com
Fri Aug 10 16:26:54 UTC 2012


This patch updates the network driver to properly utilize the new
attributes/elements that are now in virNetworkDef
---
 src/network/bridge_driver.c |  139 +++++++++++++++++++++++++++++++++++++-----
 1 files changed, 122 insertions(+), 17 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 33bc09e..457716c 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1934,9 +1934,9 @@ networkStartNetworkExternal(struct network_driver *driver ATTRIBUTE_UNUSED,
                             virNetworkObjPtr network ATTRIBUTE_UNUSED)
 {
     /* 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.
+     * type BRIDGE, PRIVATE, VEPA, HOSTDEV, HOSTDEV-HYBRID or PASSTHROUGH 
+     * is started. On failure, undo anything you've done, and return -1. 
+     * On success return 0.
      */
     return 0;
 }
@@ -1945,9 +1945,9 @@ static int networkShutdownNetworkExternal(struct network_driver *driver ATTRIBUT
                                         virNetworkObjPtr network ATTRIBUTE_UNUSED)
 {
     /* put anything here that needs to be done each time a network of
-     * type BRIDGE, PRIVATE, VEPA, HOSTDEV or PASSTHROUGH is shutdown. On
-     * failure, undo anything you've done, and return -1. On success
-     * return 0.
+     * type BRIDGE, PRIVATE, VEPA, HOSTDEV, HOSTDEV-HYBRID or PASSTHROUGH 
+     * is shutdown. On failure, undo anything you've done, and return -1. 
+     * On success return 0.
      */
     return 0;
 }
@@ -1977,6 +1977,7 @@ networkStartNetwork(struct network_driver *driver,
     case VIR_NETWORK_FORWARD_VEPA:
     case VIR_NETWORK_FORWARD_PASSTHROUGH:
     case VIR_NETWORK_FORWARD_HOSTDEV:
+    case VIR_NETWORK_FORWARD_HOSTDEV_HYBRID:
         ret = networkStartNetworkExternal(driver, network);
         break;
     }
@@ -2037,6 +2038,7 @@ static int networkShutdownNetwork(struct network_driver *driver,
     case VIR_NETWORK_FORWARD_VEPA:
     case VIR_NETWORK_FORWARD_PASSTHROUGH:
     case VIR_NETWORK_FORWARD_HOSTDEV:
+    case VIR_NETWORK_FORWARD_HOSTDEV_HYBRID:
         ret = networkShutdownNetworkExternal(driver, network);
         break;
     }
@@ -2780,7 +2782,8 @@ networkCreateInterfacePool(virNetworkDefPtr netdef) {
                 goto finish;
             }
         }
-        if (netdef->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) {
+        if (netdef->forwardType == VIR_NETWORK_FORWARD_HOSTDEV ||
+            netdef->forwardType == VIR_NETWORK_FORWARD_HOSTDEV_HYBRID) {
             netdef->forwardIfs[ii].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI; /*Assuming PCI as VF's are PCI devices */
             netdef->forwardIfs[ii].device.pci.domain = virt_fns[ii]->domain;
             netdef->forwardIfs[ii].device.pci.bus = virt_fns[ii]->bus;
@@ -2925,6 +2928,8 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
         }
         iface->data.network.actual->data.hostdev.def.parent.type = VIR_DOMAIN_DEVICE_NET;
         iface->data.network.actual->data.hostdev.def.parent.data.net = iface;
+        iface->data.network.actual->data.hostdev.def.actualParent.type = VIR_DOMAIN_DEVICE_NET;
+        iface->data.network.actual->data.hostdev.def.actualParent.data.net = iface;
         iface->data.network.actual->data.hostdev.def.info = &iface->info;
         iface->data.network.actual->data.hostdev.def.mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
         iface->data.network.actual->data.hostdev.def.managed = netdef->managed;
@@ -2958,6 +2963,97 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
                   dev->device.pci.function,
                   dev->usageCount);
         
+    } else if (netdef->forwardType == VIR_NETWORK_FORWARD_HOSTDEV_HYBRID) {
+        char *pfname = NULL;
+        if (!iface->data.network.actual
+            && (VIR_ALLOC(iface->data.network.actual) < 0)) {
+            virReportOOMError();
+            goto cleanup;
+        }
+        iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID;
+
+        if ((netdef->nForwardPfs > 0) && (netdef->nForwardIfs <= 0)) {
+            if(networkCreateInterfacePool(netdef) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Could not create Interface Pool from PF"));
+                goto cleanup;
+            }
+        }
+        /* pick first dev with 0 usageCount */
+        
+        for (ii = 0; ii < netdef->nForwardIfs; ii++) {
+            if (netdef->forwardIfs[ii].usageCount == 0) {
+                dev = &netdef->forwardIfs[ii];
+                break;
+            }
+        }
+        if (!dev) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("network '%s' requires exclusive access to interfaces, but none are available"),
+                           netdef->name);
+            goto cleanup;
+        }
+        iface->data.network.actual->data.hostdev.def.parent.type = VIR_DOMAIN_DEVICE_NONE;
+        iface->data.network.actual->data.hostdev.def.actualParent.type = VIR_DOMAIN_DEVICE_NET;
+        iface->data.network.actual->data.hostdev.def.actualParent.data.net = iface;
+        
+        if (VIR_ALLOC(iface->data.network.actual->data.hostdev.def.info) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+        iface->data.network.actual->data.hostdev.def.ephemeral = 1;
+        
+        iface->data.network.actual->data.hostdev.def.mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
+        iface->data.network.actual->data.hostdev.def.managed = netdef->managed;
+        iface->data.network.actual->data.hostdev.def.source.subsys.type = dev->type;
+        iface->data.network.actual->data.hostdev.def.source.subsys.u.pci = dev->device.pci;
+        
+        if (virNetDevGetPhysicalFunctionFromVfPciAddr(dev->device.pci.domain,
+                                                      dev->device.pci.bus,
+                                                      dev->device.pci.slot,
+                                                      dev->device.pci.function,
+                                                      &pfname) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Could not get Physical function of the selected VF"));
+            goto cleanup;
+        }
+        
+        if (pfname != NULL)
+            iface->data.network.actual->data.hostdev.linkdev = strdup(pfname);
+        else {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Linkdev is required in hostdev-hybrid mode"));
+            goto cleanup;
+        }
+        iface->data.network.actual->data.hostdev.mode = VIR_NETDEV_MACVLAN_MODE_BRIDGE;
+        
+        if (iface->data.network.virtPortProfile) {
+            virtport = iface->data.network.virtPortProfile;
+        } else {
+            if (portgroup)
+                virtport = portgroup->virtPortProfile;
+            else
+                virtport = netdef->virtPortProfile;
+        }
+        if (virtport) {
+            if (VIR_ALLOC(iface->data.network.actual->data.hostdev.virtPortProfile) < 0) {
+                virReportOOMError();
+                goto cleanup;
+            }
+            /* There are no pointers in a virtualPortProfile, so a shallow copy
+             * is sufficient
+             */
+            *iface->data.network.actual->data.direct.virtPortProfile = *virtport;
+        }
+
+        dev->usageCount++;
+        VIR_DEBUG("Using physical device with domain=%d bus=%d slot=%d function=%d, usageCount %d",
+                  dev->device.pci.domain,
+                  dev->device.pci.bus,
+                  dev->device.pci.slot,
+                  dev->device.pci.function,
+                  dev->usageCount);
+       
     } else if ((netdef->forwardType == VIR_NETWORK_FORWARD_BRIDGE) ||
                (netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE) ||
                (netdef->forwardType == VIR_NETWORK_FORWARD_VEPA) ||
@@ -3121,7 +3217,8 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
 
     if (!iface->data.network.actual ||
         ((virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_DIRECT) &&
-         (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_HOSTDEV))) {
+         (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_HOSTDEV) &&
+         (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID))) {
         VIR_DEBUG("Nothing to claim from network %s", iface->data.network.name);
         return 0;
     }
@@ -3145,7 +3242,8 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
         }
     }
     
-    if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+    if ((virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+        (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) {
         def = virDomainNetGetActualHostdev(iface);
         if (!def) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -3174,7 +3272,8 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
             }
         }
 
-        if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+        if ((virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+            (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) {
             if ((netdef->nForwardPfs > 0) && (netdef->nForwardIfs <= 0)) {
                 if(networkCreateInterfacePool(netdef) < 0) {
                     virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -3201,13 +3300,14 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
             goto cleanup;
         }
 
-        /* PASSTHROUGH mode, HOSTDEV mode and PRIVATE Mode + 802.1Qbh both require
-         * exclusive access to a device, so current usageCount must be
+        /* PASSTHROUGH mode, HOSTDEV mode, HOSTDEV-HYBRIDand PRIVATE Mode + 802.1Qbh 
+         * both require exclusive access to a device, so current usageCount must be
          * 0 in those cases.
          */
         if ((dev->usageCount > 0) &&
             ((netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) ||
              (netdef->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) || 
+             (netdef->forwardType == VIR_NETWORK_FORWARD_HOSTDEV_HYBRID) ||
              ((netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE) &&
               iface->data.network.actual->data.direct.virtPortProfile &&
               (iface->data.network.actual->data.direct.virtPortProfile->virtPortType
@@ -3223,7 +3323,8 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
             VIR_DEBUG("Using physical device %s, usageCount %d",
                       dev->device.dev, dev->usageCount);
         }
-        if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+        if ((virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+            (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) { 
             VIR_DEBUG("Using physical device with domain=%d bus=%d slot=%d function=%d, usageCount %d",
                       dev->device.pci.domain,
                       dev->device.pci.bus,
@@ -3266,7 +3367,8 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
 
     if (!iface->data.network.actual ||
         ((virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_DIRECT) &&
-         (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_HOSTDEV))) {
+         (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_HOSTDEV) &&
+         (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID))) {
         VIR_DEBUG("Nothing to release to network %s", iface->data.network.name);
         ret = 0;
         goto cleanup;
@@ -3291,7 +3393,8 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
         }
     }
     
-    if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+    if ((virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+        (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) {
         def = virDomainNetGetActualHostdev(iface);
         if (!def) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -3320,7 +3423,8 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
             }
         }
         
-        if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+        if ((virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+            (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) {
             for (ii = 0; ii < netdef->nForwardIfs; ii++) {
                 if((def->source.subsys.u.pci.domain == netdef->forwardIfs[ii].device.pci.domain) &&
                    (def->source.subsys.u.pci.bus == netdef->forwardIfs[ii].device.pci.bus) &&
@@ -3345,7 +3449,8 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
             VIR_DEBUG("Releasing physical device %s, usageCount %d",
                       dev->device.dev, dev->usageCount);
         }
-        if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+        if ((virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+            (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) {
             VIR_DEBUG("Releasing physical device with domain=%d bus=%d slot=%d function=%d, usageCount %d",
                       dev->device.pci.domain,
                       dev->device.pci.bus,
-- 
1.7.4.4





More information about the libvir-list mailing list