From 17d64cab16cb506fabbc0bdcc3994da5d0307005 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Mon, 15 Aug 2011 21:28:48 -0700 Subject: [PATCH] pci: Add helper functions for sriov devices This patch adds the following helper functions: pciDeviceIsVirtualFunction: Function to check if a pci device is a sriov VF pciGetVirtualFunctionIndex: Function to get the VF index of a sriov VF pciDeviceNetName: Function to get the network device name of a pci device pciConfigAddressCompare: Function to compare pci config addresses Signed-off-by: Roopa Prabhu Signed-off-by: Christian Benvenuti Signed-off-by: David Wang Signed-off-by: Stefan Berger --- src/util/pci.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ src/util/pci.h | 8 +++ 2 files changed, 154 insertions(+) diff --git a/src/util/pci.c b/src/util/pci.c index c3f3bb4225..7040e55323 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -1685,6 +1685,19 @@ int pciDeviceIsAssignable(pciDevice *dev, return 1; } +/* + * returns 1 if equal and 0 if not + */ +static int +pciConfigAddressEqual(struct pci_config_address *bdf1, + struct pci_config_address *bdf2) +{ + return ((bdf1->domain == bdf2->domain) && + (bdf1->bus == bdf2->bus) && + (bdf1->slot == bdf2->slot) && + (bdf1->function == bdf2->function)); +} + static int logStrToLong_ui(char const *s, char **end_ptr, @@ -1889,6 +1902,112 @@ out: return ret; } + +/* + * Returns 1 if vf device is a virtual function, 0 if not, -1 on error + */ +int +pciDeviceIsVirtualFunction(const char *vf_sysfs_device_link) +{ + char *vf_sysfs_physfn_link = NULL; + int ret = -1; + + if (virAsprintf(&vf_sysfs_physfn_link, "%s/physfn", + vf_sysfs_device_link) < 0) { + virReportOOMError(); + return ret; + } + + ret = virFileExists(vf_sysfs_physfn_link); + + VIR_FREE(vf_sysfs_physfn_link); + + return ret; +} + +/* + * Returns the sriov virtual function index of vf given its pf + */ +int +pciGetVirtualFunctionIndex(const char *pf_sysfs_device_link, + const char *vf_sysfs_device_link, + int *vf_index) +{ + int ret = -1, i; + unsigned int num_virt_fns = 0; + struct pci_config_address *vf_bdf = NULL; + struct pci_config_address **virt_fns = NULL; + + if (pciGetPciConfigAddressFromSysfsDeviceLink(vf_sysfs_device_link, + &vf_bdf)) + return ret; + + if (pciGetVirtualFunctions(pf_sysfs_device_link, &virt_fns, + &num_virt_fns)) { + pciReportError(VIR_ERR_INTERNAL_ERROR, + _("Error getting physical function's '%s' " + "virtual_functions"), pf_sysfs_device_link); + goto out; + } + + for (i = 0; i < num_virt_fns; i++) { + if (pciConfigAddressEqual(vf_bdf, virt_fns[i])) { + *vf_index = i; + ret = 0; + break; + } + } + +out: + + /* free virtual functions */ + for (i = 0; i < num_virt_fns; i++) + VIR_FREE(virt_fns[i]); + + VIR_FREE(vf_bdf); + + return ret; +} + +/* + * Returns the network device name of a pci device + */ +int +pciDeviceNetName(char *device_link_sysfs_path, char **netname) +{ + char *pcidev_sysfs_net_path = NULL; + int ret = -1; + DIR *dir = NULL; + struct dirent *entry = NULL; + + if (virBuildPath(&pcidev_sysfs_net_path, device_link_sysfs_path, + "net") == -1) { + virReportOOMError(); + return -1; + } + + dir = opendir(pcidev_sysfs_net_path); + if (dir == NULL) + goto out; + + while ((entry = readdir(dir))) { + if (STREQ(entry->d_name, ".") || + STREQ(entry->d_name, "..")) + continue; + + /* Assume a single directory entry */ + *netname = strdup(entry->d_name); + ret = 0; + break; + } + + closedir(dir); + +out: + VIR_FREE(pcidev_sysfs_net_path); + + return ret; +} #else int pciGetPhysicalFunction(const char *vf_sysfs_path, @@ -1908,4 +2027,31 @@ pciGetVirtualFunctions(const char *sysfs_path, "supported on non-linux platforms")); return -1; } + +int +pciDeviceIsVirtualFunction(const char *vf_sysfs_device_link) +{ + pciReportError(VIR_ERR_INTERNAL_ERROR, _("pciDeviceIsVirtualFunction is " + "not supported on non-linux platforms")); + return -1; +} + +int +pciGetVirtualFunctionIndex(const char *pf_sysfs_device_link, + const char *vf_sysfs_device_link, + int *vf_index) +{ + pciReportError(VIR_ERR_INTERNAL_ERROR, _("pciGetVirtualFunctionIndex is " + "not supported on non-linux platforms")); + return -1; + +} + +int +pciDeviceNetName(char *device_link_sysfs_path, char **netname) +{ + pciReportError(VIR_ERR_INTERNAL_ERROR, _("pciDeviceNetName is not " + "supported on non-linux platforms")); + return -1; +} #endif /* __linux__ */ diff --git a/src/util/pci.h b/src/util/pci.h index fe9479e078..a1600fe1fd 100644 --- a/src/util/pci.h +++ b/src/util/pci.h @@ -88,4 +88,12 @@ int pciGetVirtualFunctions(const char *sysfs_path, struct pci_config_address ***virtual_functions, unsigned int *num_virtual_functions); +int pciDeviceIsVirtualFunction(const char *vf_sysfs_device_link); + +int pciGetVirtualFunctionIndex(const char *pf_sysfs_device_link, + const char *vf_sysfs_device_link, + int *vf_index); + +int pciDeviceNetName(char *device_link_sysfs_path, char **netname); + #endif /* __VIR_PCI_H__ */