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(a)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