[libvirt] [PATCH 4/8] ActualParent is used to store the information about the NETDEV.

Shradha Shah sshah at solarflare.com
Fri Sep 7 16:15:43 UTC 2012


The parent type for hostdev hybrid needs to be VIR_DOMAIN_DEVICE_NONE as the device is passed into
the guest as a PCI Device.
In order to store the information of the NETDEV that is the parent of the HOSTDEV in question we
use a new variable actualParent. This variable also helps during VF MAC address, vlan and
virtportprofile configuration.

ActualParent = Parent in case of forward mode="hostdev"
---
 src/conf/domain_conf.c  |    9 +++
 src/conf/domain_conf.h  |    1 +
 src/qemu/qemu_hostdev.c |  152 +++++++++++++++++++++++++++++++++--------------
 src/qemu/qemu_hotplug.c |    2 +-
 4 files changed, 118 insertions(+), 46 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c59ea00..52c00db 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4587,6 +4587,8 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
 
         hostdev->parent.type = VIR_DOMAIN_DEVICE_NET;
         hostdev->parent.data.net = parent;
+        hostdev->actualParent.type = VIR_DOMAIN_DEVICE_NET;
+        hostdev->actualParent.data.net = parent;
         hostdev->info = &parent->info;
         /* The helper function expects type to already be found and
          * passed in as a string, since it is in a different place in
@@ -4607,6 +4609,9 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
         virDomainHostdevDefPtr hostdev = &actual->data.hostdev.def;
 
         hostdev->parent.type = VIR_DOMAIN_DEVICE_NONE;
+        hostdev->actualParent.type = VIR_DOMAIN_DEVICE_NET;
+        hostdev->actualParent.data.net = parent;
+
         if (VIR_ALLOC(hostdev->info) < 0) {
             virReportOOMError();
             goto error;
@@ -4990,6 +4995,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
         hostdev = &def->data.hostdev.def;
         hostdev->parent.type = VIR_DOMAIN_DEVICE_NET;
         hostdev->parent.data.net = def;
+        hostdev->actualParent.type = VIR_DOMAIN_DEVICE_NET;
+        hostdev->actualParent.data.net = def;
         hostdev->info = &def->info;
         /* The helper function expects type to already be found and
          * passed in as a string, since it is in a different place in
@@ -5011,6 +5018,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
     case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
         hostdev = &def->data.hostdev.def;
         hostdev->parent.type = VIR_DOMAIN_DEVICE_NONE;
+        hostdev->actualParent.type = VIR_DOMAIN_DEVICE_NET;
+        hostdev->actualParent.data.net = def;
         if (VIR_ALLOC(hostdev->info) < 0) {
             virReportOOMError();
             goto error;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 171dd70..adbb777 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -377,6 +377,7 @@ struct _virDomainHostdevSubsys {
 /* basic device for direct passthrough */
 struct _virDomainHostdevDef {
     virDomainDeviceDef parent; /* higher level Def containing this */
+    virDomainDeviceDef actualParent; /*used only in the case of hybrid hostdev*/
     int mode; /* enum virDomainHostdevMode */
     unsigned int managed : 1;
     unsigned int ephemeral : 1;
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index 46c84b5..a060a7e 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -320,43 +320,87 @@ qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev,
     if (qemuDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
         return ret;
 
-    vlan = virDomainNetGetActualVlan(hostdev->parent.data.net);
-    virtPort = virDomainNetGetActualVirtPortProfile(
-                                 hostdev->parent.data.net);
-    if (virtPort) {
-        if (vlan) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("direct setting of the vlan tag is not allowed "
-                             "for hostdev devices using %s mode"),
-                           virNetDevVPortTypeToString(virtPort->virtPortType));
-            goto cleanup;
-        }
-        ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf,
-                            virtPort, &hostdev->parent.data.net->mac, uuid,
-                            port_profile_associate);
-    } else {
-        /* Set only mac and vlan */
-        if (vlan) {
-            if (vlan->nTags != 1 || vlan->trunk) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                               _("vlan trunking is not supported "
-                                 "by SR-IOV network devices"));
+    if (hostdev->parent.data.net) {
+        vlan = virDomainNetGetActualVlan(hostdev->parent.data.net);
+        virtPort = virDomainNetGetActualVirtPortProfile(hostdev->parent.data.net);
+        if (virtPort) {
+            if (vlan) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("direct setting of the vlan tag is not allowed "
+                                 "for hostdev devices using %s mode"),
+                               virNetDevVPortTypeToString(virtPort->virtPortType));
                 goto cleanup;
             }
-            if (vf == -1) {
+            ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf,
+                                                            virtPort,
+                                                            &hostdev->parent.data.net->mac,
+                                                            uuid,
+                                                            port_profile_associate);
+        } else {
+            /* Set only mac and vlan */
+            if (vlan) {
+                if (vlan->nTags != 1 || vlan->trunk) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                                   _("vlan trunking is not supported "
+                                     "by SR-IOV network devices"));
+                    goto cleanup;
+                }
+                if (vf == -1) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                   _("vlan can only be set for SR-IOV VFs, but "
+                                     "%s is not a VF"), linkdev);
+                    goto cleanup;
+                }
+                vlanid = vlan->tag[0];
+            } else  if (vf >= 0) {
+                vlanid = 0; /* assure any current vlan tag is reset */
+            }
+
+            ret = virNetDevReplaceNetConfig(linkdev, vf,
+                                            &hostdev->parent.data.net->mac,
+                                            vlanid, stateDir);
+        }
+    }
+    else if (hostdev->actualParent.data.net) {
+       vlan = virDomainNetGetActualVlan(hostdev->actualParent.data.net);
+        virtPort = virDomainNetGetActualVirtPortProfile(hostdev->actualParent.data.net);
+        if (virtPort) {
+            if (vlan) {
                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                               _("vlan can only be set for SR-IOV VFs, but "
-                                 "%s is not a VF"), linkdev);
+                               _("direct setting of the vlan tag is not allowed "
+                                 "for hostdev devices using %s mode"),
+                               virNetDevVPortTypeToString(virtPort->virtPortType));
                 goto cleanup;
             }
-            vlanid = vlan->tag[0];
-        } else  if (vf >= 0) {
-            vlanid = 0; /* assure any current vlan tag is reset */
-        }
+            ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf,
+                                                            virtPort,
+                                                            &hostdev->actualParent.data.net->mac,
+                                                            uuid,
+                                                            port_profile_associate);
+        } else {
+            /* Set only mac and vlan */
+            if (vlan) {
+                if (vlan->nTags != 1 || vlan->trunk) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                                   _("vlan trunking is not supported "
+                                     "by SR-IOV network devices"));
+                    goto cleanup;
+                }
+                if (vf == -1) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                   _("vlan can only be set for SR-IOV VFs, but "
+                                     "%s is not a VF"), linkdev);
+                    goto cleanup;
+                }
+                vlanid = vlan->tag[0];
+            } else  if (vf >= 0) {
+                vlanid = 0; /* assure any current vlan tag is reset */
+            }
 
-        ret = virNetDevReplaceNetConfig(linkdev, vf,
-                                        &hostdev->parent.data.net->mac,
-                                        vlanid, stateDir);
+            ret = virNetDevReplaceNetConfig(linkdev, vf,
+                                            &hostdev->actualParent.data.net->mac,
+                                            vlanid, stateDir);
+        }
     }
 cleanup:
     VIR_FREE(linkdev);
@@ -385,14 +429,26 @@ qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
     if (qemuDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
         return ret;
 
-    virtPort = virDomainNetGetActualVirtPortProfile(
-                                 hostdev->parent.data.net);
-    if (virtPort)
-        ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort,
-                                          &hostdev->parent.data.net->mac, NULL,
-                                          port_profile_associate);
-    else
-        ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir);
+    if (hostdev->parent.data.net) {
+        virtPort = virDomainNetGetActualVirtPortProfile(hostdev->parent.data.net);
+        if (virtPort)
+            ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort,
+                                                            &hostdev->parent.data.net->mac,
+                                                            NULL,
+                                                            port_profile_associate);
+        else
+            ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir);
+    }
+    if (hostdev->actualParent.data.net) {
+        virtPort = virDomainNetGetActualVirtPortProfile(hostdev->actualParent.data.net);
+        if (virtPort)
+            ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort,
+                                                            &hostdev->actualParent.data.net->mac,
+                                                            NULL,
+                                                            port_profile_associate);
+        else
+            ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir);
+    }
 
     VIR_FREE(linkdev);
 
@@ -478,8 +534,10 @@ int qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
              continue;
          if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
              continue;
-         if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
-             hostdev->parent.data.net) {
+         if ((hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
+              hostdev->parent.data.net) ||
+             (hostdev->actualParent.type == VIR_DOMAIN_DEVICE_NET &&
+              hostdev->actualParent.data.net)) {
              if (qemuDomainHostdevNetConfigReplace(hostdev, uuid,
                                                    driver->stateDir) < 0) {
                  goto resetvfnetconfig;
@@ -568,8 +626,10 @@ inactivedevs:
 resetvfnetconfig:
     for (i = 0; i < last_processed_hostdev_vf; i++) {
          virDomainHostdevDefPtr hostdev = hostdevs[i];
-         if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
-             hostdev->parent.data.net) {
+         if ((hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
+              hostdev->parent.data.net) ||
+             (hostdev->actualParent.type == VIR_DOMAIN_DEVICE_NET &&
+              hostdev->actualParent.data.net)) {
              qemuDomainHostdevNetConfigRestore(hostdev, driver->stateDir);
          }
     }
@@ -827,8 +887,10 @@ void qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
              continue;
          if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
              continue;
-         if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
-             hostdev->parent.data.net) {
+         if ((hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
+             hostdev->parent.data.net) ||
+             (hostdev->actualParent.type == VIR_DOMAIN_DEVICE_NET &&
+              hostdev->actualParent.data.net)) {
              qemuDomainHostdevNetConfigRestore(hostdev, driver->stateDir);
          }
     }
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index a8a904c..e8860f3 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1996,7 +1996,7 @@ qemuDomainDetachHostPciDevice(struct qemud_driver *driver,
      * For SRIOV net host devices, unset mac and port profile before
      * reset and reattach device
      */
-     if (detach->parent.data.net)
+    if (detach->parent.data.net || detach->actualParent.data.net)
          qemuDomainHostdevNetConfigRestore(detach, driver->stateDir);
 
     pci = pciGetDevice(subsys->u.pci.domain, subsys->u.pci.bus,
-- 
1.7.4.4





More information about the libvir-list mailing list