net: add support for phys_port_name
authorDavid Ahern <dsahern@gmail.com>
Wed, 18 Mar 2015 02:23:15 +0000 (20:23 -0600)
committerDavid S. Miller <davem@davemloft.net>
Thu, 19 Mar 2015 02:30:35 +0000 (22:30 -0400)
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.

Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Jiri Pirko <jiri@resnulli.us>
Acked-by: Scott Feldman <sfeldma@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/ABI/testing/sysfs-class-net
include/linux/netdevice.h
include/uapi/linux/if_link.h
net/core/dev.c
net/core/net-sysfs.c
net/core/rtnetlink.c

index beb8ec4dabbc648dd629e16a076662c9b78ff529..5ecfd72ba684c35acce51273d4370258b147ffb8 100644 (file)
@@ -188,6 +188,14 @@ Description:
                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:       netdev@vger.kernel.org
+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
index 76c5de4978a8b9de1cb34560645524223b541a6e..ec8f9b5f650058295c7518f2c055cba1aee4404f 100644 (file)
@@ -1164,6 +1164,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);
@@ -2947,6 +2949,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);
index 756436e1ce8970a215c27d52816ed068deea33e2..7158fd00a109939b66e7a855d60fad369f671492 100644 (file)
@@ -147,6 +147,7 @@ enum {
        IFLA_CARRIER_CHANGES,
        IFLA_PHYS_SWITCH_ID,
        IFLA_LINK_NETNSID,
+       IFLA_PHYS_PORT_NAME,
        __IFLA_MAX
 };
 
index 39fe369b46ad5b86e6f949e0d110eb060f7eb074..a1f24151db5be24a3a671dc8f33cc2299c085a50 100644 (file)
@@ -5911,6 +5911,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
index 7e58bd7ec2328a7e9fa706086cba6f0694a6a548..cc5cf689809c6646bc567a8380a6bfe5346bb959 100644 (file)
@@ -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,
 };
index 25b4b5d2348595d0a609733b4e4fc6d83a282c93..6abe634c666c83ef2eaed2ec382fef03b98c5748 100644 (file)
@@ -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;