virPCIGetVirtualFunctions: Fetch also network interface name if needed

'virNetDevGetVirtualFunctions' calls 'virPCIGetVirtualFunctions' and
then re-iterates the returned list to fetch the interface names for the
returned virtual functions.

If we move the fetching of the interface name into
virPCIGetVirtualFunctions we can simplify the code and remove a bunch of
impossible error states.

To accomplish this the function is renamed to
'virPCIGetVirtualFunctionsFull' while keeping a wrapper with original
name and if the physical port ID is passed the interface name is fetched
too without the need to re-convert the address into a sysfs link.

For now 'virNetDevGetVirtualFunctions' still converts the returned data
into two lists.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa 2021-08-04 17:37:44 +02:00
parent 7ef618f30a
commit 795e9e05c3
4 changed files with 43 additions and 45 deletions

View File

@ -3012,6 +3012,7 @@ virPCIGetPhysicalFunction;
virPCIGetVirtualFunctionIndex;
virPCIGetVirtualFunctionInfo;
virPCIGetVirtualFunctions;
virPCIGetVirtualFunctionsFull;
virPCIHeaderTypeFromString;
virPCIHeaderTypeToString;
virPCIIsVirtualFunction;

View File

@ -1227,62 +1227,30 @@ virNetDevGetVirtualFunctions(const char *pfname,
virPCIDeviceAddress ***virt_fns,
size_t *n_vfname)
{
int ret = -1;
size_t i;
g_autofree char *pf_sysfs_device_link = NULL;
g_autofree char *pfPhysPortID = NULL;
g_autoptr(virPCIVirtualFunctionList) vfs = NULL;
*virt_fns = NULL;
*n_vfname = 0;
if (virNetDevGetPhysPortID(pfname, &pfPhysPortID) < 0)
goto cleanup;
return -1;
if (virNetDevSysfsFile(&pf_sysfs_device_link, pfname, "device") < 0)
goto cleanup;
return -1;
if (virPCIGetVirtualFunctions(pf_sysfs_device_link, &vfs) < 0)
goto cleanup;
if (virPCIGetVirtualFunctionsFull(pf_sysfs_device_link, &vfs, pfPhysPortID) < 0)
return -1;
*vfname = g_new0(char *, vfs->nfunctions);
*virt_fns = g_new0(virPCIDeviceAddress *, vfs->nfunctions);
*n_vfname = vfs->nfunctions;
for (i = 0; i < *n_vfname; i++) {
g_autofree char *pci_sysfs_device_link = NULL;
virt_fns[i] = g_steal_pointer(&vfs->functions[i].addr);
if (virPCIDeviceAddressGetSysfsFile((*virt_fns)[i],
&pci_sysfs_device_link) < 0) {
virReportSystemError(ENOSYS, "%s",
_("Failed to get PCI SYSFS file"));
goto cleanup;
}
if (virPCIGetNetName(pci_sysfs_device_link, 0,
pfPhysPortID, &((*vfname)[i])) < 0) {
goto cleanup;
}
if (!(*vfname)[i])
VIR_INFO("VF does not have an interface name");
vfname[i] = g_steal_pointer(&vfs->functions[i].ifname);
}
ret = 0;
cleanup:
if (ret < 0) {
virStringListFreeCount(*vfname, *n_vfname);
for (i = 0; i < *n_vfname; i++)
VIR_FREE((*virt_fns)[i]);
VIR_FREE(*virt_fns);
*vfname = NULL;
*n_vfname = 0;
}
return ret;
return 0;
}
/**

View File

@ -2257,12 +2257,21 @@ virPCIVirtualFunctionListFree(virPCIVirtualFunctionList *list)
for (i = 0; i < list->nfunctions; i++) {
g_free(list->functions[i].addr);
g_free(list->functions[i].ifname);
}
g_free(list);
}
int
virPCIGetVirtualFunctions(const char *sysfs_path,
virPCIVirtualFunctionList **vfs)
{
return virPCIGetVirtualFunctionsFull(sysfs_path, vfs, NULL);
}
#ifdef __linux__
virPCIDeviceAddress *
@ -2332,12 +2341,20 @@ virPCIGetPhysicalFunction(const char *vf_sysfs_path,
}
/*
* Returns virtual functions of a physical function
/**
* virPCIGetVirtualFunctionsFull:
* @sysfs_path: path to physical function sysfs entry
* @vfs: filled with the virtual function data
* @pfPhysPortID: Optional physical port id. If provided the network interface
* name of the VFs is queried too.
*
*
* Returns virtual functions of a physical function.
*/
int
virPCIGetVirtualFunctions(const char *sysfs_path,
virPCIVirtualFunctionList **vfs)
virPCIGetVirtualFunctionsFull(const char *sysfs_path,
virPCIVirtualFunctionList **vfs,
const char *pfPhysPortID)
{
g_autofree char *totalvfs_file = NULL;
g_autofree char *totalvfs_str = NULL;
@ -2363,7 +2380,7 @@ virPCIGetVirtualFunctions(const char *sysfs_path,
do {
g_autofree char *device_link = NULL;
struct virPCIVirtualFunction fnc = { NULL };
struct virPCIVirtualFunction fnc = { NULL, NULL };
/* look for virtfn%d links until one isn't found */
device_link = g_strdup_printf("%s/virtfn%zu", sysfs_path, list->nfunctions);
@ -2378,6 +2395,13 @@ virPCIGetVirtualFunctions(const char *sysfs_path,
return -1;
}
if (pfPhysPortID) {
if (virPCIGetNetName(device_link, 0, pfPhysPortID, &fnc.ifname) < 0) {
g_free(fnc.addr);
return -1;
}
}
VIR_APPEND_ELEMENT(list->functions, list->nfunctions, fnc);
} while (1);
@ -2636,8 +2660,9 @@ virPCIGetPhysicalFunction(const char *vf_sysfs_path G_GNUC_UNUSED,
}
int
virPCIGetVirtualFunctions(const char *sysfs_path G_GNUC_UNUSED,
virPCIVirtualFunctionList **vfs G_GNUC_UNUSED)
virPCIGetVirtualFunctionsFull(const char *sysfs_path G_GNUC_UNUSED,
virPCIVirtualFunctionList **vfs G_GNUC_UNUSED,
const char *pfPhysPortID G_GNUC_UNUSED)
{
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
return -1;

View File

@ -214,6 +214,7 @@ int virPCIGetPhysicalFunction(const char *vf_sysfs_path,
struct virPCIVirtualFunction {
virPCIDeviceAddress *addr;
char *ifname;
};
struct _virPCIVirtualFunctionList {
@ -226,6 +227,9 @@ typedef struct _virPCIVirtualFunctionList virPCIVirtualFunctionList;
void virPCIVirtualFunctionListFree(virPCIVirtualFunctionList *list);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virPCIVirtualFunctionList, virPCIVirtualFunctionListFree);
int virPCIGetVirtualFunctionsFull(const char *sysfs_path,
virPCIVirtualFunctionList **vfs,
const char *pfPhysPortID);
int virPCIGetVirtualFunctions(const char *sysfs_path,
virPCIVirtualFunctionList **vfs);