diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index bf809bb31d..eed13a0579 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" #include "virnetdevvportprofile.h" @@ -2780,10 +2781,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) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not get Virtual functions on %s"), netdef->forwardPfs->dev); @@ -2805,18 +2807,34 @@ 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_BRIDGE) || + (netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE) || + (netdef->forwardType == VIR_NETWORK_FORWARD_VEPA) || + (netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH)) { + netdef->forwardIfs[ii].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV; + if(vfname[ii]) { + netdef->forwardIfs[ii].device.dev = strdup(vfname[ii]); + if (!netdef->forwardIfs[ii].device.dev) { + virReportOOMError(); + goto finish; + } + } + else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Direct mode types requires interface names")); + goto finish; + } } } 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; } @@ -3008,31 +3026,22 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) } else { /* pick an interface from the pool */ + if (netdef->nForwardPfs > 0 && netdef->nForwardIfs == 0 && + networkCreateInterfacePool(netdef) < 0) { + goto error; + } + /* PASSTHROUGH mode, and PRIVATE Mode + 802.1Qbh both * require exclusive access to a device, so current * connections count must be 0. Other modes can share, so * just search for the one with the lowest number of * connections. */ - if (netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) { - if ((netdef->nForwardPfs > 0) && (netdef->nForwardIfs <= 0)) { - if ((networkCreateInterfacePool(netdef)) < 0) { - goto error; - } - } - - /* pick first dev with 0 connections */ - - for (ii = 0; ii < netdef->nForwardIfs; ii++) { - if (netdef->forwardIfs[ii].connections == 0) { - dev = &netdef->forwardIfs[ii]; - break; - } - } - } else if ((netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE) && - iface->data.network.actual->virtPortProfile && - (iface->data.network.actual->virtPortProfile->virtPortType - == VIR_NETDEV_VPORT_PROFILE_8021QBH)) { + if ((netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) || + ((netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE) && + iface->data.network.actual->virtPortProfile && + (iface->data.network.actual->virtPortProfile->virtPortType + == VIR_NETDEV_VPORT_PROFILE_8021QBH))) { /* pick first dev with 0 connections */ for (ii = 0; ii < netdef->nForwardIfs; ii++) { diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index 25bdf01e8c..f9eba1afb5 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -29,6 +29,7 @@ #include "command.h" #include "memory.h" #include "pci.h" +#include "logging.h" #include #ifdef HAVE_NET_IF_H @@ -981,18 +982,18 @@ 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; 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; @@ -1003,10 +1004,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")); @@ -1019,20 +1020,17 @@ 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; + VIR_INFO("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); + } VIR_FREE(pf_sysfs_device_link); VIR_FREE(pci_sysfs_device_link); VIR_FREE(pciConfigAddr); @@ -1169,6 +1167,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 c663e49a8d..705ad9c490 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -26,6 +26,7 @@ # include "virsocketaddr.h" # include "virnetlink.h" # include "virmacaddr.h" +# include "pci.h" int virNetDevExists(const char *brname) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; @@ -103,9 +104,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,