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

[libvirt] [RFC 3/7] hostdev: add a 'bond' type element in <hostdev> element



this 'bond' element is to create bond device when guest startup,
the xml like:
<hostdev mode='subsystem' type='pci' managed='yes'>
    <driver name='vfio' type='bond'/>
    <bond>
      <interface address='XXX'/>
      <interface address='XXX1'/>
    </bond>
</hostdev>

Signed-off-by: Chen Fan <chen fan fnst cn fujitsu com>
---
 docs/schemas/basictypes.rng   |   6 ++
 docs/schemas/domaincommon.rng |  16 ++++++
 src/conf/domain_conf.c        | 131 ++++++++++++++++++++++++++++++++++++++----
 src/conf/domain_conf.h        |  13 +++++
 src/libvirt_private.syms      |   1 +
 5 files changed, 157 insertions(+), 10 deletions(-)

diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
index f086ad2..aef24fe 100644
--- a/docs/schemas/basictypes.rng
+++ b/docs/schemas/basictypes.rng
@@ -66,6 +66,12 @@
     </choice>
   </define>
 
+  <define name="pciinterface">
+    <attribute name="address">
+      <ref name="uniMacAddr"/>
+    </attribute>
+  </define>
+
   <define name="pciaddress">
     <optional>
       <attribute name="domain">
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 03fd541..0cf82cb 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3766,9 +3766,25 @@
               <value>xen</value>
             </choice>
           </attribute>
+          <optional>
+            <attribute name="type">
+              <choice>
+                <value>bond</value>
+              </choice>
+            </attribute>
+          </optional>
           <empty/>
         </element>
       </optional>
+      <optional>
+        <element name="bond">
+          <zeroOrMore>
+            <element name="interface">
+              <ref name="pciinterface"/>
+            </element>
+          </zeroOrMore>
+        </element>
+      </optional>
       <element name="source">
         <optional>
           <ref name="startupPolicy"/>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 4d7e3c9..14bcae1 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -610,6 +610,11 @@ VIR_ENUM_IMPL(virDomainHostdevSubsysPCIBackend,
               "vfio",
               "xen")
 
+VIR_ENUM_IMPL(virDomainHostdevSubsysPCIDevice,
+              VIR_DOMAIN_HOSTDEV_PCI_DEVICE_TYPE_LAST,
+              "default",
+              "bond")
+
 VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIProtocol,
               VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_LAST,
               "adapter",
@@ -1907,6 +1912,10 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
             } else {
                 VIR_FREE(scsisrc->u.host.adapter);
             }
+        } else if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+            virDomainHostdevSubsysPCIPtr pcisrc = &def->source.subsys.u.pci;
+            if (pcisrc->device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND)
+                VIR_FREE(pcisrc->macs);
         }
         break;
     }
@@ -4978,7 +4987,9 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
     char *sgio = NULL;
     char *rawio = NULL;
     char *backendStr = NULL;
+    char *deviceStr = NULL;
     int backend;
+    int device;
     int ret = -1;
     virDomainHostdevSubsysPCIPtr pcisrc = &def->source.subsys.u.pci;
     virDomainHostdevSubsysSCSIPtr scsisrc = &def->source.subsys.u.scsi;
@@ -5077,6 +5088,68 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
         }
         pcisrc->backend = backend;
 
+        device =  VIR_DOMAIN_HOSTDEV_PCI_DEVICE_DEFAULT;
+        if ((deviceStr = virXPathString("string(./driver/@type)", ctxt)) &&
+            (((device = virDomainHostdevSubsysPCIDeviceTypeFromString(deviceStr)) < 0) ||
+             device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_DEFAULT)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("Unknown PCI device <driver type='%s'/> "
+                             "has been specified"), deviceStr);
+            goto error;
+        }
+        pcisrc->device = device;
+
+        if (device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) {
+            xmlNodePtr *macs = NULL;
+            int n = 0;
+            int i;
+            char *macStr = NULL;
+
+            if (!(virXPathNode("./bond", ctxt))) {
+                virReportError(VIR_ERR_XML_ERROR, "%s",
+                               _("missing <nond> node specified by bond type"));
+                goto error;
+            }
+
+            if ((n = virXPathNodeSet("./bond/interface", ctxt, &macs)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Cannot extract interface nodes"));
+                goto error;
+            }
+
+            VIR_FREE(pcisrc->macs);
+            if (VIR_ALLOC_N(pcisrc->macs, n) < 0)
+                goto error;
+
+            pcisrc->nmac = n;
+            for (i = 0; i < n; i++) {
+                xmlNodePtr cur_node = macs[i];
+
+                macStr = virXMLPropString(cur_node, "address");
+                if (!macStr) {
+                    virReportError(VIR_ERR_XML_ERROR, "%s",
+                                   _("Missing required address attribute "
+                                   "in interface element"));
+                    goto error;
+                }
+                if (virMacAddrParse((const char *)macStr, &pcisrc->macs[i]) < 0) {
+                    virReportError(VIR_ERR_XML_ERROR,
+                                   _("unable to parse mac address '%s'"),
+                                   (const char *)macStr);
+                    VIR_FREE(macStr);
+                    goto error;
+                }
+                if (virMacAddrIsMulticast(&pcisrc->macs[i])) {
+                    virReportError(VIR_ERR_XML_ERROR,
+                                   _("expected unicast mac address, found multicast '%s'"),
+                                   (const char *)macStr);
+                    VIR_FREE(macStr);
+                    goto error;
+                }
+                VIR_FREE(macStr);
+            }
+        }
+
         break;
 
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
@@ -18389,18 +18462,56 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
     virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
     virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
 
-    if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
-        pcisrc->backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) {
-        const char *backend =
-            virDomainHostdevSubsysPCIBackendTypeToString(pcisrc->backend);
+    if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+        const char *backend = NULL;
+        const char *device = NULL;
+        int i;
+        char macstr[VIR_MAC_STRING_BUFLEN];
 
-        if (!backend) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("unexpected pci hostdev driver name type %d"),
-                           pcisrc->backend);
-            return -1;
+        if (pcisrc->backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) {
+            backend =
+                virDomainHostdevSubsysPCIBackendTypeToString(pcisrc->backend);
+
+            if (!backend) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unexpected pci hostdev driver name type %d"),
+                               pcisrc->backend);
+                return -1;
+            }
+        }
+
+        if (pcisrc->device != VIR_DOMAIN_HOSTDEV_PCI_DEVICE_DEFAULT) {
+            device =
+                virDomainHostdevSubsysPCIDeviceTypeToString(pcisrc->device);
+
+            if (!device) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unexpected pci hostdev device name type %d"),
+                               pcisrc->device);
+                return -1;
+            }
+        }
+
+        if (backend) {
+            virBufferAddLit(buf, "<driver");
+            virBufferAsprintf(buf, " name='%s'", backend);
+            if (device)
+                virBufferAsprintf(buf, " type='%s'", device);
+
+            virBufferAddLit(buf, "/>\n");
+        }
+
+        if (pcisrc->device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND &&
+            pcisrc->nmac > 0) {
+            virBufferAddLit(buf, "<bond>\n");
+            virBufferAdjustIndent(buf, 2);
+            for (i = 0; i < pcisrc->nmac; i++) {
+                virBufferAsprintf(buf, "<interface address='%s'/>\n",
+                                  virMacAddrFormat(&pcisrc->macs[i], macstr));
+            }
+            virBufferAdjustIndent(buf, -2);
+            virBufferAddLit(buf, "</bond>\n");
         }
-        virBufferAsprintf(buf, "<driver name='%s'/>\n", backend);
     }
 
     virBufferAddLit(buf, "<source");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e6fa3c9..e62979f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -416,6 +416,16 @@ typedef enum {
 
 VIR_ENUM_DECL(virDomainHostdevSubsysPCIBackend)
 
+/* the type used for PCI hostdev devices */
+typedef enum {
+    VIR_DOMAIN_HOSTDEV_PCI_DEVICE_DEFAULT, /* default */
+    VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND,    /* bond device */
+
+    VIR_DOMAIN_HOSTDEV_PCI_DEVICE_TYPE_LAST
+} virDomainHostdevSubsysPCIDeviceType;
+
+VIR_ENUM_DECL(virDomainHostdevSubsysPCIDevice)
+
 typedef enum {
     VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_NONE,
     VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI,
@@ -442,6 +452,9 @@ typedef virDomainHostdevSubsysPCI *virDomainHostdevSubsysPCIPtr;
 struct _virDomainHostdevSubsysPCI {
     virDevicePCIAddress addr; /* host address */
     int backend; /* enum virDomainHostdevSubsysPCIBackendType */
+    int device;  /* enum virDomainHostdevSubsysPCIDeviceType */
+    size_t nmac;
+    virMacAddr* macs;
 };
 
 typedef struct _virDomainHostdevSubsysSCSIHost virDomainHostdevSubsysSCSIHost;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index aafc385..43a769d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -320,6 +320,7 @@ virDomainHostdevInsert;
 virDomainHostdevModeTypeToString;
 virDomainHostdevRemove;
 virDomainHostdevSubsysPCIBackendTypeToString;
+virDomainHostdevSubsysPCIDeviceTypeToString;
 virDomainHostdevSubsysTypeToString;
 virDomainHubTypeFromString;
 virDomainHubTypeToString;
-- 
1.9.3


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