Skip to contentSkip to conversation

net: add support for phys_port_name

PATCH Applied David Ahern 4 participants 8 messages Mar 18, 2015 – Mar 25, 2015

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH v4 1/3 net: add support for phys_port_name

Similar to port id allow netdevices to specify port names and export the name via sysfs. Drivers can implement the netdevice operation to assist udev in having sane default names for the devices using the rule:

$ cat /etc/udev/rules.d/80-net-setup-link.rules
SUBSYSTEM=="net", ACTION=="add", ATTR{phys_port_name}!="",
NAME="$attr{phys_port_name}"

Use of phys_name versus phys_id was suggested-by Jiri Pirko.

---
v4:
- updated documentation per Florian's request

v3:
- changed length from int to size_t, variable name from buf to name per Jiri's comment

v2:
- replaced netdev_phys_item_name with buffer and length per Jiri's comment

 Documentation/ABI/testing/sysfs-class-net |  8 ++++++++
 include/linux/netdevice.h                 |  4 ++++
 include/uapi/linux/if_link.h              |  1 +
 net/core/dev.c                            | 18 ++++++++++++++++++
 net/core/net-sysfs.c                      | 23 +++++++++++++++++++++++
 net/core/rtnetlink.c                      | 21 +++++++++++++++++++++
 6 files changed, 75 insertions(+)
Documentation/ABI/testing/sysfs-class-net +8 -0
index beb8ec4dabbc..5ecfd72ba684 100644
@@ -188,6 +188,14 @@ Contact:	[email protected]
 		Indicates the interface unique physical port identifier within
 		the NIC, as a string.
 
+What:		/sys/class/net/<iface>/phys_port_name
+Date:		March 2015
+KernelVersion:	4.0
+Contact:	[email protected]
+Description:
+		Indicates the interface physical port name within the NIC,
+		as a string.
+
 What:		/sys/class/net/<iface>/speed
 Date:		October 2009
 KernelVersion:	2.6.33
include/linux/netdevice.h +4 -0
index dd1d069758be..52b519b408e6 100644
@@ -1159,6 +1159,8 @@ struct net_device_ops {
 						      bool new_carrier);
 	int			(*ndo_get_phys_port_id)(struct net_device *dev,
 							struct netdev_phys_item_id *ppid);
+	int			(*ndo_get_phys_port_name)(struct net_device *dev,
+							  char *name, size_t len);
 	void			(*ndo_add_vxlan_port)(struct  net_device *dev,
 						      sa_family_t sa_family,
 						      __be16 port);
@@ -2939,6 +2941,8 @@ int dev_set_mac_address(struct net_device *, struct sockaddr *);
 int dev_change_carrier(struct net_device *, bool new_carrier);
 int dev_get_phys_port_id(struct net_device *dev,
 			 struct netdev_phys_item_id *ppid);
+int dev_get_phys_port_name(struct net_device *dev,
+			   char *name, size_t len);
 struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev);
 struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 				    struct netdev_queue *txq, int *ret);
include/uapi/linux/if_link.h +1 -0
index 756436e1ce89..7158fd00a109 100644
@@ -147,6 +147,7 @@ enum {
 	IFLA_CARRIER_CHANGES,
 	IFLA_PHYS_SWITCH_ID,
 	IFLA_LINK_NETNSID,
+	IFLA_PHYS_PORT_NAME,
 	__IFLA_MAX
 };
 
net/core/dev.c +18 -0
index 39fe369b46ad..a1f24151db5b 100644
@@ -5912,6 +5912,24 @@ int dev_get_phys_port_id(struct net_device *dev,
 EXPORT_SYMBOL(dev_get_phys_port_id);
 
 /**
+ *	dev_get_phys_port_name - Get device physical port name
+ *	@dev: device
+ *	@name: port name
+ *
+ *	Get device physical port name
+ */
+int dev_get_phys_port_name(struct net_device *dev,
+			   char *name, size_t len)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+
+	if (!ops->ndo_get_phys_port_name)
+		return -EOPNOTSUPP;
+	return ops->ndo_get_phys_port_name(dev, name, len);
+}
+EXPORT_SYMBOL(dev_get_phys_port_name);
+
+/**
  *	dev_new_index	-	allocate an ifindex
  *	@net: the applicable net namespace
  *
net/core/net-sysfs.c +23 -0
index cf30620a88e1..b2a673870c4b 100644
@@ -418,6 +418,28 @@ static ssize_t phys_port_id_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(phys_port_id);
 
+static ssize_t phys_port_name_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct net_device *netdev = to_net_dev(dev);
+	ssize_t ret = -EINVAL;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
+
+	if (dev_isalive(netdev)) {
+		char name[IFNAMSIZ];
+
+		ret = dev_get_phys_port_name(netdev, name, sizeof(name));
+		if (!ret)
+			ret = sprintf(buf, "%s\n", name);
+	}
+	rtnl_unlock();
+
+	return ret;
+}
+static DEVICE_ATTR_RO(phys_port_name);
+
 static ssize_t phys_switch_id_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
@@ -465,6 +487,7 @@ static struct attribute *net_class_attrs[] = {
 	&dev_attr_tx_queue_len.attr,
 	&dev_attr_gro_flush_timeout.attr,
 	&dev_attr_phys_port_id.attr,
+	&dev_attr_phys_port_name.attr,
 	&dev_attr_phys_switch_id.attr,
 	NULL,
 };
net/core/rtnetlink.c +21 -0
index 25b4b5d23485..6abe634c666c 100644
@@ -982,6 +982,24 @@ static int rtnl_phys_port_id_fill(struct sk_buff *skb, struct net_device *dev)
 	return 0;
 }
 
+static int rtnl_phys_port_name_fill(struct sk_buff *skb, struct net_device *dev)
+{
+	char name[IFNAMSIZ];
+	int err;
+
+	err = dev_get_phys_port_name(dev, name, sizeof(name));
+	if (err) {
+		if (err == -EOPNOTSUPP)
+			return 0;
+		return err;
+	}
+
+	if (nla_put(skb, IFLA_PHYS_PORT_NAME, strlen(name), name))
+		return -EMSGSIZE;
+
+	return 0;
+}
+
 static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev)
 {
 	int err;
@@ -1072,6 +1090,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 	if (rtnl_phys_port_id_fill(skb, dev))
 		goto nla_put_failure;
 
+	if (rtnl_phys_port_name_fill(skb, dev))
+		goto nla_put_failure;
+
 	if (rtnl_phys_switch_id_fill(skb, dev))
 		goto nla_put_failure;
 
Signature · 1 line
2.2.1
#1 lore raw

PATCH v3 2/3 rocker: add support for phys_port_name

Implement the phys_port_name operation. Port names are pulled from the rocker hardware model in qemu and default to the qemu name + port id. e.g.,

sw1p1: flags=4098<BROADCAST,MULTICAST> mtu 1500
ether 52:54:00:12:35:01 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

where 'sw1' comes from the qemu command line -device rocker,name=sw1, and 'p1' is port 1.

Patch is adapted from Scott's phys_port_id patch.

---
v3:
- updated per comments from Jiri and Philip regarding len type and initializations

v2:
- updated per changes in prior patch requested by Jiri

 drivers/net/ethernet/rocker/rocker.c | 64 ++++++++++++++++++++++++++++++++++++
 drivers/net/ethernet/rocker/rocker.h |  1 +
 2 files changed, 65 insertions(+)
drivers/net/ethernet/rocker/rocker.c +64 -0
index 2511ae22ccd8..c9558e6d57ad 100644
@@ -30,6 +30,7 @@
 #include <linux/if_vlan.h>
 #include <linux/if_bridge.h>
 #include <linux/bitops.h>
+#include <linux/ctype.h>
 #include <net/switchdev.h>
 #include <net/rtnetlink.h>
 #include <net/ip_fib.h>
@@ -1630,6 +1631,53 @@ rocker_cmd_get_port_settings_macaddr_proc(struct rocker *rocker,
 	return 0;
 }
 
+struct port_name {
+	char *buf;
+	size_t len;
+};
+
+static int
+rocker_cmd_get_port_settings_phys_name_proc(struct rocker *rocker,
+					    struct rocker_port *rocker_port,
+					    struct rocker_desc_info *desc_info,
+					    void *priv)
+{
+	struct rocker_tlv *info_attrs[ROCKER_TLV_CMD_PORT_SETTINGS_MAX + 1];
+	struct rocker_tlv *attrs[ROCKER_TLV_CMD_MAX + 1];
+	struct port_name *name = priv;
+	struct rocker_tlv *attr;
+	size_t i, j, len;
+	char *str;
+
+	rocker_tlv_parse_desc(attrs, ROCKER_TLV_CMD_MAX, desc_info);
+	if (!attrs[ROCKER_TLV_CMD_INFO])
+		return -EIO;
+
+	rocker_tlv_parse_nested(info_attrs, ROCKER_TLV_CMD_PORT_SETTINGS_MAX,
+				attrs[ROCKER_TLV_CMD_INFO]);
+	attr = info_attrs[ROCKER_TLV_CMD_PORT_SETTINGS_PHYS_NAME];
+	if (!attr)
+		return -EIO;
+
+	len = min_t(size_t, rocker_tlv_len(attr), name->len);
+	str = rocker_tlv_data(attr);
+
+	/* make sure name only contains alphanumeric characters */
+	for (i = j = 0; i < len; ++i) {
+		if (isalnum(str[i])) {
+			name->buf[j] = str[i];
+			j++;
+		}
+	}
+
+	if (j == 0)
+		return -EIO;
+
+	name->buf[j] = '\0';
+
+	return 0;
+}
+
 static int
 rocker_cmd_set_port_settings_ethtool_prep(struct rocker *rocker,
 					  struct rocker_port *rocker_port,
@@ -4138,6 +4186,21 @@ static int rocker_port_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
 				       rocker_port->brport_flags, mask);
 }
 
+static int rocker_port_get_phys_port_name(struct net_device *dev,
+					  char *buf, size_t len)
+{
+	struct rocker_port *rocker_port = netdev_priv(dev);
+	struct port_name name = { .buf = buf, .len = len };
+	int err;
+
+	err = rocker_cmd_exec(rocker_port->rocker, rocker_port,
+			      rocker_cmd_get_port_settings_prep, NULL,
+			      rocker_cmd_get_port_settings_phys_name_proc,
+			      &name, false);
+
+	return err ? -EOPNOTSUPP : 0;
+}
+
 static const struct net_device_ops rocker_port_netdev_ops = {
 	.ndo_open			= rocker_port_open,
 	.ndo_stop			= rocker_port_stop,
@@ -4150,6 +4213,7 @@ static const struct net_device_ops rocker_port_netdev_ops = {
 	.ndo_fdb_dump			= rocker_port_fdb_dump,
 	.ndo_bridge_setlink		= rocker_port_bridge_setlink,
 	.ndo_bridge_getlink		= rocker_port_bridge_getlink,
+	.ndo_get_phys_port_name		= rocker_port_get_phys_port_name,
 };
 
 /********************
drivers/net/ethernet/rocker/rocker.h +1 -0
index 51e430d25138..a4e9591d7457 100644
@@ -158,6 +158,7 @@ enum {
 	ROCKER_TLV_CMD_PORT_SETTINGS_MACADDR,		/* binary */
 	ROCKER_TLV_CMD_PORT_SETTINGS_MODE,		/* u8 */
 	ROCKER_TLV_CMD_PORT_SETTINGS_LEARNING,		/* u8 */
+	ROCKER_TLV_CMD_PORT_SETTINGS_PHYS_NAME,		/* binary */
 
 	__ROCKER_TLV_CMD_PORT_SETTINGS_MAX,
 	ROCKER_TLV_CMD_PORT_SETTINGS_MAX =
Signature · 1 line
2.2.1
maintainer Applied
#2 lore raw

Re: [PATCH v3 2/3] rocker: add support for phys_port_name

From: David Ahern <[email protected]>
Date: Tue, 17 Mar 2015 20:23:16 -0600

Quoted 11 lines

Implement the phys_port_name operation. Port names are pulled from the rocker hardware model in qemu and default to the qemu name + port id. e.g.,

sw1p1: flags=4098<BROADCAST,MULTICAST> mtu 1500
ether 52:54:00:12:35:01 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

Quoted 8 lines

where 'sw1' comes from the qemu command line -device rocker,name=sw1, and 'p1' is port 1.

Patch is adapted from Scott's phys_port_id patch.

Applied to net-next.

#3 lore raw

PATCH 3/3 iproute2: Add support for phys_port_name

In reply to David Ahern

Display phys_port_name attribute if returned:

./ip link show sw1p1
4: sw1p1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop port name sw1p1 state DOWN mode DEFAULT group default qlen 1000

    link/ether 52:54:00:12:35:01 brd ff:ff:ff:ff:ff:ff
---
 include/linux/if_link.h | 1 +
 ip/ipaddress.c          | 3 +++
 2 files changed, 4 insertions(+)
include/linux/if_link.h +1 -0
index 3450c3fbdc65..c5ee8c91b1c6 100644
@@ -147,6 +147,7 @@ enum {
 	IFLA_CARRIER_CHANGES,
 	IFLA_PHYS_SWITCH_ID,
 	IFLA_LINK_NETNSID,
+	IFLA_PHYS_PORT_NAME,
 	__IFLA_MAX
 };
 
ip/ipaddress.c +3 -0
index 99a6ab5977e3..9e65015b7a48 100644
@@ -645,6 +645,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
 				      b1, sizeof(b1)));
 	}
 
+	if (tb[IFLA_PHYS_PORT_NAME])
+		fprintf(fp, "port name %s ", rta_getattr_str(tb[IFLA_PHYS_PORT_NAME]));
+
 	if (tb[IFLA_OPERSTATE])
 		print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE]));
 
Signature · 1 line
2.2.1
maintainer Applied
#4 lore raw
In reply to David Ahern

From: David Ahern <[email protected]>
Date: Tue, 17 Mar 2015 20:23:15 -0600

Quoted 9 lines

Similar to port id allow netdevices to specify port names and export the name via sysfs. Drivers can implement the netdevice operation to assist udev in having sane default names for the devices using the rule:

$ cat /etc/udev/rules.d/80-net-setup-link.rules
SUBSYSTEM=="net", ACTION=="add", ATTR{phys_port_name}!="",
NAME="$attr{phys_port_name}"
Quoted 5 lines

Use of phys_name versus phys_id was suggested-by Jiri Pirko.

Applied to net-next.

#5 lore raw
In reply to David Ahern
Quoted 9 lines · On Tue, 17 Mar 2015 20:23:15 -0600 David Ahern <[email protected]> wrote:

Similar to port id allow netdevices to specify port names and export the name via sysfs. Drivers can implement the netdevice operation to assist udev in having sane default names for the devices using the rule:

$ cat /etc/udev/rules.d/80-net-setup-link.rules
SUBSYSTEM=="net", ACTION=="add", ATTR{phys_port_name}!="",
NAME="$attr{phys_port_name}"
Quoted 5 lines

Use of phys_name versus phys_id was suggested-by Jiri Pirko.

Should this also be settable as well?

#6 lore raw
Quoted 12 lines · Stephen Hemminger
Quoted 9 lines · On Tue, 17 Mar 2015 20:23:15 -0600 David Ahern <[email protected]> wrote:

Similar to port id allow netdevices to specify port names and export the name via sysfs. Drivers can implement the netdevice operation to assist udev in having sane default names for the devices using the rule:

$ cat /etc/udev/rules.d/80-net-setup-link.rules
SUBSYSTEM=="net", ACTION=="add", ATTR{phys_port_name}!="",
NAME="$attr{phys_port_name}"
Quoted 9 lines
Quoted 5 lines

Use of phys_name versus phys_id was suggested-by Jiri Pirko.

Should this also be settable as well?

The intention was for this to come from the device. Currently, phys_port_id and phys_port_name only have get methods, so no set.

David

maintainer
#7 lore raw
Quoted 19 lines · Tue, Mar 24, 2015 at 11:25:12PM CET, [email protected] wrote:
Quoted 18 lines · Stephen Hemminger
Quoted 14 lines · On Tue, 17 Mar 2015 20:23:15 -0600 David Ahern <[email protected]> wrote:

Similar to port id allow netdevices to specify port names and export the name via sysfs. Drivers can implement the netdevice operation to assist udev in having sane default names for the devices using the rule:

$ cat /etc/udev/rules.d/80-net-setup-link.rules
SUBSYSTEM=="net", ACTION=="add", ATTR{phys_port_name}!="",
NAME="$attr{phys_port_name}"

Use of phys_name versus phys_id was suggested-by Jiri Pirko.

Quoted 6 lines
Quoted 3 lines

Should this also be settable as well?

The intention was for this to come from the device. Currently, phys_port_id and phys_port_name only have get methods, so no set.

Makes no sense to have set for these two.

Quoted 2 lines

David