[libvirt] [PATCH 0/6 v3] 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 ++++++++- include/libvirt/virterror.h | 1 + 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 + 28 files changed, 890 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> --- include/libvirt/virterror.h | 1 + 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 +- 16 files changed, 289 insertions(+), 180 deletions(-) diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 0e0bc9c..7ad1201 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -97,6 +97,7 @@ typedef enum { VIR_FROM_URI = 45, /* Error from URI handling */ VIR_FROM_AUTH = 46, /* Error from auth handling */ VIR_FROM_DBUS = 47, /* Error from DBus */ + VIR_FROM_DEVICE = 48, /* Error from Device */ # ifdef VIR_ENUM_SENTINELS VIR_ERR_DOMAIN_LAST diff --git a/src/Makefile.am b/src/Makefile.am index 2309984..7ffb3c2 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 = \ @@ -1526,6 +1530,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..d4eb764 --- /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_DEVICE, 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 4086dac..0e12b03 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -52,6 +52,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 @@ -151,12 +152,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", @@ -1903,7 +1898,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; @@ -1915,16 +1910,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) { @@ -2148,7 +2133,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; @@ -2196,75 +2181,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) { @@ -2625,7 +2541,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; @@ -2673,7 +2589,7 @@ cleanup: static int virDomainParseLegacyDeviceAddress(char *devaddr, - virDomainDevicePCIAddressPtr pci) + virDevicePCIAddressPtr pci) { char *tmp; @@ -2858,10 +2774,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")) { @@ -11426,14 +11342,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 || @@ -11446,7 +11360,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 964ec38..7db8e7a 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2563,8 +2563,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")); @@ -2575,7 +2575,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")); @@ -2585,7 +2585,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")); @@ -2594,7 +2594,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")); @@ -2851,7 +2851,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")); @@ -2890,7 +2890,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

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 7e8de19..36afa1b 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2730,6 +2730,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 * @@ -2748,8 +2798,6 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) virNetworkObjPtr network; virNetworkDefPtr netdef; virPortGroupDefPtr portgroup; - unsigned int num_virt_fns = 0; - char **vfname = NULL; int ii; int ret = -1; @@ -2895,36 +2943,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 */ @@ -2976,9 +2999,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

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 515bc36..be37856 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 36afa1b..230012c 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2764,8 +2764,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; } @@ -2985,7 +2985,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; @@ -2993,7 +2993,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); } } @@ -3066,7 +3066,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; } @@ -3097,7 +3097,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; @@ -3165,7 +3165,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; } @@ -3180,7 +3180,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; @@ -3261,7 +3261,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 230012c..2f8a937 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -59,6 +59,7 @@ #include "dnsmasq.h" #include "configmake.h" #include "virnetdev.h" +#include "pci.h" #include "virnetdevbridge.h" #include "virnetdevtap.h" @@ -2739,10 +2740,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); @@ -2764,19 +2766,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 2f8a937..c2c763a 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -1938,7 +1938,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. */ @@ -1949,7 +1949,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. */ @@ -1980,6 +1980,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; } @@ -2039,6 +2040,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; } @@ -2780,7 +2782,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; @@ -2819,6 +2821,8 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) virNetworkObjPtr network; virNetworkDefPtr netdef; virPortGroupDefPtr portgroup; + virNetDevVPortProfilePtr virtport = NULL; + virNetworkForwardIfDefPtr dev = NULL; int ii; int ret = -1; @@ -2871,6 +2875,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) { @@ -2891,11 +2896,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. @@ -2953,7 +3021,6 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) netdef->name); goto cleanup; } else { - virNetworkForwardIfDefPtr dev = NULL; /* pick an interface from the pool */ @@ -3045,14 +3112,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; } @@ -3067,17 +3136,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 { @@ -3085,13 +3165,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, @@ -3106,6 +3200,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 @@ -3117,8 +3212,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; @@ -3145,14 +3250,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; @@ -3168,29 +3275,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, @@ -3200,10 +3333,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

Hello All, May I request a review for this patch series that supports forward mode='hostdev' with interface pools? Many Thanks, Regards, Shradha Shah On 06/29/2012 01:19 PM, Shradha Shah wrote:
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 ++++++++- include/libvirt/virterror.h | 1 + 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 + 28 files changed, 890 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

On 07/26/2012 06:21 AM, Shradha Shah wrote:
Hello All,
May I request a review for this patch series that supports forward mode='hostdev' with interface pools?
Sorry for keeping you up in the air for so long. This has been on my list since I got back from vacation, but something else always seems to come up. I'll try to go through it today.

That's fine. Thanks. Just wanted to ping the list once and keep these patches in the loop. Many Thanks, Regards, Shradha Shah On 07/26/2012 02:59 PM, Laine Stump wrote:
On 07/26/2012 06:21 AM, Shradha Shah wrote:
Hello All,
May I request a review for this patch series that supports forward mode='hostdev' with interface pools?
Sorry for keeping you up in the air for so long. This has been on my list since I got back from vacation, but something else always seems to come up. I'll try to go through it today.
participants (2)
-
Laine Stump
-
Shradha Shah