ea4a6f
From 8f2d9991d50e09ba9af842fb592b37d0c2021a06 Mon Sep 17 00:00:00 2001
ea4a6f
From: dirkjacobus <dirkjacobus@gmail.com>
ea4a6f
Date: Sun, 11 Nov 2018 23:29:24 -0800
ea4a6f
Subject: [PATCH] Netronome biosdevname support (#8)
ea4a6f
ea4a6f
* Add support for Netronome netdevices
ea4a6f
ea4a6f
Netronome netdevices also provide multiple ports through the same
ea4a6f
function.
ea4a6f
ea4a6f
* Set devID with phys_port_name index for nfp devices
ea4a6f
ea4a6f
Netronome netdevices should rather use the index from the phys_port_name
ea4a6f
attribute instead of the dev_port/dev_id
ea4a6f
attributes.
ea4a6f
ea4a6f
* Exclude naming Netronome logical devices
ea4a6f
ea4a6f
Some drivers, like the Netronome nfp driver, expose logical devices such
ea4a6f
as representors and switchdev uplink devices.
ea4a6f
ea4a6f
There isn't currently a naming scheme for such devices, so exclude them
ea4a6f
from the biosdevname naming policy.
ea4a6f
ea4a6f
Split ports also don't have a naming scheme defined for biosdevname, so
ea4a6f
its better to exclude them from naming.
ea4a6f
ea4a6f
Identification of such devices will always be driver dependent.
ea4a6f
At the moment, only 'nfp' driver devices are considered for exclusion.
ea4a6f
---
ea4a6f
 src/bios_device.c |  6 ++++-
ea4a6f
 src/eths.c        | 65 ++++++++++++++++++++++++++++++++++++++++-------
ea4a6f
 src/eths.h        |  6 +++++
ea4a6f
 3 files changed, 67 insertions(+), 10 deletions(-)
ea4a6f
ea4a6f
diff --git a/src/bios_device.c b/src/bios_device.c
ea4a6f
index 3cc528b..4882513 100644
ea4a6f
--- a/src/bios_device.c
ea4a6f
+++ b/src/bios_device.c
ea4a6f
@@ -214,7 +214,7 @@ static void sort_device_list(struct libbiosdevname_state *state)
ea4a6f
 	list_splice(&sorted_devices, &state->bios_devices);
ea4a6f
 }
ea4a6f
 
ea4a6f
-/* Check for Mellanox/Chelsio drivers */
ea4a6f
+/* Check for multiport drivers */
ea4a6f
 int ismultiport(const char *driver)
ea4a6f
 {
ea4a6f
 	if (!strncmp(driver, "mlx4", 4))
ea4a6f
@@ -223,6 +223,8 @@ int ismultiport(const char *driver)
ea4a6f
 		return 1;
ea4a6f
 	if (!strncmp(driver, "exanic", 6))
ea4a6f
 		return 1;
ea4a6f
+	if (!strncmp(driver, "nfp", 3))
ea4a6f
+		return 1;
ea4a6f
 	return 0;
ea4a6f
 }
ea4a6f
 
ea4a6f
@@ -248,6 +250,8 @@ static void match_pci_and_eth_devs(struct libbiosdevname_state *state)
ea4a6f
 			/* Ignore if devtype is fcoe */
ea4a6f
 			if (netdev_devtype_is_fcoe(n))
ea4a6f
 				continue;
ea4a6f
+			if (!netdev_is_eligible(n))
ea4a6f
+				continue;
ea4a6f
 			b = malloc(sizeof(*b));
ea4a6f
 			if (!b)
ea4a6f
 				continue;
ea4a6f
diff --git a/src/eths.c b/src/eths.c
ea4a6f
index d2c4d36..688c3af 100644
ea4a6f
--- a/src/eths.c
ea4a6f
+++ b/src/eths.c
ea4a6f
@@ -35,21 +35,67 @@ char *pr_ether(char *buf, const int size, const unsigned char *s)
ea4a6f
 	return (buf);
ea4a6f
 }
ea4a6f
 
ea4a6f
-static void eths_get_devid(const char *devname, int *devid)
ea4a6f
+static int eths_get_phys_port_name_id(const char *devname)
ea4a6f
+{
ea4a6f
+	char *portstr = NULL;
ea4a6f
+	char path[PATH_MAX];
ea4a6f
+	int index = -1;
ea4a6f
+
ea4a6f
+	/* Only devices that have a phys_port_name of 'pX' are considered here,
ea4a6f
+	 * with the index 'X' extracted.
ea4a6f
+	 */
ea4a6f
+	snprintf(path, sizeof(path), "/sys/class/net/%s/phys_port_name", devname);
ea4a6f
+	if (sysfs_read_file(path, &portstr) == 0) {
ea4a6f
+		char *res = NULL;
ea4a6f
+
ea4a6f
+		if (portstr[0] == 'p') {
ea4a6f
+			index = strtol(&portstr[1], &res, 10);
ea4a6f
+			/* Reset to invalid if the format is unexpected. */
ea4a6f
+			if (*res)
ea4a6f
+				index = -1;
ea4a6f
+		}
ea4a6f
+
ea4a6f
+		free(portstr);
ea4a6f
+	}
ea4a6f
+
ea4a6f
+	return index;
ea4a6f
+}
ea4a6f
+
ea4a6f
+static void eths_get_dev_eligible(struct network_device *dev)
ea4a6f
+{
ea4a6f
+	/* By default, all network devices are eligible for naming. Some may
ea4a6f
+	 * opt-out explicitly below.
ea4a6f
+	 */
ea4a6f
+	dev->is_eligible = 1;
ea4a6f
+
ea4a6f
+	if (dev->drvinfo_valid && strcmp(dev->drvinfo.driver, "nfp") == 0) {
ea4a6f
+		dev->is_eligible = (eths_get_phys_port_name_id(dev->kernel_name) >= 0 ? 1 : 0);
ea4a6f
+	}
ea4a6f
+}
ea4a6f
+
ea4a6f
+static void eths_get_devid(struct network_device *dev)
ea4a6f
 {
ea4a6f
 	char path[PATH_MAX];
ea4a6f
 	char *devidstr = NULL;
ea4a6f
 
ea4a6f
-	*devid = -1;
ea4a6f
-	snprintf(path, sizeof(path), "/sys/class/net/%s/dev_port", devname);
ea4a6f
-	if (sysfs_read_file(path, &devidstr) == 0) {
ea4a6f
-		sscanf(devidstr, "%i", devid);
ea4a6f
-		free(devidstr);
ea4a6f
+	dev->devid = -1;
ea4a6f
+
ea4a6f
+	/* For some drivers, the phys_port_name index, e.g. pX, is the correct
ea4a6f
+	 * dev ID to use instead of the dev_port attribute.
ea4a6f
+	 */
ea4a6f
+	if (dev->drvinfo_valid && strcmp(dev->drvinfo.driver, "nfp") == 0) {
ea4a6f
+		dev->devid = eths_get_phys_port_name_id(dev->kernel_name);
ea4a6f
 	} else {
ea4a6f
-		snprintf(path, sizeof(path), "/sys/class/net/%s/dev_id", devname);
ea4a6f
+		snprintf(path, sizeof(path), "/sys/class/net/%s/dev_port", dev->kernel_name);
ea4a6f
 		if (sysfs_read_file(path, &devidstr) == 0) {
ea4a6f
-			sscanf(devidstr, "%i", devid);
ea4a6f
+			sscanf(devidstr, "%i", &dev->devid);
ea4a6f
 			free(devidstr);
ea4a6f
+		} else {
ea4a6f
+			snprintf(path, sizeof(path), "/sys/class/net/%s/dev_id", dev->kernel_name);
ea4a6f
+			if (sysfs_read_file(path, &devidstr) == 0) {
ea4a6f
+				sscanf(devidstr, "%i", &dev->devid);
ea4a6f
+				free(devidstr);
ea4a6f
+			}
ea4a6f
 		}
ea4a6f
 	}
ea4a6f
 }
ea4a6f
@@ -224,13 +270,14 @@ static void fill_eth_dev(struct network_device *dev)
ea4a6f
 	eths_get_ifindex(dev->kernel_name, &dev->ifindex);
ea4a6f
 	eths_get_hwaddr(dev->kernel_name, dev->dev_addr, sizeof(dev->dev_addr), &dev->arphrd_type);
ea4a6f
 	eths_get_permaddr(dev->kernel_name, dev->perm_addr, sizeof(dev->perm_addr));
ea4a6f
-	eths_get_devid(dev->kernel_name, &dev->devid);
ea4a6f
 	devtype = eths_get_devtype(dev);
ea4a6f
 	if (devtype > 0)
ea4a6f
 		dev->devtype_is_fcoe = 1;
ea4a6f
 	rc = eths_get_info(dev->kernel_name, &dev->drvinfo);
ea4a6f
 	if (rc == 0)
ea4a6f
 		dev->drvinfo_valid = 1;
ea4a6f
+	eths_get_devid(dev);
ea4a6f
+	eths_get_dev_eligible(dev);
ea4a6f
 }
ea4a6f
 
ea4a6f
 void free_eths(struct libbiosdevname_state *state)
ea4a6f
diff --git a/src/eths.h b/src/eths.h
ea4a6f
index b695d3d..49e399d 100644
ea4a6f
--- a/src/eths.h
ea4a6f
+++ b/src/eths.h
ea4a6f
@@ -30,6 +30,7 @@ struct network_device {
ea4a6f
 	int devid;
ea4a6f
 	int devtype_is_fcoe;
ea4a6f
 	char *devtype;
ea4a6f
+	int is_eligible:1; /* not eligible for naming when 0 */
ea4a6f
 };
ea4a6f
 
ea4a6f
 extern void get_eths(struct libbiosdevname_state *state);
ea4a6f
@@ -68,4 +69,9 @@ static inline int netdev_arphrd_type_is_eth(const struct network_device *dev)
ea4a6f
         return (dev->arphrd_type == ARPHRD_ETHER);
ea4a6f
 }
ea4a6f
 
ea4a6f
+static inline int netdev_is_eligible(const struct network_device *dev)
ea4a6f
+{
ea4a6f
+	return (!!dev->is_eligible);
ea4a6f
+}
ea4a6f
+
ea4a6f
 #endif /* __ETHS_H_INCLUDED */
ea4a6f
-- 
ea4a6f
2.17.2
ea4a6f