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@xxxxxxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list