diff --git a/src/util/pci.c b/src/util/pci.c index 5e09c2fb91..17cde81bf9 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -1293,6 +1293,30 @@ pciReadDeviceID(pciDevice *dev, const char *id_name) return id_str; } +int +pciGetDeviceAddrString(unsigned domain, + unsigned bus, + unsigned slot, + unsigned function, + char **pciConfigAddr) +{ + pciDevice *dev = NULL; + int ret = -1; + + dev = pciGetDevice(domain, bus, slot, function); + if (dev != NULL) { + if ((*pciConfigAddr = strdup(dev->name)) == NULL) { + virReportOOMError(); + goto cleanup; + } + ret = 0; + } + +cleanup: + pciFreeDevice(dev); + return ret; +} + pciDevice * pciGetDevice(unsigned domain, unsigned bus, diff --git a/src/util/pci.h b/src/util/pci.h index fe62a257e2..5493e0aed0 100644 --- a/src/util/pci.h +++ b/src/util/pci.h @@ -112,4 +112,10 @@ int pciDeviceNetName(char *device_link_sysfs_path, char **netname); int pciSysfsFile(char *pciDeviceName, char **pci_sysfs_device_link) ATTRIBUTE_RETURN_CHECK; +int pciGetDeviceAddrString(unsigned domain, + unsigned bus, + unsigned slot, + unsigned function, + char **pciConfigAddr) + ATTRIBUTE_NONNULL(5) ATTRIBUTE_RETURN_CHECK; #endif /* __VIR_PCI_H__ */ diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index 115f46ae34..06c825d3b9 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2011 Red Hat, Inc. + * Copyright (C) 2007-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 @@ -969,6 +969,77 @@ virNetDevSysfsDeviceFile(char **pf_sysfs_device_link, const char *ifname, return 0; } +/** + * virNetDevGetVirtualFunctions: + * + * @pfname : name of the physical function interface name + * @vfname: array that will hold the interface names of the virtual_functions + * @n_vfname: pointer to the number of virtual functions + * + * Returns 0 on success and -1 on failure + */ + +int +virNetDevGetVirtualFunctions(const char *pfname, + char ***vfname, + 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, + n_vfname) < 0) + goto cleanup; + + if (VIR_ALLOC_N(*vfname, *n_vfname) < 0) { + virReportOOMError(); + goto cleanup; + } + + 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, + &pciConfigAddr) < 0) { + virReportSystemError(ENOSYS, "%s", + _("Failed to get PCI Config Address String")); + goto cleanup; + } + if (pciSysfsFile(pciConfigAddr, &pci_sysfs_device_link) < 0) { + virReportSystemError(ENOSYS, "%s", + _("Failed to get PCI SYSFS file")); + goto cleanup; + } + + if (pciDeviceNetName(pci_sysfs_device_link, &((*vfname)[i])) < 0) { + virReportSystemError(ENOSYS, "%s", + _("Failed to get interface name of the VF")); + goto cleanup; + } + } + + ret = 0; + +cleanup: + if (ret < 0) + VIR_FREE(*vfname); + 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); + return ret; +} + /** * virNetDevIsVirtualFunction: * @ifname : name of the interface @@ -1056,6 +1127,17 @@ virNetDevGetPhysicalFunction(const char *ifname, char **pfname) return ret; } #else /* !__linux__ */ + +int +virNetDevGetVirtualFunctions(const char *pfname ATTRIBUTE_UNUSED, + char ***vfname ATTRIBUTE_UNUSED, + unsigned int *n_vfname ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Unable to get virtual functions on this platfornm")); + return -1; +} + int virNetDevIsVirtualFunction(const char *ifname ATTRIBUTE_UNUSED) { diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index 13ba1dab7a..7845e251ca 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2011 Red Hat, Inc. + * Copyright (C) 2007-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 @@ -99,4 +99,10 @@ int virNetDevGetVirtualFunctionIndex(const char *pfname, const char *vfname, int virNetDevGetPhysicalFunction(const char *ifname, char **pfname) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; +int virNetDevGetVirtualFunctions(const char *pfname, + char ***vfname, + unsigned int *n_vfname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_RETURN_CHECK; + #endif /* __VIR_NETDEV_H__ */