[libvirt] [PATCH 0/6 v2] Support forward mode='hostdev' and interface pools
This patch series supports the forward mode='hostdev'. The functionality of this mode is the same as interface type='hostdev' but with the added benefit of using interface pools. The patch series also contains a patch to support use of interface names and PCI device addresses interchangeably in a network xml, and return the appropriate one in actualDevice when networkAllocateActualDevice is called. At the top level managed attribute can be specified with identical results as when it's specified for a hostdev. Currently forward mode='hostdev' does not support USB devices. Shradha Shah (6): Prerequisite Patch. virDomainDevicePCIAddress and respective functions moved to a new file called conf/device_conf.ch Moved the code to create implicit interface pool from PF to a new function RNG updates, new xml parser/formatter code to support forward mode=hostdev Code to return interface name or pci_addr of the VF in actualDevice Forward Mode Hostdev network driver Implementation Forward Mode 'Hostdev' qemu driver implementation docs/formatnetwork.html.in | 62 ++++++ docs/schemas/network.rng | 82 ++++++++- src/Makefile.am | 7 +- src/conf/device_conf.c | 135 +++++++++++++ src/conf/device_conf.h | 65 +++++++ src/conf/domain_conf.c | 114 ++---------- src/conf/domain_conf.h | 25 +--- src/conf/network_conf.c | 126 +++++++++++-- src/conf/network_conf.h | 29 +++- src/libvirt_private.syms | 10 +- src/network/bridge_driver.c | 322 +++++++++++++++++++++++++------- src/qemu/qemu_command.c | 27 ++- src/qemu/qemu_hotplug.c | 7 +- src/qemu/qemu_monitor.c | 14 +- src/qemu/qemu_monitor.h | 17 +- src/qemu/qemu_monitor_json.c | 14 +- src/qemu/qemu_monitor_json.h | 14 +- src/qemu/qemu_monitor_text.c | 16 +- src/qemu/qemu_monitor_text.h | 14 +- src/util/virnetdev.c | 29 ++-- src/util/virnetdev.h | 4 +- src/xen/xend_internal.c | 3 +- tests/networkxml2xmlin/hostdev-pf.xml | 11 + tests/networkxml2xmlin/hostdev.xml | 10 + tests/networkxml2xmlout/hostdev-pf.xml | 7 + tests/networkxml2xmlout/hostdev.xml | 10 + tests/networkxml2xmltest.c | 2 + 27 files changed, 889 insertions(+), 287 deletions(-) create mode 100644 src/conf/device_conf.c create mode 100644 src/conf/device_conf.h create mode 100644 tests/networkxml2xmlin/hostdev-pf.xml create mode 100644 tests/networkxml2xmlin/hostdev.xml create mode 100644 tests/networkxml2xmlout/hostdev-pf.xml create mode 100644 tests/networkxml2xmlout/hostdev.xml -- 1.7.4.4
Refactoring existing code without causing any functional changes to prepare for new code. This patch makes the code reusable. Signed-off-by: Shradha Shah <sshah@solarflare.com> --- src/Makefile.am | 7 ++- src/conf/device_conf.c | 135 ++++++++++++++++++++++++++++++++++++++++++ src/conf/device_conf.h | 65 ++++++++++++++++++++ src/conf/domain_conf.c | 114 ++++------------------------------- src/conf/domain_conf.h | 25 +------- src/libvirt_private.syms | 10 ++- src/qemu/qemu_command.c | 13 ++-- src/qemu/qemu_hotplug.c | 7 +- src/qemu/qemu_monitor.c | 14 ++-- src/qemu/qemu_monitor.h | 17 +++--- src/qemu/qemu_monitor_json.c | 14 ++-- src/qemu/qemu_monitor_json.h | 14 ++-- src/qemu/qemu_monitor_text.c | 16 +++--- src/qemu/qemu_monitor_text.h | 14 ++-- src/xen/xend_internal.c | 3 +- 15 files changed, 288 insertions(+), 180 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index e40909b..009c4e5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -199,6 +199,9 @@ CONSOLE_CONF_SOURCES = \ DOMAIN_LIST_SOURCES = \ conf/virdomainlist.c conf/virdomainlist.h +DEVICE_CONF_SOURCES = \ + conf/device_conf.c conf/device_conf.h + CONF_SOURCES = \ $(NETDEV_CONF_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ @@ -212,7 +215,8 @@ CONF_SOURCES = \ $(SECRET_CONF_SOURCES) \ $(CPU_CONF_SOURCES) \ $(CONSOLE_CONF_SOURCES) \ - $(DOMAIN_LIST_SOURCES) + $(DOMAIN_LIST_SOURCES) \ + $(DEVICE_CONF_SOURCES) # The remote RPC driver, covering domains, storage, networks, etc REMOTE_DRIVER_GENERATED = \ @@ -1525,6 +1529,7 @@ libvirt_lxc_SOURCES = \ $(ENCRYPTION_CONF_SOURCES) \ $(NETDEV_CONF_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ + $(DEVICE_CONF_SOURCES) \ $(SECRET_CONF_SOURCES) \ $(CPU_CONF_SOURCES) \ $(SECURITY_DRIVER_SOURCES) \ diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c new file mode 100644 index 0000000..af21aad --- /dev/null +++ b/src/conf/device_conf.c @@ -0,0 +1,135 @@ +/* + * device_conf.h: device XML handling + * + * Copyright (C) 2006-2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Shradha Shah <sshah@solarflare.com> + */ + +#include <config.h> +#include "virterror_internal.h" +#include "datatypes.h" +#include "memory.h" +#include "xml.h" +#include "uuid.h" +#include "util.h" +#include "buf.h" +#include "conf/device_conf.h" + +#define VIR_FROM_THIS VIR_FROM_DEVICE + +#define virDeviceReportError(code, ...) \ + virReportErrorHelper(VIR_FROM_DOMAIN, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + +VIR_ENUM_IMPL(virDeviceAddressPciMulti, + VIR_DEVICE_ADDRESS_PCI_MULTI_LAST, + "default", + "on", + "off") + +int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr) +{ + /* PCI bus has 32 slots and 8 functions per slot */ + if (addr->slot >= 32 || addr->function >= 8) + return 0; + return addr->domain || addr->bus || addr->slot; +} + + +int +virDevicePCIAddressParseXML(xmlNodePtr node, + virDevicePCIAddressPtr addr) +{ + char *domain, *slot, *bus, *function, *multi; + int ret = -1; + + memset(addr, 0, sizeof(*addr)); + + domain = virXMLPropString(node, "domain"); + bus = virXMLPropString(node, "bus"); + slot = virXMLPropString(node, "slot"); + function = virXMLPropString(node, "function"); + multi = virXMLPropString(node, "multifunction"); + + if (domain && + virStrToLong_ui(domain, NULL, 0, &addr->domain) < 0) { + virDeviceReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'domain' attribute")); + goto cleanup; + } + + if (bus && + virStrToLong_ui(bus, NULL, 0, &addr->bus) < 0) { + virDeviceReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'bus' attribute")); + goto cleanup; + } + + if (slot && + virStrToLong_ui(slot, NULL, 0, &addr->slot) < 0) { + virDeviceReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'slot' attribute")); + goto cleanup; + } + + if (function && + virStrToLong_ui(function, NULL, 0, &addr->function) < 0) { + virDeviceReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'function' attribute")); + goto cleanup; + } + + if (multi && + ((addr->multi = virDeviceAddressPciMultiTypeFromString(multi)) <= 0)) { + virDeviceReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unknown value '%s' for <address> 'multifunction' attribute"), + multi); + goto cleanup; + + } + if (!virDevicePCIAddressIsValid(addr)) { + virDeviceReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Insufficient specification for PCI address")); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(domain); + VIR_FREE(bus); + VIR_FREE(slot); + VIR_FREE(function); + VIR_FREE(multi); + return ret; +} + +int +virDevicePCIAddressFormat(virBufferPtr buf, + virDevicePCIAddress addr, + bool includeTypeInAddr) +{ + virBufferAsprintf(buf, " <address %sdomain='0x%.4x' bus='0x%.2x' " + "slot='0x%.2x' function='0x%.1x'/>\n", + includeTypeInAddr ? "type='pci' " : "", + addr.domain, + addr.bus, + addr.slot, + addr.function); + return 0; +} diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h new file mode 100644 index 0000000..b060798 --- /dev/null +++ b/src/conf/device_conf.h @@ -0,0 +1,65 @@ +/* + * device_conf.h: device XML handling entry points + * + * Copyright (C) 2006-2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Shradha Shah <sshah@solarflare.com> + */ + +#ifndef __DEVICE_CONF_H__ +# define __DEVICE_CONF_H__ + +# include <libxml/parser.h> +# include <libxml/tree.h> +# include <libxml/xpath.h> + +# include "internal.h" +# include "util.h" +# include "threads.h" +# include "buf.h" + +enum virDeviceAddressPciMulti { + VIR_DEVICE_ADDRESS_PCI_MULTI_DEFAULT = 0, + VIR_DEVICE_ADDRESS_PCI_MULTI_ON, + VIR_DEVICE_ADDRESS_PCI_MULTI_OFF, + + VIR_DEVICE_ADDRESS_PCI_MULTI_LAST +}; + +typedef struct _virDevicePCIAddress virDevicePCIAddress; +typedef virDevicePCIAddress *virDevicePCIAddressPtr; +struct _virDevicePCIAddress { + unsigned int domain; + unsigned int bus; + unsigned int slot; + unsigned int function; + int multi; /* enum virDomainDeviceAddressPciMulti */ +}; + +int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr); + +int virDevicePCIAddressParseXML(xmlNodePtr node, + virDevicePCIAddressPtr addr); + +int virDevicePCIAddressFormat(virBufferPtr buf, + virDevicePCIAddress addr, + bool includeTypeInAddr); + + +VIR_ENUM_DECL(virDeviceAddressPciMulti) + +#endif /* __DEVICE_CONF_H__ */ diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f44dc93..7541627 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -53,6 +53,7 @@ #include "netdev_vport_profile_conf.h" #include "netdev_bandwidth_conf.h" #include "virdomainlist.h" +#include "device_conf.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN @@ -152,12 +153,6 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, "usb", "spapr-vio") -VIR_ENUM_IMPL(virDomainDeviceAddressPciMulti, - VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_LAST, - "default", - "on", - "off") - VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, "block", "file", @@ -1904,7 +1899,7 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, switch (info->type) { case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: - return virDomainDevicePCIAddressIsValid(&info->addr.pci); + return virDevicePCIAddressIsValid(&info->addr.pci); case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: return 1; @@ -1916,16 +1911,6 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, return 0; } - -int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr) -{ - /* PCI bus has 32 slots and 8 functions per slot */ - if (addr->slot >= 32 || addr->function >= 8) - return 0; - return addr->domain || addr->bus || addr->slot; -} - - static bool virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info, unsigned int flags) { @@ -2149,7 +2134,7 @@ virDomainDeviceInfoFormat(virBufferPtr buf, info->addr.pci.function); if (info->addr.pci.multi) { virBufferAsprintf(buf, " multifunction='%s'", - virDomainDeviceAddressPciMultiTypeToString(info->addr.pci.multi)); + virDeviceAddressPciMultiTypeToString(info->addr.pci.multi)); } break; @@ -2197,75 +2182,6 @@ virDomainDeviceInfoFormat(virBufferPtr buf, } static int -virDomainDevicePCIAddressParseXML(xmlNodePtr node, - virDomainDevicePCIAddressPtr addr) -{ - char *domain, *slot, *bus, *function, *multi; - int ret = -1; - - memset(addr, 0, sizeof(*addr)); - - domain = virXMLPropString(node, "domain"); - bus = virXMLPropString(node, "bus"); - slot = virXMLPropString(node, "slot"); - function = virXMLPropString(node, "function"); - multi = virXMLPropString(node, "multifunction"); - - if (domain && - virStrToLong_ui(domain, NULL, 0, &addr->domain) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot parse <address> 'domain' attribute")); - goto cleanup; - } - - if (bus && - virStrToLong_ui(bus, NULL, 0, &addr->bus) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot parse <address> 'bus' attribute")); - goto cleanup; - } - - if (slot && - virStrToLong_ui(slot, NULL, 0, &addr->slot) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot parse <address> 'slot' attribute")); - goto cleanup; - } - - if (function && - virStrToLong_ui(function, NULL, 0, &addr->function) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot parse <address> 'function' attribute")); - goto cleanup; - } - - if (multi && - ((addr->multi = virDomainDeviceAddressPciMultiTypeFromString(multi)) <= 0)) { - virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unknown value '%s' for <address> 'multifunction' attribute"), - multi); - goto cleanup; - - } - if (!virDomainDevicePCIAddressIsValid(addr)) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Insufficient specification for PCI address")); - goto cleanup; - } - - ret = 0; - -cleanup: - VIR_FREE(domain); - VIR_FREE(bus); - VIR_FREE(slot); - VIR_FREE(function); - VIR_FREE(multi); - return ret; -} - - -static int virDomainDeviceDriveAddressParseXML(xmlNodePtr node, virDomainDeviceDriveAddressPtr addr) { @@ -2626,7 +2542,7 @@ virDomainDeviceInfoParseXML(xmlNodePtr node, switch (info->type) { case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: - if (virDomainDevicePCIAddressParseXML(address, &info->addr.pci) < 0) + if (virDevicePCIAddressParseXML(address, &info->addr.pci) < 0) goto cleanup; break; @@ -2674,7 +2590,7 @@ cleanup: static int virDomainParseLegacyDeviceAddress(char *devaddr, - virDomainDevicePCIAddressPtr pci) + virDevicePCIAddressPtr pci) { char *tmp; @@ -2859,10 +2775,10 @@ virDomainHostdevSubsysPciDefParseXML(const xmlNodePtr node, while (cur != NULL) { if (cur->type == XML_ELEMENT_NODE) { if (xmlStrEqual(cur->name, BAD_CAST "address")) { - virDomainDevicePCIAddressPtr addr = + virDevicePCIAddressPtr addr = &def->source.subsys.u.pci; - if (virDomainDevicePCIAddressParseXML(cur, addr) < 0) + if (virDevicePCIAddressParseXML(cur, addr) < 0) goto out; } else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) && xmlStrEqual(cur->name, BAD_CAST "state")) { @@ -11427,14 +11343,12 @@ virDomainHostdevSourceFormat(virBufferPtr buf, } break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: - virBufferAsprintf(buf, " <address %sdomain='0x%.4x' bus='0x%.2x' " - "slot='0x%.2x' function='0x%.1x'/>\n", - includeTypeInAddr ? "type='pci' " : "", - def->source.subsys.u.pci.domain, - def->source.subsys.u.pci.bus, - def->source.subsys.u.pci.slot, - def->source.subsys.u.pci.function); - + if (virDevicePCIAddressFormat(buf, + def->source.subsys.u.pci, + includeTypeInAddr) != 0) + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("PCI address Formatting failed")); + if ((flags & VIR_DOMAIN_XML_INTERNAL_PCI_ORIG_STATES) && (def->origstates.states.pci.unbind_from_stub || def->origstates.states.pci.remove_slot || @@ -11447,7 +11361,7 @@ virDomainHostdevSourceFormat(virBufferPtr buf, if (def->origstates.states.pci.reprobe) virBufferAddLit(buf, " <reprobe/>\n"); virBufferAddLit(buf, " </origstates>\n"); - } + } break; default: virDomainReportError(VIR_ERR_INTERNAL_ERROR, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 7d5d60b..51b2da8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -43,6 +43,7 @@ # include "virnetdevvportprofile.h" # include "virnetdevopenvswitch.h" # include "virnetdevbandwidth.h" +# include "device_conf.h" /* forward declarations of all device types, required by * virDomainDeviceDef @@ -176,14 +177,6 @@ enum virDomainDeviceAddressType { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST }; -enum virDomainDeviceAddressPciMulti { - VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_DEFAULT = 0, - VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON, - VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_OFF, - - VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_LAST -}; - enum virDomainPciRombarMode { VIR_DOMAIN_PCI_ROMBAR_DEFAULT = 0, VIR_DOMAIN_PCI_ROMBAR_ON, @@ -192,16 +185,6 @@ enum virDomainPciRombarMode { VIR_DOMAIN_PCI_ROMBAR_LAST }; -typedef struct _virDomainDevicePCIAddress virDomainDevicePCIAddress; -typedef virDomainDevicePCIAddress *virDomainDevicePCIAddressPtr; -struct _virDomainDevicePCIAddress { - unsigned int domain; - unsigned int bus; - unsigned int slot; - unsigned int function; - int multi; /* enum virDomainDeviceAddressPciMulti */ -}; - typedef struct _virDomainDeviceDriveAddress virDomainDeviceDriveAddress; typedef virDomainDeviceDriveAddress *virDomainDeviceDriveAddressPtr; struct _virDomainDeviceDriveAddress { @@ -263,7 +246,7 @@ struct _virDomainDeviceInfo { char *alias; int type; union { - virDomainDevicePCIAddress pci; + virDevicePCIAddress pci; virDomainDeviceDriveAddress drive; virDomainDeviceVirtioSerialAddress vioserial; virDomainDeviceCcidAddress ccid; @@ -374,7 +357,7 @@ struct _virDomainHostdevSubsys { unsigned vendor; unsigned product; } usb; - virDomainDevicePCIAddress pci; /* host address */ + virDevicePCIAddress pci; /* host address */ } u; }; @@ -1891,7 +1874,6 @@ virDomainDeviceDefPtr virDomainDeviceDefCopy(virCapsPtr caps, virDomainDeviceDefPtr src); int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, int type); -int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr); void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); void virDomainDefClearPCIAddresses(virDomainDefPtr def); void virDomainDefClearDeviceAliases(virDomainDefPtr def); @@ -2161,7 +2143,6 @@ VIR_ENUM_DECL(virDomainLifecycle) VIR_ENUM_DECL(virDomainLifecycleCrash) VIR_ENUM_DECL(virDomainDevice) VIR_ENUM_DECL(virDomainDeviceAddress) -VIR_ENUM_DECL(virDomainDeviceAddressPciMulti) VIR_ENUM_DECL(virDomainDisk) VIR_ENUM_DECL(virDomainDiskDevice) VIR_ENUM_DECL(virDomainDiskBus) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2fe5068..0a77130 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -210,6 +210,13 @@ virUnrefStorageVol; virUnrefStream; +# device_conf.h +virDeviceAddressPciMultiTypeFromString; +virDeviceAddressPciMultiTypeToString; +virDevicePCIAddressIsValid; +virDevicePCIAddressParseXML; +virDevicePCIAddressFormat; + # dnsmasq.h dnsmasqAddDhcpHost; dnsmasqAddHost; @@ -286,14 +293,11 @@ virDomainDefParseNode; virDomainDefParseString; virDomainDeleteConfig; virDomainDeviceAddressIsValid; -virDomainDeviceAddressPciMultiTypeFromString; -virDomainDeviceAddressPciMultiTypeToString; virDomainDeviceAddressTypeToString; virDomainDeviceDefCopy; virDomainDeviceDefFree; virDomainDeviceDefParse; virDomainDeviceInfoIterate; -virDomainDevicePCIAddressIsValid; virDomainDeviceTypeToString; virDomainDiskBusTypeToString; virDomainDiskCacheTypeFromString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 6549f57..93c018d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -40,6 +40,7 @@ #include "network/bridge_driver.h" #include "virnetdevtap.h" #include "base64.h" +#include "device_conf.h" #include <sys/utsname.h> #include <sys/stat.h> @@ -909,7 +910,7 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, addr = NULL; if ((info->addr.pci.function == 0) && - (info->addr.pci.multi != VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON)) { + (info->addr.pci.multi != VIR_DEVICE_ADDRESS_PCI_MULTI_ON)) { /* a function 0 w/o multifunction=on must reserve the entire slot */ int function; virDomainDeviceInfo temp_info = *info; @@ -1465,7 +1466,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) /* USB2 needs special handling to put all companions in the same slot */ if (IS_USB2_CONTROLLER(def->controllers[i])) { - virDomainDevicePCIAddress addr = { 0, 0, 0, 0, false }; + virDevicePCIAddress addr = { 0, 0, 0, 0, false }; for (j = 0 ; j < i ; j++) { if (IS_USB2_CONTROLLER(def->controllers[j]) && def->controllers[j]->idx == def->controllers[i]->idx) { @@ -1480,7 +1481,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) break; case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1: addr.function = 0; - addr.multi = VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON; + addr.multi = VIR_DEVICE_ADDRESS_PCI_MULTI_ON; break; case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2: addr.function = 1; @@ -1631,7 +1632,7 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, "are supported with this QEMU binary")); return -1; } - if (info->addr.pci.multi == VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON) { + if (info->addr.pci.multi == VIR_DEVICE_ADDRESS_PCI_MULTI_ON) { qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("'multifunction=on' is not supported with " "this QEMU binary")); @@ -1649,9 +1650,9 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, virBufferAsprintf(buf, ",bus=pci.0"); else virBufferAsprintf(buf, ",bus=pci"); - if (info->addr.pci.multi == VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON) + if (info->addr.pci.multi == VIR_DEVICE_ADDRESS_PCI_MULTI_ON) virBufferAddLit(buf, ",multifunction=on"); - else if (info->addr.pci.multi == VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_OFF) + else if (info->addr.pci.multi == VIR_DEVICE_ADDRESS_PCI_MULTI_OFF) virBufferAddLit(buf, ",multifunction=off"); virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot); if (info->addr.pci.function != 0) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index c2fa75b..2c07f55 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -43,6 +43,7 @@ #include "virnetdev.h" #include "virnetdevbridge.h" #include "virnetdevtap.h" +#include "device_conf.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -258,7 +259,7 @@ int qemuDomainAttachPciDiskDevice(virConnectPtr conn, } } } else { - virDomainDevicePCIAddress guestAddr = disk->info.addr.pci; + virDevicePCIAddress guestAddr = disk->info.addr.pci; ret = qemuMonitorAddPCIDisk(priv->mon, disk->src, type, @@ -659,7 +660,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, char *netstr = NULL; virNetDevVPortProfilePtr vport = NULL; int ret = -1; - virDomainDevicePCIAddress guestAddr; + virDevicePCIAddress guestAddr; int vlan; bool releaseaddr = false; bool iface_connected = false; @@ -967,7 +968,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, configfd, configfd_name); qemuDomainObjExitMonitorWithDriver(driver, vm); } else { - virDomainDevicePCIAddress guestAddr = hostdev->info->addr.pci; + virDevicePCIAddress guestAddr = hostdev->info->addr.pci; qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorAddPCIHostDevice(priv->mon, diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index b8a2f2f..02b42c2 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2148,8 +2148,8 @@ int qemuMonitorAddUSBDeviceMatch(qemuMonitorPtr mon, int qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *hostAddr, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *hostAddr, + virDevicePCIAddress *guestAddr) { int ret; VIR_DEBUG("mon=%p domain=%d bus=%d slot=%d function=%d", @@ -2173,7 +2173,7 @@ int qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon, int qemuMonitorAddPCIDisk(qemuMonitorPtr mon, const char *path, const char *bus, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { int ret; VIR_DEBUG("mon=%p path=%s bus=%s", @@ -2195,7 +2195,7 @@ int qemuMonitorAddPCIDisk(qemuMonitorPtr mon, int qemuMonitorAddPCINetwork(qemuMonitorPtr mon, const char *nicstr, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { int ret; VIR_DEBUG("mon=%p nicstr=%s", mon, nicstr); @@ -2215,7 +2215,7 @@ int qemuMonitorAddPCINetwork(qemuMonitorPtr mon, int qemuMonitorRemovePCIDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { int ret; VIR_DEBUG("mon=%p domain=%d bus=%d slot=%d function=%d", @@ -2451,7 +2451,7 @@ int qemuMonitorGetPtyPaths(qemuMonitorPtr mon, int qemuMonitorAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { VIR_DEBUG("mon=%p type=%s", mon, bus); int ret; @@ -2473,7 +2473,7 @@ int qemuMonitorAttachPCIDiskController(qemuMonitorPtr mon, int qemuMonitorAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress *controllerAddr, + virDevicePCIAddress *controllerAddr, virDomainDeviceDriveAddress *driveAddr) { VIR_DEBUG("mon=%p drivestr=%s domain=%d bus=%d slot=%d function=%d", diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 66bec38..6b5bbe6 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -32,6 +32,7 @@ # include "bitmap.h" # include "virhash.h" # include "json.h" +# include "device_conf.h" typedef struct _qemuMonitor qemuMonitor; typedef qemuMonitor *qemuMonitorPtr; @@ -413,8 +414,8 @@ int qemuMonitorAddUSBDeviceMatch(qemuMonitorPtr mon, int qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *hostAddr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *hostAddr, + virDevicePCIAddress *guestAddr); /* XXX disk driver type eg, qcow/etc. * XXX cache mode @@ -422,17 +423,17 @@ int qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon, int qemuMonitorAddPCIDisk(qemuMonitorPtr mon, const char *path, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); /* XXX do we really want to hardcode 'nicstr' as the * sendable item here */ int qemuMonitorAddPCINetwork(qemuMonitorPtr mon, const char *nicstr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); int qemuMonitorRemovePCIDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); int qemuMonitorSendFileHandle(qemuMonitorPtr mon, @@ -471,11 +472,11 @@ int qemuMonitorGetPtyPaths(qemuMonitorPtr mon, int qemuMonitorAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); int qemuMonitorAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress *controllerAddr, + virDevicePCIAddress *controllerAddr, virDomainDeviceDriveAddress *driveAddr); @@ -483,7 +484,7 @@ typedef struct _qemuMonitorPCIAddress qemuMonitorPCIAddress; struct _qemuMonitorPCIAddress { unsigned int vendor; unsigned int product; - virDomainDevicePCIAddress addr; + virDevicePCIAddress addr; }; int qemuMonitorGetAllPCIAddresses(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 7d2da21..1d8ac2a 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2564,8 +2564,8 @@ int qemuMonitorJSONAddUSBDeviceMatch(qemuMonitorPtr mon ATTRIBUTE_UNUSED, int qemuMonitorJSONAddPCIHostDevice(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *hostAddr ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) + virDevicePCIAddress *hostAddr ATTRIBUTE_UNUSED, + virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("pci_add not supported in JSON mode")); @@ -2576,7 +2576,7 @@ int qemuMonitorJSONAddPCIHostDevice(qemuMonitorPtr mon ATTRIBUTE_UNUSED, int qemuMonitorJSONAddPCIDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED, const char *path ATTRIBUTE_UNUSED, const char *bus ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) + virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("pci_add not supported in JSON mode")); @@ -2586,7 +2586,7 @@ int qemuMonitorJSONAddPCIDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED, int qemuMonitorJSONAddPCINetwork(qemuMonitorPtr mon ATTRIBUTE_UNUSED, const char *nicstr ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) + virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("pci_add not supported in JSON mode")); @@ -2595,7 +2595,7 @@ int qemuMonitorJSONAddPCINetwork(qemuMonitorPtr mon ATTRIBUTE_UNUSED, int qemuMonitorJSONRemovePCIDevice(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) + virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("pci_del not supported in JSON mode")); @@ -2852,7 +2852,7 @@ int qemuMonitorJSONGetPtyPaths(qemuMonitorPtr mon, int qemuMonitorJSONAttachPCIDiskController(qemuMonitorPtr mon ATTRIBUTE_UNUSED, const char *bus ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) + virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("pci_add not supported in JSON mode")); @@ -2891,7 +2891,7 @@ qemuMonitorJSONGetGuestDriveAddress(virJSONValuePtr reply, int qemuMonitorJSONAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress* controllerAddr, + virDevicePCIAddress* controllerAddr, virDomainDeviceDriveAddress* driveAddr) { int ret; diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index e8bd9b8..8237751 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -161,20 +161,20 @@ int qemuMonitorJSONAddUSBDeviceMatch(qemuMonitorPtr mon, int qemuMonitorJSONAddPCIHostDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *hostAddr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *hostAddr, + virDevicePCIAddress *guestAddr); int qemuMonitorJSONAddPCIDisk(qemuMonitorPtr mon, const char *path, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); int qemuMonitorJSONAddPCINetwork(qemuMonitorPtr mon, const char *nicstr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); int qemuMonitorJSONRemovePCIDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); int qemuMonitorJSONSendFileHandle(qemuMonitorPtr mon, const char *fdname, @@ -201,11 +201,11 @@ int qemuMonitorJSONGetPtyPaths(qemuMonitorPtr mon, int qemuMonitorJSONAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); int qemuMonitorJSONAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress *controllerAddr, + virDevicePCIAddress *controllerAddr, virDomainDeviceDriveAddress *driveAddr); int qemuMonitorJSONGetAllPCIAddresses(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index edb5dfd..f299bc1 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1898,7 +1898,7 @@ int qemuMonitorTextAddUSBDeviceMatch(qemuMonitorPtr mon, static int qemuMonitorTextParsePciAddReply(qemuMonitorPtr mon ATTRIBUTE_UNUSED, const char *reply, - virDomainDevicePCIAddress *addr) + virDevicePCIAddress *addr) { char *s, *e; @@ -1960,8 +1960,8 @@ qemuMonitorTextParsePciAddReply(qemuMonitorPtr mon ATTRIBUTE_UNUSED, int qemuMonitorTextAddPCIHostDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *hostAddr, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *hostAddr, + virDevicePCIAddress *guestAddr) { char *cmd; char *reply = NULL; @@ -2006,7 +2006,7 @@ cleanup: int qemuMonitorTextAddPCIDisk(qemuMonitorPtr mon, const char *path, const char *bus, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { char *cmd = NULL; char *reply = NULL; @@ -2058,7 +2058,7 @@ cleanup: int qemuMonitorTextAddPCINetwork(qemuMonitorPtr mon, const char *nicstr, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { char *cmd; char *reply = NULL; @@ -2091,7 +2091,7 @@ cleanup: int qemuMonitorTextRemovePCIDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { char *cmd = NULL; char *reply = NULL; @@ -2439,7 +2439,7 @@ cleanup: int qemuMonitorTextAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { char *cmd = NULL; char *reply = NULL; @@ -2528,7 +2528,7 @@ qemudParseDriveAddReply(const char *reply, int qemuMonitorTextAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress *controllerAddr, + virDevicePCIAddress *controllerAddr, virDomainDeviceDriveAddress *driveAddr) { char *cmd = NULL; diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 4525864..cdde88b 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -147,20 +147,20 @@ int qemuMonitorTextAddUSBDeviceMatch(qemuMonitorPtr mon, int qemuMonitorTextAddPCIHostDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *hostAddr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *hostAddr, + virDevicePCIAddress *guestAddr); int qemuMonitorTextAddPCIDisk(qemuMonitorPtr mon, const char *path, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); int qemuMonitorTextAddPCINetwork(qemuMonitorPtr mon, const char *nicstr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); int qemuMonitorTextRemovePCIDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); int qemuMonitorTextSendFileHandle(qemuMonitorPtr mon, const char *fdname, @@ -187,11 +187,11 @@ int qemuMonitorTextGetPtyPaths(qemuMonitorPtr mon, int qemuMonitorTextAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr); int qemuMonitorTextAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress *controllerAddr, + virDevicePCIAddress *controllerAddr, virDomainDeviceDriveAddress *driveAddr); int qemuMonitorTextGetAllPCIAddresses(qemuMonitorPtr mon, diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index f1aa9b6..5106103 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -46,6 +46,7 @@ #include "count-one-bits.h" #include "virfile.h" #include "viruri.h" +#include "device_conf.h" /* required for cpumap_t */ #include <xen/dom0_ops.h> @@ -2732,7 +2733,7 @@ xenDaemonAttachDeviceFlags(virDomainPtr domain, const char *xml, if (xenFormatSxprOnePCI(dev->data.hostdev, &buf, 0) < 0) goto cleanup; - virDomainDevicePCIAddress PCIAddr; + virDevicePCIAddress PCIAddr; PCIAddr = dev->data.hostdev->source.subsys.u.pci; virAsprintf(&target, "PCI device: %.4x:%.2x:%.2x", PCIAddr.domain, -- 1.7.4.4
On 2012年06月25日 19:35, Shradha Shah wrote:
Refactoring existing code without causing any functional changes to prepare for new code. This patch makes the code reusable.
Signed-off-by: Shradha Shah<sshah@solarflare.com> --- src/Makefile.am | 7 ++- src/conf/device_conf.c | 135 ++++++++++++++++++++++++++++++++++++++++++ src/conf/device_conf.h | 65 ++++++++++++++++++++ src/conf/domain_conf.c | 114 ++++------------------------------- src/conf/domain_conf.h | 25 +------- src/libvirt_private.syms | 10 ++- src/qemu/qemu_command.c | 13 ++-- src/qemu/qemu_hotplug.c | 7 +- src/qemu/qemu_monitor.c | 14 ++-- src/qemu/qemu_monitor.h | 17 +++--- src/qemu/qemu_monitor_json.c | 14 ++-- src/qemu/qemu_monitor_json.h | 14 ++-- src/qemu/qemu_monitor_text.c | 16 +++--- src/qemu/qemu_monitor_text.h | 14 ++-- src/xen/xend_internal.c | 3 +- 15 files changed, 288 insertions(+), 180 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am index e40909b..009c4e5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -199,6 +199,9 @@ CONSOLE_CONF_SOURCES = \ DOMAIN_LIST_SOURCES = \ conf/virdomainlist.c conf/virdomainlist.h
+DEVICE_CONF_SOURCES = \ + conf/device_conf.c conf/device_conf.h + CONF_SOURCES = \ $(NETDEV_CONF_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ @@ -212,7 +215,8 @@ CONF_SOURCES = \ $(SECRET_CONF_SOURCES) \ $(CPU_CONF_SOURCES) \ $(CONSOLE_CONF_SOURCES) \ - $(DOMAIN_LIST_SOURCES) + $(DOMAIN_LIST_SOURCES) \ + $(DEVICE_CONF_SOURCES)
# The remote RPC driver, covering domains, storage, networks, etc REMOTE_DRIVER_GENERATED = \ @@ -1525,6 +1529,7 @@ libvirt_lxc_SOURCES = \ $(ENCRYPTION_CONF_SOURCES) \ $(NETDEV_CONF_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ + $(DEVICE_CONF_SOURCES) \ $(SECRET_CONF_SOURCES) \ $(CPU_CONF_SOURCES) \ $(SECURITY_DRIVER_SOURCES) \ diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c new file mode 100644 index 0000000..af21aad --- /dev/null +++ b/src/conf/device_conf.c @@ -0,0 +1,135 @@ +/* + * device_conf.h: device XML handling + * + * Copyright (C) 2006-2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Shradha Shah<sshah@solarflare.com> + */ + +#include<config.h> +#include "virterror_internal.h" +#include "datatypes.h" +#include "memory.h" +#include "xml.h" +#include "uuid.h" +#include "util.h" +#include "buf.h" +#include "conf/device_conf.h" + +#define VIR_FROM_THIS VIR_FROM_DEVICE
VIR_FROM_DEVICE is not defined, and isn't it too big to use 'device'? I see only pci device address parsing and formating code actually. And most of the device conf codes are in domain_conf.[ch].
+ +#define virDeviceReportError(code, ...) \ + virReportErrorHelper(VIR_FROM_DOMAIN, code, __FILE__, \
Copy & Paste mistake (VIR_DOMAIN_DOMAIN) I'm wondering if it's neccessary to refactor the codes like this. As it just split the codes from domain_conf.[ch] into new files, no more reusability as far as I can see. The only exception is the new virDevicePCIAddressFormat, but it can be in domain_conf.[ch] too. Any special reason you want to have 2 new files?
+ __FUNCTION__, __LINE__, __VA_ARGS__) + +VIR_ENUM_IMPL(virDeviceAddressPciMulti, + VIR_DEVICE_ADDRESS_PCI_MULTI_LAST, + "default", + "on", + "off") + +int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr) +{ + /* PCI bus has 32 slots and 8 functions per slot */ + if (addr->slot>= 32 || addr->function>= 8) + return 0; + return addr->domain || addr->bus || addr->slot; +} + + +int +virDevicePCIAddressParseXML(xmlNodePtr node, + virDevicePCIAddressPtr addr) +{ + char *domain, *slot, *bus, *function, *multi; + int ret = -1; + + memset(addr, 0, sizeof(*addr)); + + domain = virXMLPropString(node, "domain"); + bus = virXMLPropString(node, "bus"); + slot = virXMLPropString(node, "slot"); + function = virXMLPropString(node, "function"); + multi = virXMLPropString(node, "multifunction"); + + if (domain&& + virStrToLong_ui(domain, NULL, 0,&addr->domain)< 0) { + virDeviceReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse<address> 'domain' attribute")); + goto cleanup; + } + + if (bus&& + virStrToLong_ui(bus, NULL, 0,&addr->bus)< 0) { + virDeviceReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse<address> 'bus' attribute")); + goto cleanup; + } + + if (slot&& + virStrToLong_ui(slot, NULL, 0,&addr->slot)< 0) { + virDeviceReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse<address> 'slot' attribute")); + goto cleanup; + } + + if (function&& + virStrToLong_ui(function, NULL, 0,&addr->function)< 0) { + virDeviceReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse<address> 'function' attribute")); + goto cleanup; + } + + if (multi&& + ((addr->multi = virDeviceAddressPciMultiTypeFromString(multi))<= 0)) { + virDeviceReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unknown value '%s' for<address> 'multifunction' attribute"), + multi); + goto cleanup; + + } + if (!virDevicePCIAddressIsValid(addr)) { + virDeviceReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Insufficient specification for PCI address")); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(domain); + VIR_FREE(bus); + VIR_FREE(slot); + VIR_FREE(function); + VIR_FREE(multi); + return ret; +} + +int +virDevicePCIAddressFormat(virBufferPtr buf, + virDevicePCIAddress addr, + bool includeTypeInAddr) +{ + virBufferAsprintf(buf, "<address %sdomain='0x%.4x' bus='0x%.2x' " + "slot='0x%.2x' function='0x%.1x'/>\n", + includeTypeInAddr ? "type='pci' " : "", + addr.domain, + addr.bus, + addr.slot, + addr.function); + return 0; +} diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h new file mode 100644 index 0000000..b060798 --- /dev/null +++ b/src/conf/device_conf.h @@ -0,0 +1,65 @@ +/* + * device_conf.h: device XML handling entry points + * + * Copyright (C) 2006-2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Shradha Shah<sshah@solarflare.com> + */ + +#ifndef __DEVICE_CONF_H__ +# define __DEVICE_CONF_H__ + +# include<libxml/parser.h> +# include<libxml/tree.h> +# include<libxml/xpath.h> + +# include "internal.h" +# include "util.h" +# include "threads.h" +# include "buf.h" + +enum virDeviceAddressPciMulti { + VIR_DEVICE_ADDRESS_PCI_MULTI_DEFAULT = 0, + VIR_DEVICE_ADDRESS_PCI_MULTI_ON, + VIR_DEVICE_ADDRESS_PCI_MULTI_OFF, + + VIR_DEVICE_ADDRESS_PCI_MULTI_LAST +}; + +typedef struct _virDevicePCIAddress virDevicePCIAddress; +typedef virDevicePCIAddress *virDevicePCIAddressPtr; +struct _virDevicePCIAddress { + unsigned int domain; + unsigned int bus; + unsigned int slot; + unsigned int function; + int multi; /* enum virDomainDeviceAddressPciMulti */ +}; + +int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr); + +int virDevicePCIAddressParseXML(xmlNodePtr node, + virDevicePCIAddressPtr addr); + +int virDevicePCIAddressFormat(virBufferPtr buf, + virDevicePCIAddress addr, + bool includeTypeInAddr); + + +VIR_ENUM_DECL(virDeviceAddressPciMulti) + +#endif /* __DEVICE_CONF_H__ */ diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f44dc93..7541627 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -53,6 +53,7 @@ #include "netdev_vport_profile_conf.h" #include "netdev_bandwidth_conf.h" #include "virdomainlist.h" +#include "device_conf.h"
#define VIR_FROM_THIS VIR_FROM_DOMAIN
@@ -152,12 +153,6 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, "usb", "spapr-vio")
-VIR_ENUM_IMPL(virDomainDeviceAddressPciMulti, - VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_LAST, - "default", - "on", - "off") - VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, "block", "file", @@ -1904,7 +1899,7 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
switch (info->type) { case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: - return virDomainDevicePCIAddressIsValid(&info->addr.pci); + return virDevicePCIAddressIsValid(&info->addr.pci);
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: return 1; @@ -1916,16 +1911,6 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, return 0; }
- -int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr) -{ - /* PCI bus has 32 slots and 8 functions per slot */ - if (addr->slot>= 32 || addr->function>= 8) - return 0; - return addr->domain || addr->bus || addr->slot; -} - - static bool virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info, unsigned int flags) { @@ -2149,7 +2134,7 @@ virDomainDeviceInfoFormat(virBufferPtr buf, info->addr.pci.function); if (info->addr.pci.multi) { virBufferAsprintf(buf, " multifunction='%s'", - virDomainDeviceAddressPciMultiTypeToString(info->addr.pci.multi)); + virDeviceAddressPciMultiTypeToString(info->addr.pci.multi)); } break;
@@ -2197,75 +2182,6 @@ virDomainDeviceInfoFormat(virBufferPtr buf, }
static int -virDomainDevicePCIAddressParseXML(xmlNodePtr node, - virDomainDevicePCIAddressPtr addr) -{ - char *domain, *slot, *bus, *function, *multi; - int ret = -1; - - memset(addr, 0, sizeof(*addr)); - - domain = virXMLPropString(node, "domain"); - bus = virXMLPropString(node, "bus"); - slot = virXMLPropString(node, "slot"); - function = virXMLPropString(node, "function"); - multi = virXMLPropString(node, "multifunction"); - - if (domain&& - virStrToLong_ui(domain, NULL, 0,&addr->domain)< 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot parse<address> 'domain' attribute")); - goto cleanup; - } - - if (bus&& - virStrToLong_ui(bus, NULL, 0,&addr->bus)< 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot parse<address> 'bus' attribute")); - goto cleanup; - } - - if (slot&& - virStrToLong_ui(slot, NULL, 0,&addr->slot)< 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot parse<address> 'slot' attribute")); - goto cleanup; - } - - if (function&& - virStrToLong_ui(function, NULL, 0,&addr->function)< 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot parse<address> 'function' attribute")); - goto cleanup; - } - - if (multi&& - ((addr->multi = virDomainDeviceAddressPciMultiTypeFromString(multi))<= 0)) { - virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unknown value '%s' for<address> 'multifunction' attribute"), - multi); - goto cleanup; - - } - if (!virDomainDevicePCIAddressIsValid(addr)) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Insufficient specification for PCI address")); - goto cleanup; - } - - ret = 0; - -cleanup: - VIR_FREE(domain); - VIR_FREE(bus); - VIR_FREE(slot); - VIR_FREE(function); - VIR_FREE(multi); - return ret; -} - - -static int virDomainDeviceDriveAddressParseXML(xmlNodePtr node, virDomainDeviceDriveAddressPtr addr) { @@ -2626,7 +2542,7 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
switch (info->type) { case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: - if (virDomainDevicePCIAddressParseXML(address,&info->addr.pci)< 0) + if (virDevicePCIAddressParseXML(address,&info->addr.pci)< 0) goto cleanup; break;
@@ -2674,7 +2590,7 @@ cleanup:
static int virDomainParseLegacyDeviceAddress(char *devaddr, - virDomainDevicePCIAddressPtr pci) + virDevicePCIAddressPtr pci) { char *tmp;
@@ -2859,10 +2775,10 @@ virDomainHostdevSubsysPciDefParseXML(const xmlNodePtr node, while (cur != NULL) { if (cur->type == XML_ELEMENT_NODE) { if (xmlStrEqual(cur->name, BAD_CAST "address")) { - virDomainDevicePCIAddressPtr addr = + virDevicePCIAddressPtr addr = &def->source.subsys.u.pci;
- if (virDomainDevicePCIAddressParseXML(cur, addr)< 0) + if (virDevicePCIAddressParseXML(cur, addr)< 0) goto out; } else if ((flags& VIR_DOMAIN_XML_INTERNAL_STATUS)&& xmlStrEqual(cur->name, BAD_CAST "state")) { @@ -11427,14 +11343,12 @@ virDomainHostdevSourceFormat(virBufferPtr buf, } break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: - virBufferAsprintf(buf, "<address %sdomain='0x%.4x' bus='0x%.2x' " - "slot='0x%.2x' function='0x%.1x'/>\n", - includeTypeInAddr ? "type='pci' " : "", - def->source.subsys.u.pci.domain, - def->source.subsys.u.pci.bus, - def->source.subsys.u.pci.slot, - def->source.subsys.u.pci.function); - + if (virDevicePCIAddressFormat(buf, + def->source.subsys.u.pci, + includeTypeInAddr) != 0) + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("PCI address Formatting failed")); + if ((flags& VIR_DOMAIN_XML_INTERNAL_PCI_ORIG_STATES)&& (def->origstates.states.pci.unbind_from_stub || def->origstates.states.pci.remove_slot || @@ -11447,7 +11361,7 @@ virDomainHostdevSourceFormat(virBufferPtr buf, if (def->origstates.states.pci.reprobe) virBufferAddLit(buf, "<reprobe/>\n"); virBufferAddLit(buf, "</origstates>\n"); - } + } break; default: virDomainReportError(VIR_ERR_INTERNAL_ERROR, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 7d5d60b..51b2da8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -43,6 +43,7 @@ # include "virnetdevvportprofile.h" # include "virnetdevopenvswitch.h" # include "virnetdevbandwidth.h" +# include "device_conf.h"
/* forward declarations of all device types, required by * virDomainDeviceDef @@ -176,14 +177,6 @@ enum virDomainDeviceAddressType { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST };
-enum virDomainDeviceAddressPciMulti { - VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_DEFAULT = 0, - VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON, - VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_OFF, - - VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_LAST -}; - enum virDomainPciRombarMode { VIR_DOMAIN_PCI_ROMBAR_DEFAULT = 0, VIR_DOMAIN_PCI_ROMBAR_ON, @@ -192,16 +185,6 @@ enum virDomainPciRombarMode { VIR_DOMAIN_PCI_ROMBAR_LAST };
-typedef struct _virDomainDevicePCIAddress virDomainDevicePCIAddress; -typedef virDomainDevicePCIAddress *virDomainDevicePCIAddressPtr; -struct _virDomainDevicePCIAddress { - unsigned int domain; - unsigned int bus; - unsigned int slot; - unsigned int function; - int multi; /* enum virDomainDeviceAddressPciMulti */ -}; - typedef struct _virDomainDeviceDriveAddress virDomainDeviceDriveAddress; typedef virDomainDeviceDriveAddress *virDomainDeviceDriveAddressPtr; struct _virDomainDeviceDriveAddress { @@ -263,7 +246,7 @@ struct _virDomainDeviceInfo { char *alias; int type; union { - virDomainDevicePCIAddress pci; + virDevicePCIAddress pci; virDomainDeviceDriveAddress drive; virDomainDeviceVirtioSerialAddress vioserial; virDomainDeviceCcidAddress ccid; @@ -374,7 +357,7 @@ struct _virDomainHostdevSubsys { unsigned vendor; unsigned product; } usb; - virDomainDevicePCIAddress pci; /* host address */ + virDevicePCIAddress pci; /* host address */ } u; };
@@ -1891,7 +1874,6 @@ virDomainDeviceDefPtr virDomainDeviceDefCopy(virCapsPtr caps, virDomainDeviceDefPtr src); int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, int type); -int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr); void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); void virDomainDefClearPCIAddresses(virDomainDefPtr def); void virDomainDefClearDeviceAliases(virDomainDefPtr def); @@ -2161,7 +2143,6 @@ VIR_ENUM_DECL(virDomainLifecycle) VIR_ENUM_DECL(virDomainLifecycleCrash) VIR_ENUM_DECL(virDomainDevice) VIR_ENUM_DECL(virDomainDeviceAddress) -VIR_ENUM_DECL(virDomainDeviceAddressPciMulti) VIR_ENUM_DECL(virDomainDisk) VIR_ENUM_DECL(virDomainDiskDevice) VIR_ENUM_DECL(virDomainDiskBus) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2fe5068..0a77130 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -210,6 +210,13 @@ virUnrefStorageVol; virUnrefStream;
+# device_conf.h +virDeviceAddressPciMultiTypeFromString; +virDeviceAddressPciMultiTypeToString; +virDevicePCIAddressIsValid; +virDevicePCIAddressParseXML; +virDevicePCIAddressFormat; + # dnsmasq.h dnsmasqAddDhcpHost; dnsmasqAddHost; @@ -286,14 +293,11 @@ virDomainDefParseNode; virDomainDefParseString; virDomainDeleteConfig; virDomainDeviceAddressIsValid; -virDomainDeviceAddressPciMultiTypeFromString; -virDomainDeviceAddressPciMultiTypeToString; virDomainDeviceAddressTypeToString; virDomainDeviceDefCopy; virDomainDeviceDefFree; virDomainDeviceDefParse; virDomainDeviceInfoIterate; -virDomainDevicePCIAddressIsValid; virDomainDeviceTypeToString; virDomainDiskBusTypeToString; virDomainDiskCacheTypeFromString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 6549f57..93c018d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -40,6 +40,7 @@ #include "network/bridge_driver.h" #include "virnetdevtap.h" #include "base64.h" +#include "device_conf.h"
#include<sys/utsname.h> #include<sys/stat.h> @@ -909,7 +910,7 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, addr = NULL;
if ((info->addr.pci.function == 0)&& - (info->addr.pci.multi != VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON)) { + (info->addr.pci.multi != VIR_DEVICE_ADDRESS_PCI_MULTI_ON)) { /* a function 0 w/o multifunction=on must reserve the entire slot */ int function; virDomainDeviceInfo temp_info = *info; @@ -1465,7 +1466,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
/* USB2 needs special handling to put all companions in the same slot */ if (IS_USB2_CONTROLLER(def->controllers[i])) { - virDomainDevicePCIAddress addr = { 0, 0, 0, 0, false }; + virDevicePCIAddress addr = { 0, 0, 0, 0, false }; for (j = 0 ; j< i ; j++) { if (IS_USB2_CONTROLLER(def->controllers[j])&& def->controllers[j]->idx == def->controllers[i]->idx) { @@ -1480,7 +1481,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) break; case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1: addr.function = 0; - addr.multi = VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON; + addr.multi = VIR_DEVICE_ADDRESS_PCI_MULTI_ON; break; case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2: addr.function = 1; @@ -1631,7 +1632,7 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, "are supported with this QEMU binary")); return -1; } - if (info->addr.pci.multi == VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON) { + if (info->addr.pci.multi == VIR_DEVICE_ADDRESS_PCI_MULTI_ON) { qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("'multifunction=on' is not supported with " "this QEMU binary")); @@ -1649,9 +1650,9 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, virBufferAsprintf(buf, ",bus=pci.0"); else virBufferAsprintf(buf, ",bus=pci"); - if (info->addr.pci.multi == VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON) + if (info->addr.pci.multi == VIR_DEVICE_ADDRESS_PCI_MULTI_ON) virBufferAddLit(buf, ",multifunction=on"); - else if (info->addr.pci.multi == VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_OFF) + else if (info->addr.pci.multi == VIR_DEVICE_ADDRESS_PCI_MULTI_OFF) virBufferAddLit(buf, ",multifunction=off"); virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot); if (info->addr.pci.function != 0) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index c2fa75b..2c07f55 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -43,6 +43,7 @@ #include "virnetdev.h" #include "virnetdevbridge.h" #include "virnetdevtap.h" +#include "device_conf.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -258,7 +259,7 @@ int qemuDomainAttachPciDiskDevice(virConnectPtr conn, } } } else { - virDomainDevicePCIAddress guestAddr = disk->info.addr.pci; + virDevicePCIAddress guestAddr = disk->info.addr.pci; ret = qemuMonitorAddPCIDisk(priv->mon, disk->src, type, @@ -659,7 +660,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, char *netstr = NULL; virNetDevVPortProfilePtr vport = NULL; int ret = -1; - virDomainDevicePCIAddress guestAddr; + virDevicePCIAddress guestAddr; int vlan; bool releaseaddr = false; bool iface_connected = false; @@ -967,7 +968,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, configfd, configfd_name); qemuDomainObjExitMonitorWithDriver(driver, vm); } else { - virDomainDevicePCIAddress guestAddr = hostdev->info->addr.pci; + virDevicePCIAddress guestAddr = hostdev->info->addr.pci;
qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorAddPCIHostDevice(priv->mon, diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index b8a2f2f..02b42c2 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2148,8 +2148,8 @@ int qemuMonitorAddUSBDeviceMatch(qemuMonitorPtr mon,
int qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *hostAddr, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *hostAddr, + virDevicePCIAddress *guestAddr) { int ret; VIR_DEBUG("mon=%p domain=%d bus=%d slot=%d function=%d", @@ -2173,7 +2173,7 @@ int qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon, int qemuMonitorAddPCIDisk(qemuMonitorPtr mon, const char *path, const char *bus, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { int ret; VIR_DEBUG("mon=%p path=%s bus=%s", @@ -2195,7 +2195,7 @@ int qemuMonitorAddPCIDisk(qemuMonitorPtr mon,
int qemuMonitorAddPCINetwork(qemuMonitorPtr mon, const char *nicstr, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { int ret; VIR_DEBUG("mon=%p nicstr=%s", mon, nicstr); @@ -2215,7 +2215,7 @@ int qemuMonitorAddPCINetwork(qemuMonitorPtr mon,
int qemuMonitorRemovePCIDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { int ret; VIR_DEBUG("mon=%p domain=%d bus=%d slot=%d function=%d", @@ -2451,7 +2451,7 @@ int qemuMonitorGetPtyPaths(qemuMonitorPtr mon,
int qemuMonitorAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { VIR_DEBUG("mon=%p type=%s", mon, bus); int ret; @@ -2473,7 +2473,7 @@ int qemuMonitorAttachPCIDiskController(qemuMonitorPtr mon,
int qemuMonitorAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress *controllerAddr, + virDevicePCIAddress *controllerAddr, virDomainDeviceDriveAddress *driveAddr) { VIR_DEBUG("mon=%p drivestr=%s domain=%d bus=%d slot=%d function=%d", diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 66bec38..6b5bbe6 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -32,6 +32,7 @@ # include "bitmap.h" # include "virhash.h" # include "json.h" +# include "device_conf.h"
typedef struct _qemuMonitor qemuMonitor; typedef qemuMonitor *qemuMonitorPtr; @@ -413,8 +414,8 @@ int qemuMonitorAddUSBDeviceMatch(qemuMonitorPtr mon,
int qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *hostAddr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *hostAddr, + virDevicePCIAddress *guestAddr);
/* XXX disk driver type eg, qcow/etc. * XXX cache mode @@ -422,17 +423,17 @@ int qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon, int qemuMonitorAddPCIDisk(qemuMonitorPtr mon, const char *path, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
/* XXX do we really want to hardcode 'nicstr' as the * sendable item here */ int qemuMonitorAddPCINetwork(qemuMonitorPtr mon, const char *nicstr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
int qemuMonitorRemovePCIDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
int qemuMonitorSendFileHandle(qemuMonitorPtr mon, @@ -471,11 +472,11 @@ int qemuMonitorGetPtyPaths(qemuMonitorPtr mon,
int qemuMonitorAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
int qemuMonitorAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress *controllerAddr, + virDevicePCIAddress *controllerAddr, virDomainDeviceDriveAddress *driveAddr);
@@ -483,7 +484,7 @@ typedef struct _qemuMonitorPCIAddress qemuMonitorPCIAddress; struct _qemuMonitorPCIAddress { unsigned int vendor; unsigned int product; - virDomainDevicePCIAddress addr; + virDevicePCIAddress addr; };
int qemuMonitorGetAllPCIAddresses(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 7d2da21..1d8ac2a 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2564,8 +2564,8 @@ int qemuMonitorJSONAddUSBDeviceMatch(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
int qemuMonitorJSONAddPCIHostDevice(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *hostAddr ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) + virDevicePCIAddress *hostAddr ATTRIBUTE_UNUSED, + virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("pci_add not supported in JSON mode")); @@ -2576,7 +2576,7 @@ int qemuMonitorJSONAddPCIHostDevice(qemuMonitorPtr mon ATTRIBUTE_UNUSED, int qemuMonitorJSONAddPCIDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED, const char *path ATTRIBUTE_UNUSED, const char *bus ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) + virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("pci_add not supported in JSON mode")); @@ -2586,7 +2586,7 @@ int qemuMonitorJSONAddPCIDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
int qemuMonitorJSONAddPCINetwork(qemuMonitorPtr mon ATTRIBUTE_UNUSED, const char *nicstr ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) + virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("pci_add not supported in JSON mode")); @@ -2595,7 +2595,7 @@ int qemuMonitorJSONAddPCINetwork(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
int qemuMonitorJSONRemovePCIDevice(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) + virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("pci_del not supported in JSON mode")); @@ -2852,7 +2852,7 @@ int qemuMonitorJSONGetPtyPaths(qemuMonitorPtr mon,
int qemuMonitorJSONAttachPCIDiskController(qemuMonitorPtr mon ATTRIBUTE_UNUSED, const char *bus ATTRIBUTE_UNUSED, - virDomainDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) + virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("pci_add not supported in JSON mode")); @@ -2891,7 +2891,7 @@ qemuMonitorJSONGetGuestDriveAddress(virJSONValuePtr reply,
int qemuMonitorJSONAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress* controllerAddr, + virDevicePCIAddress* controllerAddr, virDomainDeviceDriveAddress* driveAddr) { int ret; diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index e8bd9b8..8237751 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -161,20 +161,20 @@ int qemuMonitorJSONAddUSBDeviceMatch(qemuMonitorPtr mon,
int qemuMonitorJSONAddPCIHostDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *hostAddr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *hostAddr, + virDevicePCIAddress *guestAddr);
int qemuMonitorJSONAddPCIDisk(qemuMonitorPtr mon, const char *path, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
int qemuMonitorJSONAddPCINetwork(qemuMonitorPtr mon, const char *nicstr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
int qemuMonitorJSONRemovePCIDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
int qemuMonitorJSONSendFileHandle(qemuMonitorPtr mon, const char *fdname, @@ -201,11 +201,11 @@ int qemuMonitorJSONGetPtyPaths(qemuMonitorPtr mon,
int qemuMonitorJSONAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
int qemuMonitorJSONAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress *controllerAddr, + virDevicePCIAddress *controllerAddr, virDomainDeviceDriveAddress *driveAddr);
int qemuMonitorJSONGetAllPCIAddresses(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index edb5dfd..f299bc1 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1898,7 +1898,7 @@ int qemuMonitorTextAddUSBDeviceMatch(qemuMonitorPtr mon, static int qemuMonitorTextParsePciAddReply(qemuMonitorPtr mon ATTRIBUTE_UNUSED, const char *reply, - virDomainDevicePCIAddress *addr) + virDevicePCIAddress *addr) { char *s, *e;
@@ -1960,8 +1960,8 @@ qemuMonitorTextParsePciAddReply(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
int qemuMonitorTextAddPCIHostDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *hostAddr, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *hostAddr, + virDevicePCIAddress *guestAddr) { char *cmd; char *reply = NULL; @@ -2006,7 +2006,7 @@ cleanup: int qemuMonitorTextAddPCIDisk(qemuMonitorPtr mon, const char *path, const char *bus, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { char *cmd = NULL; char *reply = NULL; @@ -2058,7 +2058,7 @@ cleanup:
int qemuMonitorTextAddPCINetwork(qemuMonitorPtr mon, const char *nicstr, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { char *cmd; char *reply = NULL; @@ -2091,7 +2091,7 @@ cleanup:
int qemuMonitorTextRemovePCIDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { char *cmd = NULL; char *reply = NULL; @@ -2439,7 +2439,7 @@ cleanup:
int qemuMonitorTextAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, - virDomainDevicePCIAddress *guestAddr) + virDevicePCIAddress *guestAddr) { char *cmd = NULL; char *reply = NULL; @@ -2528,7 +2528,7 @@ qemudParseDriveAddReply(const char *reply,
int qemuMonitorTextAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress *controllerAddr, + virDevicePCIAddress *controllerAddr, virDomainDeviceDriveAddress *driveAddr) { char *cmd = NULL; diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 4525864..cdde88b 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -147,20 +147,20 @@ int qemuMonitorTextAddUSBDeviceMatch(qemuMonitorPtr mon,
int qemuMonitorTextAddPCIHostDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *hostAddr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *hostAddr, + virDevicePCIAddress *guestAddr);
int qemuMonitorTextAddPCIDisk(qemuMonitorPtr mon, const char *path, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
int qemuMonitorTextAddPCINetwork(qemuMonitorPtr mon, const char *nicstr, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
int qemuMonitorTextRemovePCIDevice(qemuMonitorPtr mon, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
int qemuMonitorTextSendFileHandle(qemuMonitorPtr mon, const char *fdname, @@ -187,11 +187,11 @@ int qemuMonitorTextGetPtyPaths(qemuMonitorPtr mon,
int qemuMonitorTextAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, - virDomainDevicePCIAddress *guestAddr); + virDevicePCIAddress *guestAddr);
int qemuMonitorTextAttachDrive(qemuMonitorPtr mon, const char *drivestr, - virDomainDevicePCIAddress *controllerAddr, + virDevicePCIAddress *controllerAddr, virDomainDeviceDriveAddress *driveAddr);
int qemuMonitorTextGetAllPCIAddresses(qemuMonitorPtr mon, diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index f1aa9b6..5106103 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -46,6 +46,7 @@ #include "count-one-bits.h" #include "virfile.h" #include "viruri.h" +#include "device_conf.h"
/* required for cpumap_t */ #include<xen/dom0_ops.h> @@ -2732,7 +2733,7 @@ xenDaemonAttachDeviceFlags(virDomainPtr domain, const char *xml, if (xenFormatSxprOnePCI(dev->data.hostdev,&buf, 0)< 0) goto cleanup;
- virDomainDevicePCIAddress PCIAddr; + virDevicePCIAddress PCIAddr;
PCIAddr = dev->data.hostdev->source.subsys.u.pci; virAsprintf(&target, "PCI device: %.4x:%.2x:%.2x", PCIAddr.domain,
On 06/27/2012 09:18 AM, Osier Yang wrote:
On 2012年06月25日 19:35, Shradha Shah wrote:
Refactoring existing code without causing any functional changes to prepare for new code. This patch makes the code reusable.
Signed-off-by: Shradha Shah<sshah@solarflare.com> --- src/Makefile.am | 7 ++- src/conf/device_conf.c | 135 ++++++++++++++++++++++++++++++++++++++++++ src/conf/device_conf.h | 65 ++++++++++++++++++++ src/conf/domain_conf.c | 114 ++++------------------------------- src/conf/domain_conf.h | 25 +------- src/libvirt_private.syms | 10 ++- src/qemu/qemu_command.c | 13 ++-- src/qemu/qemu_hotplug.c | 7 +- src/qemu/qemu_monitor.c | 14 ++-- src/qemu/qemu_monitor.h | 17 +++--- src/qemu/qemu_monitor_json.c | 14 ++-- src/qemu/qemu_monitor_json.h | 14 ++-- src/qemu/qemu_monitor_text.c | 16 +++--- src/qemu/qemu_monitor_text.h | 14 ++-- src/xen/xend_internal.c | 3 +- 15 files changed, 288 insertions(+), 180 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am index e40909b..009c4e5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -199,6 +199,9 @@ CONSOLE_CONF_SOURCES = \ DOMAIN_LIST_SOURCES = \ conf/virdomainlist.c conf/virdomainlist.h
+DEVICE_CONF_SOURCES = \ + conf/device_conf.c conf/device_conf.h + CONF_SOURCES = \ $(NETDEV_CONF_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ @@ -212,7 +215,8 @@ CONF_SOURCES = \ $(SECRET_CONF_SOURCES) \ $(CPU_CONF_SOURCES) \ $(CONSOLE_CONF_SOURCES) \ - $(DOMAIN_LIST_SOURCES) + $(DOMAIN_LIST_SOURCES) \ + $(DEVICE_CONF_SOURCES)
# The remote RPC driver, covering domains, storage, networks, etc REMOTE_DRIVER_GENERATED = \ @@ -1525,6 +1529,7 @@ libvirt_lxc_SOURCES = \ $(ENCRYPTION_CONF_SOURCES) \ $(NETDEV_CONF_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ + $(DEVICE_CONF_SOURCES) \ $(SECRET_CONF_SOURCES) \ $(CPU_CONF_SOURCES) \ $(SECURITY_DRIVER_SOURCES) \ diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c new file mode 100644 index 0000000..af21aad --- /dev/null +++ b/src/conf/device_conf.c @@ -0,0 +1,135 @@ +/* + * device_conf.h: device XML handling + * + * Copyright (C) 2006-2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Shradha Shah<sshah@solarflare.com> + */ + +#include<config.h> +#include "virterror_internal.h" +#include "datatypes.h" +#include "memory.h" +#include "xml.h" +#include "uuid.h" +#include "util.h" +#include "buf.h" +#include "conf/device_conf.h" + +#define VIR_FROM_THIS VIR_FROM_DEVICE
VIR_FROM_DEVICE is not defined, and isn't it too big to use 'device'? I see only pci device address parsing and formating code actually. And most of the device conf codes are in domain_conf.[ch].
I think I suggested "device_conf.[ch]" in my review of Shradha's previous series. The reason is that we may need to break out the parsing/formatting of other types of devices in the future.
+ +#define virDeviceReportError(code, ...) \ + virReportErrorHelper(VIR_FROM_DOMAIN, code, __FILE__, \
Copy & Paste mistake (VIR_DOMAIN_DOMAIN)
I'm wondering if it's neccessary to refactor the codes like this. As it just split the codes from domain_conf.[ch] into new files, no more reusability as far as I can see. The only exception is the new virDevicePCIAddressFormat, but it can be in domain_conf.[ch] too. Any special reason you want to have 2 new files?
The immediate use is that the data structures will also be used in network_conf.h, and some of the functions will be called from network_conf.c, and I don't think it's clean to have network_conf.c calling into domain_conf.c, or to have network_conf.h #including domain_conf.h. The alternative mode of operation (just use the functions in their current location) could lead to a jumbled mess - consider if someone in the future decided that (in a move mirroring what's happened here) an object defined in network_conf.h was also useful in domain_conf.[hc] - you would then have a situation where domain_conf.h needed to #include network_conf.h, but network_conf.h needed to #include domain_conf.h. Better to keep a hierarchical organization and avoid circular references.
Just code movement no functional changes here. This makes the code reusable Signed-off-by: Shradha Shah <sshah@solarflare.com> --- src/network/bridge_driver.c | 84 ++++++++++++++++++++++++++---------------- 1 files changed, 52 insertions(+), 32 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 79d3010..7d853c6 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2731,6 +2731,56 @@ int networkRegister(void) { * "backend" function table. */ +/* networkCreateInterfacePool: + * @netdef: the original NetDef from the network + * + * Creates an implicit interface pool of VF's when a PF dev is given + */ +static int +networkCreateInterfacePool(virNetworkDefPtr netdef) { + unsigned int num_virt_fns = 0; + char **vfname = NULL; + int ret = -1, ii = 0; + + if ((virNetDevGetVirtualFunctions(netdef->forwardPfs->dev, + &vfname, &num_virt_fns)) < 0) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get Virtual functions on %s"), + netdef->forwardPfs->dev); + goto finish; + } + + if (num_virt_fns == 0) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("No Vf's present on SRIOV PF %s"), + netdef->forwardPfs->dev); + goto finish; + } + + if ((VIR_ALLOC_N(netdef->forwardIfs, num_virt_fns)) < 0) { + virReportOOMError(); + goto finish; + } + + netdef->nForwardIfs = num_virt_fns; + + for (ii = 0; ii < netdef->nForwardIfs; ii++) { + netdef->forwardIfs[ii].dev = strdup(vfname[ii]); + if (!netdef->forwardIfs[ii].dev) { + virReportOOMError(); + goto finish; + } + netdef->forwardIfs[ii].usageCount = 0; + } + + ret = 0; +finish: + for (ii = 0; ii < num_virt_fns; ii++) + VIR_FREE(vfname[ii]); + VIR_FREE(vfname); + return ret; +} + /* networkAllocateActualDevice: * @iface: the original NetDef from the domain * @@ -2749,8 +2799,6 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) virNetworkObjPtr network; virNetworkDefPtr netdef; virPortGroupDefPtr portgroup; - unsigned int num_virt_fns = 0; - char **vfname = NULL; int ii; int ret = -1; @@ -2896,36 +2944,11 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) */ if (netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) { if ((netdef->nForwardPfs > 0) && (netdef->nForwardIfs <= 0)) { - if ((virNetDevGetVirtualFunctions(netdef->forwardPfs->dev, - &vfname, &num_virt_fns)) < 0) { + if ((networkCreateInterfacePool(netdef)) < 0) { networkReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not get Virtual functions on %s"), - netdef->forwardPfs->dev); + _("Could not Interface Pool")); goto cleanup; } - - if (num_virt_fns == 0) { - networkReportError(VIR_ERR_INTERNAL_ERROR, - _("No Vf's present on SRIOV PF %s"), - netdef->forwardPfs->dev); - goto cleanup; - } - - if ((VIR_ALLOC_N(netdef->forwardIfs, num_virt_fns)) < 0) { - virReportOOMError(); - goto cleanup; - } - - netdef->nForwardIfs = num_virt_fns; - - for (ii = 0; ii < netdef->nForwardIfs; ii++) { - netdef->forwardIfs[ii].dev = strdup(vfname[ii]); - if (!netdef->forwardIfs[ii].dev) { - virReportOOMError(); - goto cleanup; - } - netdef->forwardIfs[ii].usageCount = 0; - } } /* pick first dev with 0 usageCount */ @@ -2977,9 +3000,6 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) ret = 0; cleanup: - for (ii = 0; ii < num_virt_fns; ii++) - VIR_FREE(vfname[ii]); - VIR_FREE(vfname); if (network) virNetworkObjUnlock(network); if (ret < 0) { -- 1.7.4.4
On 2012年06月25日 19:35, Shradha Shah wrote:
Just code movement no functional changes here. This makes the code reusable
Signed-off-by: Shradha Shah<sshah@solarflare.com> --- src/network/bridge_driver.c | 84 ++++++++++++++++++++++++++---------------- 1 files changed, 52 insertions(+), 32 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 79d3010..7d853c6 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2731,6 +2731,56 @@ int networkRegister(void) { * "backend" function table. */
+/* networkCreateInterfacePool: + * @netdef: the original NetDef from the network + * + * Creates an implicit interface pool of VF's when a PF dev is given + */ +static int +networkCreateInterfacePool(virNetworkDefPtr netdef) { + unsigned int num_virt_fns = 0; + char **vfname = NULL; + int ret = -1, ii = 0; + + if ((virNetDevGetVirtualFunctions(netdef->forwardPfs->dev, +&vfname,&num_virt_fns))< 0) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get Virtual functions on %s"), + netdef->forwardPfs->dev); + goto finish; + } + + if (num_virt_fns == 0) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("No Vf's present on SRIOV PF %s"), + netdef->forwardPfs->dev); + goto finish; + } + + if ((VIR_ALLOC_N(netdef->forwardIfs, num_virt_fns))< 0) { + virReportOOMError(); + goto finish; + } + + netdef->nForwardIfs = num_virt_fns; + + for (ii = 0; ii< netdef->nForwardIfs; ii++) { + netdef->forwardIfs[ii].dev = strdup(vfname[ii]); + if (!netdef->forwardIfs[ii].dev) { + virReportOOMError(); + goto finish; + } + netdef->forwardIfs[ii].usageCount = 0; + } + + ret = 0; +finish: + for (ii = 0; ii< num_virt_fns; ii++) + VIR_FREE(vfname[ii]); + VIR_FREE(vfname); + return ret; +} + /* networkAllocateActualDevice: * @iface: the original NetDef from the domain * @@ -2749,8 +2799,6 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) virNetworkObjPtr network; virNetworkDefPtr netdef; virPortGroupDefPtr portgroup; - unsigned int num_virt_fns = 0; - char **vfname = NULL; int ii; int ret = -1;
@@ -2896,36 +2944,11 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) */ if (netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) { if ((netdef->nForwardPfs> 0)&& (netdef->nForwardIfs<= 0)) { - if ((virNetDevGetVirtualFunctions(netdef->forwardPfs->dev, -&vfname,&num_virt_fns))< 0) { + if ((networkCreateInterfacePool(netdef))< 0) { networkReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not get Virtual functions on %s"), - netdef->forwardPfs->dev); + _("Could not Interface Pool")); goto cleanup; } - - if (num_virt_fns == 0) { - networkReportError(VIR_ERR_INTERNAL_ERROR, - _("No Vf's present on SRIOV PF %s"), - netdef->forwardPfs->dev); - goto cleanup; - } - - if ((VIR_ALLOC_N(netdef->forwardIfs, num_virt_fns))< 0) { - virReportOOMError(); - goto cleanup; - } - - netdef->nForwardIfs = num_virt_fns; - - for (ii = 0; ii< netdef->nForwardIfs; ii++) { - netdef->forwardIfs[ii].dev = strdup(vfname[ii]); - if (!netdef->forwardIfs[ii].dev) { - virReportOOMError(); - goto cleanup; - } - netdef->forwardIfs[ii].usageCount = 0; - } }
/* pick first dev with 0 usageCount */ @@ -2977,9 +3000,6 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
ret = 0; cleanup: - for (ii = 0; ii< num_virt_fns; ii++) - VIR_FREE(vfname[ii]); - VIR_FREE(vfname); if (network) virNetworkObjUnlock(network); if (ret< 0) {
Just move existed codes outside, and Looks good, ACK. Osier
This patch introduces the new forward mode='hostdev' along with attribute managed Includes updates to the network RNG and new xml parser/formatter code. Signed-off-by: Shradha Shah <sshah@solarflare.com> --- docs/schemas/network.rng | 82 +++++++++++++++++++-- src/conf/network_conf.c | 126 ++++++++++++++++++++++++++++---- src/conf/network_conf.h | 29 +++++++- src/network/bridge_driver.c | 18 ++-- tests/networkxml2xmlin/hostdev-pf.xml | 11 +++ tests/networkxml2xmlin/hostdev.xml | 10 +++ tests/networkxml2xmlout/hostdev-pf.xml | 7 ++ tests/networkxml2xmlout/hostdev.xml | 10 +++ tests/networkxml2xmltest.c | 2 + 9 files changed, 262 insertions(+), 33 deletions(-) diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index 2ae879e..d1297cd 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -82,17 +82,41 @@ <value>passthrough</value> <value>private</value> <value>vepa</value> + <value>hostdev</value> + </choice> + </attribute> + </optional> + + <optional> + <attribute name="managed"> + <choice> + <value>yes</value> + <value>no</value> </choice> </attribute> </optional> <interleave> - <zeroOrMore> - <element name='interface'> - <attribute name='dev'> - <ref name='deviceName'/> - </attribute> - </element> - </zeroOrMore> + <choice> + <group> + <zeroOrMore> + <element name='interface'> + <attribute name='dev'> + <ref name='deviceName'/> + </attribute> + </element> + </zeroOrMore> + </group> + <group> + <zeroOrMore> + <element name='address'> + <attribute name='type'> + <value>pci</value> + </attribute> + <ref name="pciaddress"/> + </element> + </zeroOrMore> + </group> + </choice> <optional> <element name='pf'> <attribute name='dev'> @@ -238,4 +262,48 @@ </interleave> </element> </define> + <define name="pciaddress"> + <optional> + <attribute name="domain"> + <ref name="pciDomain"/> + </attribute> + </optional> + <attribute name="bus"> + <ref name="pciBus"/> + </attribute> + <attribute name="slot"> + <ref name="pciSlot"/> + </attribute> + <attribute name="function"> + <ref name="pciFunc"/> + </attribute> + <optional> + <attribute name="multifunction"> + <choice> + <value>on</value> + <value>off</value> + </choice> + </attribute> + </optional> + </define> + <define name="pciDomain"> + <data type="string"> + <param name="pattern">(0x)?[0-9a-fA-F]{1,4}</param> + </data> + </define> + <define name="pciBus"> + <data type="string"> + <param name="pattern">(0x)?[0-9a-fA-F]{1,2}</param> + </data> + </define> + <define name="pciSlot"> + <data type="string"> + <param name="pattern">(0x)?[0-1]?[0-9a-fA-F]</param> + </data> + </define> + <define name="pciFunc"> + <data type="string"> + <param name="pattern">(0x)?[0-7]</param> + </data> + </define> </grammar> diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 60cd888..a9aa330 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -48,10 +48,14 @@ #define VIR_FROM_THIS VIR_FROM_NETWORK VIR_ENUM_DECL(virNetworkForward) - VIR_ENUM_IMPL(virNetworkForward, VIR_NETWORK_FORWARD_LAST, - "none", "nat", "route", "bridge", "private", "vepa", "passthrough" ) + "none", "nat", "route", "bridge", "private", "vepa", "passthrough", "hostdev") + +VIR_ENUM_DECL(virNetworkForwardHostdevDevice) +VIR_ENUM_IMPL(virNetworkForwardHostdevDevice, + VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST, + "none", "pci") #define virNetworkReportError(code, ...) \ virReportErrorHelper(VIR_FROM_NETWORK, code, __FILE__, \ @@ -100,6 +104,12 @@ virPortGroupDefClear(virPortGroupDefPtr def) static void virNetworkForwardIfDefClear(virNetworkForwardIfDefPtr def) { + VIR_FREE(def->device.dev); +} + +static void +virNetworkForwardPfDefClear(virNetworkForwardPfDefPtr def) +{ VIR_FREE(def->dev); } @@ -163,12 +173,13 @@ void virNetworkDefFree(virNetworkDefPtr def) VIR_FREE(def->domain); for (ii = 0 ; ii < def->nForwardPfs && def->forwardPfs ; ii++) { - virNetworkForwardIfDefClear(&def->forwardPfs[ii]); + virNetworkForwardPfDefClear(&def->forwardPfs[ii]); } VIR_FREE(def->forwardPfs); for (ii = 0 ; ii < def->nForwardIfs && def->forwardIfs ; ii++) { - virNetworkForwardIfDefClear(&def->forwardIfs[ii]); + if (def->forwardType != VIR_NETWORK_FORWARD_HOSTDEV) + virNetworkForwardIfDefClear(&def->forwardIfs[ii]); } VIR_FREE(def->forwardIfs); @@ -935,11 +946,14 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) xmlNodePtr *portGroupNodes = NULL; xmlNodePtr *forwardIfNodes = NULL; xmlNodePtr *forwardPfNodes = NULL; + xmlNodePtr *forwardAddrNodes = NULL; xmlNodePtr dnsNode = NULL; xmlNodePtr virtPortNode = NULL; xmlNodePtr forwardNode = NULL; - int nIps, nPortGroups, nForwardIfs, nForwardPfs; + int nIps, nPortGroups, nForwardIfs, nForwardPfs, nForwardAddrs; char *forwardDev = NULL; + char *forwardManaged = NULL; + char *type = NULL; xmlNodePtr save = ctxt->node; xmlNodePtr bandwidthNode = NULL; @@ -1084,17 +1098,30 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) } forwardDev = virXPathString("string(./@dev)", ctxt); + forwardManaged = virXPathString("string(./@managed)", ctxt); + if(forwardManaged != NULL) { + if (STREQ(forwardManaged, "yes")) + def->managed = 1; + else + def->managed = 0; + } /* all of these modes can use a pool of physical interfaces */ nForwardIfs = virXPathNodeSet("./interface", ctxt, &forwardIfNodes); nForwardPfs = virXPathNodeSet("./pf", ctxt, &forwardPfNodes); + nForwardAddrs = virXPathNodeSet("./address", ctxt, &forwardAddrNodes); - if (nForwardIfs < 0 || nForwardPfs < 0) { + if (nForwardIfs < 0 || nForwardPfs < 0 || nForwardAddrs < 0) { virNetworkReportError(VIR_ERR_XML_ERROR, _("No interface pool or SRIOV physical device given")); goto error; } + if ((nForwardIfs > 0) && (nForwardAddrs > 0)) { + virNetworkReportError(VIR_ERR_XML_ERROR, + _("Address and interface attributes are mutually exclusive")); + } + if (nForwardPfs == 1) { if (VIR_ALLOC_N(def->forwardPfs, nForwardPfs) < 0) { virReportOOMError(); @@ -1124,7 +1151,55 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) _("Use of more than one physical interface is not allowed")); goto error; } - if (nForwardIfs > 0 || forwardDev) { + if (nForwardAddrs > 0) { + int ii; + + if (VIR_ALLOC_N(def->forwardIfs, nForwardAddrs) < 0) { + virReportOOMError(); + goto error; + } + + if (forwardDev) { + virNetworkReportError(VIR_ERR_XML_ERROR, + _("A forward Dev should not be used when using address attribute")); + goto error; + } + + for (ii = 0; ii < nForwardAddrs; ii++) { + type = virXMLPropString(*forwardAddrNodes, "type"); + + if (type) { + if ((def->forwardIfs[ii].type = virNetworkForwardHostdevDeviceTypeFromString(type)) < 0) { + virNetworkReportError(VIR_ERR_XML_ERROR, + _("unknown address type '%s'"), type); + goto error; + } + } else { + virNetworkReportError(VIR_ERR_XML_ERROR, + "%s", _("No type specified for device address")); + goto error; + } + + switch (def->forwardIfs[ii].type) { + case VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI: + if (virDevicePCIAddressParseXML(*forwardAddrNodes, &(def->forwardIfs[ii].device.pci)) < 0) + goto error; + break; + + /* Add USB case here */ + + default: + virNetworkReportError(VIR_ERR_XML_ERROR, + _("unknown address type '%s'"), type); + goto error; + } + + def->forwardIfs[ii].usageCount = 0; + type = NULL; + def->nForwardIfs++; + } + } + else if (nForwardIfs > 0 || forwardDev) { int ii; /* allocate array to hold all the portgroups */ @@ -1135,7 +1210,8 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) if (forwardDev) { def->forwardIfs[0].usageCount = 0; - def->forwardIfs[0].dev = forwardDev; + def->forwardIfs[0].device.dev = forwardDev; + def->forwardIfs[0].type = 0; forwardDev = NULL; def->nForwardIfs++; } @@ -1153,10 +1229,10 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) if ((ii == 0) && (def->nForwardIfs == 1)) { /* both forwardDev and an interface element are present. * If they don't match, it's an error. */ - if (STRNEQ(forwardDev, def->forwardIfs[0].dev)) { + if (STRNEQ(forwardDev, def->forwardIfs[0].device.dev)) { virNetworkReportError(VIR_ERR_XML_ERROR, _("forward dev '%s' must match first interface element dev '%s' in network '%s'"), - def->forwardIfs[0].dev, + def->forwardIfs[0].device.dev, forwardDev, def->name); goto error; } @@ -1164,16 +1240,19 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) continue; } - def->forwardIfs[ii].dev = forwardDev; + def->forwardIfs[ii].device.dev = forwardDev; forwardDev = NULL; def->forwardIfs[ii].usageCount = 0; + def->forwardIfs[ii].type = 0; def->nForwardIfs++; } } + VIR_FREE(type); VIR_FREE(forwardDev); + VIR_FREE(forwardManaged); VIR_FREE(forwardPfNodes); VIR_FREE(forwardIfNodes); - + VIR_FREE(forwardAddrNodes); switch (def->forwardType) { case VIR_NETWORK_FORWARD_ROUTE: case VIR_NETWORK_FORWARD_NAT: @@ -1198,6 +1277,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) case VIR_NETWORK_FORWARD_PRIVATE: case VIR_NETWORK_FORWARD_VEPA: case VIR_NETWORK_FORWARD_PASSTHROUGH: + case VIR_NETWORK_FORWARD_HOSTDEV: if (def->bridge) { virNetworkReportError(VIR_ERR_XML_ERROR, _("bridge name not allowed in %s mode (network '%s')"), @@ -1483,6 +1563,12 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags) } virBufferAddLit(&buf, " <forward"); virBufferEscapeString(&buf, " dev='%s'", dev); + if (def->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) { + if (def->managed == 1) + virBufferAddLit(&buf, " managed='yes'"); + else + virBufferAddLit(&buf, " managed='no'"); + } virBufferAsprintf(&buf, " mode='%s'%s>\n", mode, (def->nForwardIfs || def->nForwardPfs) ? "" : "/"); @@ -1494,8 +1580,20 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags) if (def->nForwardIfs && (!def->nForwardPfs || !(flags & VIR_NETWORK_XML_INACTIVE))) { for (ii = 0; ii < def->nForwardIfs; ii++) { - virBufferEscapeString(&buf, " <interface dev='%s'/>\n", - def->forwardIfs[ii].dev); + if (def->forwardType != VIR_NETWORK_FORWARD_HOSTDEV) + virBufferEscapeString(&buf, " <interface dev='%s'/>\n", + def->forwardIfs[ii].device.dev); + else { + if (def->forwardIfs[ii].type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) { + if (virDevicePCIAddressFormat(&buf, + def->forwardIfs[ii].device.pci, + true) < 0) { + virNetworkReportError(VIR_ERR_INTERNAL_ERROR, + _("PCI address format failed")); + goto error; + } + } + } } } if (def->nForwardPfs || def->nForwardIfs) diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 4339a69..b1a7ddd 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -36,6 +36,7 @@ # include "virnetdevbandwidth.h" # include "virnetdevvportprofile.h" # include "virmacaddr.h" +# include "device_conf.h" enum virNetworkForwardType { VIR_NETWORK_FORWARD_NONE = 0, @@ -45,10 +46,19 @@ enum virNetworkForwardType { VIR_NETWORK_FORWARD_PRIVATE, VIR_NETWORK_FORWARD_VEPA, VIR_NETWORK_FORWARD_PASSTHROUGH, + VIR_NETWORK_FORWARD_HOSTDEV, VIR_NETWORK_FORWARD_LAST, }; +enum virNetworkForwardHostdevDeviceType { + VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NONE = 0, + VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI, + /* USB Device to be added here when supported */ + + VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST, +}; + typedef struct _virNetworkDHCPRangeDef virNetworkDHCPRangeDef; typedef virNetworkDHCPRangeDef *virNetworkDHCPRangeDefPtr; struct _virNetworkDHCPRangeDef { @@ -131,7 +141,19 @@ struct _virNetworkIpDef { typedef struct _virNetworkForwardIfDef virNetworkForwardIfDef; typedef virNetworkForwardIfDef *virNetworkForwardIfDefPtr; struct _virNetworkForwardIfDef { - char *dev; /* name of device */ + int type; + union { + virDevicePCIAddress pci; /*PCI Address of device */ + /* when USB devices are supported a new variable to be added here */ + char *dev; /* name of device */ + }device; + int usageCount; /* how many guest interfaces are bound to this device? */ +}; + +typedef struct _virNetworkForwardPfDef virNetworkForwardPfDef; +typedef virNetworkForwardPfDef *virNetworkForwardPfDefPtr; +struct _virNetworkForwardPfDef { + char *dev; /* name of device */ int usageCount; /* how many guest interfaces are bound to this device? */ }; @@ -158,12 +180,13 @@ struct _virNetworkDef { bool mac_specified; int forwardType; /* One of virNetworkForwardType constants */ + int managed; /* managed attribute for hostdev mode */ /* If there are multiple forward devices (i.e. a pool of * interfaces), they will be listed here. */ size_t nForwardPfs; - virNetworkForwardIfDefPtr forwardPfs; + virNetworkForwardPfDefPtr forwardPfs; size_t nForwardIfs; virNetworkForwardIfDefPtr forwardIfs; @@ -233,7 +256,7 @@ static inline const char * virNetworkDefForwardIf(const virNetworkDefPtr def, size_t n) { return ((def->forwardIfs && (def->nForwardIfs > n)) - ? def->forwardIfs[n].dev : NULL); + ? def->forwardIfs[n].device.dev : NULL); } virPortGroupDefPtr virPortGroupFindByName(virNetworkDefPtr net, diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 7d853c6..630a655 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2765,8 +2765,8 @@ networkCreateInterfacePool(virNetworkDefPtr netdef) { netdef->nForwardIfs = num_virt_fns; for (ii = 0; ii < netdef->nForwardIfs; ii++) { - netdef->forwardIfs[ii].dev = strdup(vfname[ii]); - if (!netdef->forwardIfs[ii].dev) { + netdef->forwardIfs[ii].device.dev = strdup(vfname[ii]); + if (!netdef->forwardIfs[ii].device.dev) { virReportOOMError(); goto finish; } @@ -2986,7 +2986,7 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) netdef->name); goto cleanup; } - iface->data.network.actual->data.direct.linkdev = strdup(dev->dev); + iface->data.network.actual->data.direct.linkdev = strdup(dev->device.dev); if (!iface->data.network.actual->data.direct.linkdev) { virReportOOMError(); goto cleanup; @@ -2994,7 +2994,7 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) /* we are now assured of success, so mark the allocation */ dev->usageCount++; VIR_DEBUG("Using physical device %s, usageCount %d", - dev->dev, dev->usageCount); + dev->device.dev, dev->usageCount); } } @@ -3067,7 +3067,7 @@ networkNotifyActualDevice(virDomainNetDefPtr iface) /* find the matching interface in the pool and increment its usageCount */ for (ii = 0; ii < netdef->nForwardIfs; ii++) { - if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) { + if (STREQ(actualDev, netdef->forwardIfs[ii].device.dev)) { dev = &netdef->forwardIfs[ii]; break; } @@ -3098,7 +3098,7 @@ networkNotifyActualDevice(virDomainNetDefPtr iface) /* we are now assured of success, so mark the allocation */ dev->usageCount++; VIR_DEBUG("Using physical device %s, usageCount %d", - dev->dev, dev->usageCount); + dev->device.dev, dev->usageCount); } ret = 0; @@ -3166,7 +3166,7 @@ networkReleaseActualDevice(virDomainNetDefPtr iface) virNetworkForwardIfDefPtr dev = NULL; for (ii = 0; ii < netdef->nForwardIfs; ii++) { - if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) { + if (STREQ(actualDev, netdef->forwardIfs[ii].device.dev)) { dev = &netdef->forwardIfs[ii]; break; } @@ -3181,7 +3181,7 @@ networkReleaseActualDevice(virDomainNetDefPtr iface) dev->usageCount--; VIR_DEBUG("Releasing physical device %s, usageCount %d", - dev->dev, dev->usageCount); + dev->device.dev, dev->usageCount); } ret = 0; @@ -3262,7 +3262,7 @@ networkGetNetworkAddress(const char *netname, char **netaddr) case VIR_NETWORK_FORWARD_VEPA: case VIR_NETWORK_FORWARD_PASSTHROUGH: if ((netdef->nForwardIfs > 0) && netdef->forwardIfs) - dev_name = netdef->forwardIfs[0].dev; + dev_name = netdef->forwardIfs[0].device.dev; if (!dev_name) { networkReportError(VIR_ERR_INTERNAL_ERROR, diff --git a/tests/networkxml2xmlin/hostdev-pf.xml b/tests/networkxml2xmlin/hostdev-pf.xml new file mode 100644 index 0000000..e07db69 --- /dev/null +++ b/tests/networkxml2xmlin/hostdev-pf.xml @@ -0,0 +1,11 @@ +<network> + <name>hostdev</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward mode="hostdev" managed="yes"> + <pf dev='eth2'/> + <address type='pci' domain='0' bus='3' slot='0' function='1'/> + <address type='pci' domain='0' bus='3' slot='0' function='2'/> + <address type='pci' domain='0' bus='3' slot='0' function='3'/> + <address type='pci' domain='0' bus='3' slot='0' function='4'/> + </forward> +</network> diff --git a/tests/networkxml2xmlin/hostdev.xml b/tests/networkxml2xmlin/hostdev.xml new file mode 100644 index 0000000..0ec52d2 --- /dev/null +++ b/tests/networkxml2xmlin/hostdev.xml @@ -0,0 +1,10 @@ +<network> + <name>hostdev</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward mode="hostdev" managed="yes"> + <address type='pci' domain='0' bus='3' slot='0' function='1'/> + <address type='pci' domain='0' bus='3' slot='0' function='2'/> + <address type='pci' domain='0' bus='3' slot='0' function='3'/> + <address type='pci' domain='0' bus='3' slot='0' function='4'/> + </forward> +</network> diff --git a/tests/networkxml2xmlout/hostdev-pf.xml b/tests/networkxml2xmlout/hostdev-pf.xml new file mode 100644 index 0000000..e955312 --- /dev/null +++ b/tests/networkxml2xmlout/hostdev-pf.xml @@ -0,0 +1,7 @@ +<network> + <name>hostdev</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward mode="hostdev" managed="yes"> + <pf dev='eth2'/> + </forward> +</network> diff --git a/tests/networkxml2xmlout/hostdev.xml b/tests/networkxml2xmlout/hostdev.xml new file mode 100644 index 0000000..0ec52d2 --- /dev/null +++ b/tests/networkxml2xmlout/hostdev.xml @@ -0,0 +1,10 @@ +<network> + <name>hostdev</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward mode="hostdev" managed="yes"> + <address type='pci' domain='0' bus='3' slot='0' function='1'/> + <address type='pci' domain='0' bus='3' slot='0' function='2'/> + <address type='pci' domain='0' bus='3' slot='0' function='3'/> + <address type='pci' domain='0' bus='3' slot='0' function='4'/> + </forward> +</network> diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c index 8641c41..c9c8311 100644 --- a/tests/networkxml2xmltest.c +++ b/tests/networkxml2xmltest.c @@ -105,6 +105,8 @@ mymain(void) DO_TEST("vepa-net"); DO_TEST("bandwidth-network"); DO_TEST_FULL("passthrough-pf", VIR_NETWORK_XML_INACTIVE); + DO_TEST("hostdev"); + DO_TEST_FULL("hostdev-pf", VIR_NETWORK_XML_INACTIVE); return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.7.4.4
The network pool should be able to keep track of both, network device names nad PCI addresses, and return the appropriate one in the actualDevice when networkAllocateActualDevice is called. Signed-off-by: Shradha Shah <sshah@solarflare.com> --- src/network/bridge_driver.c | 33 +++++++++++++++++++++++++++------ src/util/virnetdev.c | 29 ++++++++++++++++------------- src/util/virnetdev.h | 4 +++- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 630a655..6ce41b5 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -60,6 +60,7 @@ #include "configmake.h" #include "ignore-value.h" #include "virnetdev.h" +#include "pci.h" #include "virnetdevbridge.h" #include "virnetdevtap.h" @@ -2740,10 +2741,11 @@ static int networkCreateInterfacePool(virNetworkDefPtr netdef) { unsigned int num_virt_fns = 0; char **vfname = NULL; + struct pci_config_address **virt_fns; int ret = -1, ii = 0; if ((virNetDevGetVirtualFunctions(netdef->forwardPfs->dev, - &vfname, &num_virt_fns)) < 0) { + &vfname, &virt_fns, &num_virt_fns)) < 0) { networkReportError(VIR_ERR_INTERNAL_ERROR, _("Could not get Virtual functions on %s"), netdef->forwardPfs->dev); @@ -2765,19 +2767,38 @@ networkCreateInterfacePool(virNetworkDefPtr netdef) { netdef->nForwardIfs = num_virt_fns; for (ii = 0; ii < netdef->nForwardIfs; ii++) { - netdef->forwardIfs[ii].device.dev = strdup(vfname[ii]); - if (!netdef->forwardIfs[ii].device.dev) { - virReportOOMError(); - goto finish; + if (netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) { + if(vfname[ii]) { + netdef->forwardIfs[ii].device.dev = strdup(vfname[ii]); + if (!netdef->forwardIfs[ii].device.dev) { + virReportOOMError(); + goto finish; + } + } + else { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("Passthrough mode requires interface names")); + goto finish; + } + } + else if (netdef->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) { + 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; + netdef->forwardIfs[ii].device.pci.slot = virt_fns[ii]->slot; + netdef->forwardIfs[ii].device.pci.function = virt_fns[ii]->function; } netdef->forwardIfs[ii].usageCount = 0; } ret = 0; finish: - for (ii = 0; ii < num_virt_fns; ii++) + for (ii = 0; ii < num_virt_fns; ii++) { VIR_FREE(vfname[ii]); + VIR_FREE(virt_fns[ii]); + } VIR_FREE(vfname); + VIR_FREE(virt_fns); return ret; } diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index d53352f..a59012f 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -983,18 +983,19 @@ virNetDevSysfsDeviceFile(char **pf_sysfs_device_link, const char *ifname, int virNetDevGetVirtualFunctions(const char *pfname, char ***vfname, + struct pci_config_address ***virt_fns, unsigned int *n_vfname) { int ret = -1, i; char *pf_sysfs_device_link = NULL; char *pci_sysfs_device_link = NULL; - struct pci_config_address **virt_fns; +// struct pci_config_address **virt_fns; char *pciConfigAddr; if (virNetDevSysfsFile(&pf_sysfs_device_link, pfname, "device") < 0) return ret; - if (pciGetVirtualFunctions(pf_sysfs_device_link, &virt_fns, + if (pciGetVirtualFunctions(pf_sysfs_device_link, virt_fns, n_vfname) < 0) goto cleanup; @@ -1005,10 +1006,10 @@ virNetDevGetVirtualFunctions(const char *pfname, for (i = 0; i < *n_vfname; i++) { - if (pciGetDeviceAddrString(virt_fns[i]->domain, - virt_fns[i]->bus, - virt_fns[i]->slot, - virt_fns[i]->function, + if (pciGetDeviceAddrString((*virt_fns)[i]->domain, + (*virt_fns)[i]->bus, + (*virt_fns)[i]->slot, + (*virt_fns)[i]->function, &pciConfigAddr) < 0) { virReportSystemError(ENOSYS, "%s", _("Failed to get PCI Config Address String")); @@ -1021,20 +1022,21 @@ virNetDevGetVirtualFunctions(const char *pfname, } if (pciDeviceNetName(pci_sysfs_device_link, &((*vfname)[i])) < 0) { - virReportSystemError(ENOSYS, "%s", - _("Failed to get interface name of the VF")); - goto cleanup; + virReportSystemError(ENODATA, "%s", + _("VF does not have an interface name")); } } ret = 0; cleanup: - if (ret < 0) + if (ret < 0) { VIR_FREE(*vfname); - for (i = 0; i < *n_vfname; i++) - VIR_FREE(virt_fns[i]); - VIR_FREE(virt_fns); + VIR_FREE(*virt_fns); + } + //for (i = 0; i < *n_vfname; i++) + // VIR_FREE(virt_fns[i]); + //VIR_FREE(virt_fns); VIR_FREE(pf_sysfs_device_link); VIR_FREE(pci_sysfs_device_link); VIR_FREE(pciConfigAddr); @@ -1171,6 +1173,7 @@ cleanup: int virNetDevGetVirtualFunctions(const char *pfname ATTRIBUTE_UNUSED, char ***vfname ATTRIBUTE_UNUSED, + struct pci_config_address ***virt_fns ATTRIBUTE_UNUSED, unsigned int *n_vfname ATTRIBUTE_UNUSED) { virReportSystemError(ENOSYS, "%s", diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index 660d2db..9be367c 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -25,6 +25,7 @@ # include "virsocketaddr.h" # include "virnetlink.h" +# include "pci.h" int virNetDevExists(const char *brname) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; @@ -102,9 +103,10 @@ int virNetDevGetPhysicalFunction(const char *ifname, char **pfname) int virNetDevGetVirtualFunctions(const char *pfname, char ***vfname, + struct pci_config_address ***virt_fns, unsigned int *n_vfname) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) - ATTRIBUTE_RETURN_CHECK; + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; int virNetDevLinkDump(const char *ifname, int ifindex, struct nlattr **tb, -- 1.7.4.4
This patch updates the network driver to properly utilize the new attributes/elements that are now in virNetworkDef Signed-off-by: Shradha Shah <sshah@solarflare.com> --- docs/formatnetwork.html.in | 62 +++++++++++++ src/network/bridge_driver.c | 213 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 240 insertions(+), 35 deletions(-) diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in index 7e8e991..96b9eb2 100644 --- a/docs/formatnetwork.html.in +++ b/docs/formatnetwork.html.in @@ -210,6 +210,37 @@ (usually either a domain start, or a hotplug interface attach to a domain).<span class="since">Since 0.9.4</span> </dd> + <dt><code>hostdev</code></dt> + <dd> + This network facilitates PCI Passthrough of a network device. + A network device is chosen from the interface pool and + directly assigned to the guest using generic device + passthrough, after first optionally setting the device's MAC + address to the configured value, and associating the device with + an 802.1Qbh capable switch using an optionally specified + <code><virtualport></code> element. + Note that - due to limitations in standard single-port PCI + ethernet card driver design - only SR-IOV (Single Root I/O + Virtualization) virtual function (VF) devices can be assigned + in this manner; to assign a standard single-port PCI or PCIe + ethernet card to a guest, use the traditional <code>< + hostdev></code> device definition and <span class="since"> + Since 0.9.12</span> + + <p>Note that this "intelligent passthrough" of network devices is + very similar to the functionality of a standard <code>< + hostdev></code> device, the difference being that this + method allows specifying a MAC address and <code><virtualport + ></code> for the passed-through device. If these capabilities + are not required, if you have a standard single-port PCI, PCIe, + or USB network card that doesn't support SR-IOV (and hence would + anyway lose the configured MAC address during reset after being + assigned to the guest domain), or if you are using a version of + libvirt older than 0.9.12, you should use standard + <code><hostdev></code> to assign the device to the + guest instead of <code><forward mode='hostdev'/></code>. + </p> + </dd> </dl> As mentioned above, a <code><forward></code> element can have multiple <code><interface></code> subelements, each @@ -249,6 +280,37 @@ particular, 'passthrough' mode, and 'private' mode when using 802.1Qbh), libvirt will choose an unused physical interface or, if it can't find an unused interface, fail the operation.</p> + + <span class="since">since 0.9.12</span> and when using forward mode + 'hostdev' we specify the interface pool by using the + <code><address></code> element and <code>< + type></code> <code><domain></code> <code><bus></code> + <code><slot></code> and <code><function></code> + sub-elements. + + <pre> +... + <forward mode='hostdev' managed='yes'> + <address type='pci' domain='0' bus='4' slot='0' function='1'/> + <address type='pci' domain='0' bus='4' slot='0' function='2'/> + <address type='pci' domain='0' bus='4' slot='0' function='3'/> + </forward> +... + </pre> + + Alternatively the interface pool can also be mentioned using a + single physical function <code><pf></code> subelement to + call out the corresponding physical interface associated with + multiple virtual interfaces (similar to the passthrough mode): + + <pre> +... + <forward mode='hostdev' managed='yes'> + <pf dev='eth0'/> + </forward> +... + </pre> + </dd> </dl> <h5><a name="elementQoS">Quality of service</a></h5> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 6ce41b5..35636a8 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -1939,7 +1939,7 @@ 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, or PASSTHROUGH is started. On + * type BRIDGE, PRIVATE, VEPA, HOSTDEV or PASSTHROUGH is started. On * failure, undo anything you've done, and return -1. On success * return 0. */ @@ -1950,7 +1950,7 @@ 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, or PASSTHROUGH is shutdown. On + * type BRIDGE, PRIVATE, VEPA, HOSTDEV or PASSTHROUGH is shutdown. On * failure, undo anything you've done, and return -1. On success * return 0. */ @@ -1981,6 +1981,7 @@ networkStartNetwork(struct network_driver *driver, case VIR_NETWORK_FORWARD_PRIVATE: case VIR_NETWORK_FORWARD_VEPA: case VIR_NETWORK_FORWARD_PASSTHROUGH: + case VIR_NETWORK_FORWARD_HOSTDEV: ret = networkStartNetworkExternal(driver, network); break; } @@ -2040,6 +2041,7 @@ static int networkShutdownNetwork(struct network_driver *driver, case VIR_NETWORK_FORWARD_PRIVATE: case VIR_NETWORK_FORWARD_VEPA: case VIR_NETWORK_FORWARD_PASSTHROUGH: + case VIR_NETWORK_FORWARD_HOSTDEV: ret = networkShutdownNetworkExternal(driver, network); break; } @@ -2781,7 +2783,7 @@ networkCreateInterfacePool(virNetworkDefPtr netdef) { goto finish; } } - else if (netdef->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) { + if (netdef->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) { 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; @@ -2820,6 +2822,8 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) virNetworkObjPtr network; virNetworkDefPtr netdef; virPortGroupDefPtr portgroup; + virNetDevVPortProfilePtr virtport = NULL; + virNetworkForwardIfDefPtr dev = NULL; int ii; int ret = -1; @@ -2872,6 +2876,7 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) */ if (iface->data.network.actual) iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_NETWORK; + } else if ((netdef->forwardType == VIR_NETWORK_FORWARD_BRIDGE) && netdef->bridge) { @@ -2892,11 +2897,74 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) goto cleanup; } + } else if (netdef->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) { + 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; + if ((netdef->nForwardPfs > 0) && (netdef->nForwardIfs <= 0)) { + if(networkCreateInterfacePool(netdef) < 0) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + _("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) { + networkReportError(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_NET; + iface->data.network.actual->data.hostdev.def.parent.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; + 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 (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) || (netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH)) { - virNetDevVPortProfilePtr virtport = NULL; /* <forward type='bridge|private|vepa|passthrough'> are all * VIR_DOMAIN_NET_TYPE_DIRECT. @@ -2954,7 +3022,6 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) netdef->name); goto cleanup; } else { - virNetworkForwardIfDefPtr dev = NULL; /* pick an interface from the pool */ @@ -3046,14 +3113,16 @@ networkNotifyActualDevice(virDomainNetDefPtr iface) struct network_driver *driver = driverState; virNetworkObjPtr network; virNetworkDefPtr netdef; - const char *actualDev; + const char *actualDev = NULL; + virDomainHostdevDefPtr def = NULL; int ret = -1; if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) return 0; if (!iface->data.network.actual || - (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_DIRECT)) { + ((virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_DIRECT) && + (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_HOSTDEV))) { VIR_DEBUG("Nothing to claim from network %s", iface->data.network.name); return 0; } @@ -3068,17 +3137,28 @@ networkNotifyActualDevice(virDomainNetDefPtr iface) goto cleanup; } - actualDev = virDomainNetGetActualDirectDev(iface); - if (!actualDev) { - networkReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("the interface uses a direct mode, but has no source dev")); - goto cleanup; + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_DIRECT) { + actualDev = virDomainNetGetActualDirectDev(iface); + if (!actualDev) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("the interface uses a direct mode, but has no source dev")); + goto cleanup; + } + } + + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) { + def = virDomainNetGetActualHostdev(iface); + if (!def) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("the interface uses a hostdev mode, but has no hostdev")); + goto cleanup; + } } netdef = network->def; if (netdef->nForwardIfs == 0) { networkReportError(VIR_ERR_INTERNAL_ERROR, - _("network '%s' uses a direct mode, but has no forward dev and no interface pool"), + _("network '%s' uses a direct/hostdev mode, but has no forward dev and no interface pool"), netdef->name); goto cleanup; } else { @@ -3086,13 +3166,27 @@ networkNotifyActualDevice(virDomainNetDefPtr iface) virNetworkForwardIfDefPtr dev = NULL; /* find the matching interface in the pool and increment its usageCount */ + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_DIRECT) { + for (ii = 0; ii < netdef->nForwardIfs; ii++) { + if (STREQ(actualDev, netdef->forwardIfs[ii].device.dev)) { + dev = &netdef->forwardIfs[ii]; + break; + } + } + } - for (ii = 0; ii < netdef->nForwardIfs; ii++) { - if (STREQ(actualDev, netdef->forwardIfs[ii].device.dev)) { - dev = &netdef->forwardIfs[ii]; - break; + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) { + 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) && + (def->source.subsys.u.pci.slot == netdef->forwardIfs[ii].device.pci.slot) && + (def->source.subsys.u.pci.function == netdef->forwardIfs[ii].device.pci.function)) { + dev = &netdef->forwardIfs[ii]; + break; + } } } + /* dev points at the physical device we want to use */ if (!dev) { networkReportError(VIR_ERR_INTERNAL_ERROR, @@ -3107,6 +3201,7 @@ networkNotifyActualDevice(virDomainNetDefPtr iface) */ if ((dev->usageCount > 0) && ((netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) || + (netdef->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) || ((netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE) && iface->data.network.actual->data.direct.virtPortProfile && (iface->data.network.actual->data.direct.virtPortProfile->virtPortType @@ -3118,8 +3213,18 @@ networkNotifyActualDevice(virDomainNetDefPtr iface) } /* we are now assured of success, so mark the allocation */ dev->usageCount++; - VIR_DEBUG("Using physical device %s, usageCount %d", - dev->device.dev, dev->usageCount); + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_DIRECT) { + VIR_DEBUG("Using physical device %s, usageCount %d", + dev->device.dev, dev->usageCount); + } + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) { + 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); + } } ret = 0; @@ -3146,14 +3251,16 @@ networkReleaseActualDevice(virDomainNetDefPtr iface) struct network_driver *driver = driverState; virNetworkObjPtr network = NULL; virNetworkDefPtr netdef; - const char *actualDev; + const char *actualDev = NULL; + virDomainHostdevDefPtr def = NULL; int ret = -1; if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) return 0; if (!iface->data.network.actual || - (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_DIRECT)) { + ((virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_DIRECT) && + (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_HOSTDEV))) { VIR_DEBUG("Nothing to release to network %s", iface->data.network.name); ret = 0; goto cleanup; @@ -3169,29 +3276,55 @@ networkReleaseActualDevice(virDomainNetDefPtr iface) goto cleanup; } - actualDev = virDomainNetGetActualDirectDev(iface); - if (!actualDev) { - networkReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("the interface uses a direct mode, but has no source dev")); - goto cleanup; + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_DIRECT) { + actualDev = virDomainNetGetActualDirectDev(iface); + if (!actualDev) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("the interface uses a direct mode, but has no source dev")); + goto cleanup; + } + } + + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) { + def = virDomainNetGetActualHostdev(iface); + if (!def) { + networkReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("the interface uses a hostdev mode, but has no hostdev")); + goto cleanup; + } } netdef = network->def; if (netdef->nForwardIfs == 0) { networkReportError(VIR_ERR_INTERNAL_ERROR, - _("network '%s' uses a direct mode, but has no forward dev and no interface pool"), + _("network '%s' uses a direct/hostdev mode, but has no forward dev and no interface pool"), netdef->name); goto cleanup; } else { int ii; virNetworkForwardIfDefPtr dev = NULL; - - for (ii = 0; ii < netdef->nForwardIfs; ii++) { - if (STREQ(actualDev, netdef->forwardIfs[ii].device.dev)) { - dev = &netdef->forwardIfs[ii]; - break; + + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_DIRECT) { + for (ii = 0; ii < netdef->nForwardIfs; ii++) { + if (STREQ(actualDev, netdef->forwardIfs[ii].device.dev)) { + dev = &netdef->forwardIfs[ii]; + break; + } + } + } + + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) { + 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) && + (def->source.subsys.u.pci.slot == netdef->forwardIfs[ii].device.pci.slot) && + (def->source.subsys.u.pci.function == netdef->forwardIfs[ii].device.pci.function)) { + dev = &netdef->forwardIfs[ii]; + break; + } } } + /* dev points at the physical device we've been using */ if (!dev) { networkReportError(VIR_ERR_INTERNAL_ERROR, @@ -3201,10 +3334,20 @@ networkReleaseActualDevice(virDomainNetDefPtr iface) } dev->usageCount--; - VIR_DEBUG("Releasing physical device %s, usageCount %d", - dev->device.dev, dev->usageCount); + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_DIRECT) { + VIR_DEBUG("Releasing physical device %s, usageCount %d", + dev->device.dev, dev->usageCount); + } + if (virDomainNetGetActualType(iface) == VIR_DOMAIN_NET_TYPE_HOSTDEV) { + VIR_DEBUG("Releasing 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); + } } - + ret = 0; cleanup: if (network) -- 1.7.4.4
Signed-off-by: Shradha Shah <sshah@solarflare.com> --- src/qemu/qemu_command.c | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 93c018d..0f6b714 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5030,6 +5030,20 @@ qemuBuildCommandLine(virConnectPtr conn, * code here that adds the newly minted hostdev to the * hostdevs array). */ + if (qemuAssignDeviceHostdevAlias(def, + virDomainNetGetActualHostdev(net), + (def->nhostdevs-1)) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not assign alias to Net Hostdev")); + goto error; + } + + if (virDomainHostdevInsert(def, + virDomainNetGetActualHostdev(net)) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Hostdev not inserted into the array")); + goto error; + } continue; } -- 1.7.4.4
participants (3)
-
Laine Stump -
Osier Yang -
Shradha Shah