From d6abc5969463359c366d459247b90366fcd6f5c5 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 09:45:35 -0800 Subject: net: Introduce ndo_get_port_parent_id() In preparation for getting rid of switchdev_ops, create a dedicated NDO operation for getting the port's parent identifier. There are essentially two classes of drivers that need to implement getting the port's parent ID which are VF/PF drivers with a built-in switch, and pure switchdev drivers such as mlxsw, ocelot, dsa etc. We introduce a helper function: dev_get_port_parent_id() which supports recursion into the lower devices to obtain the first port's parent ID. Convert the bridge, core and ipv4 multicast routing code to check for such ndo_get_port_parent_id() and call the helper function when valid before falling back to switchdev_port_attr_get(). This will allow us to convert all relevant drivers in one go instead of having to implement both switchdev_port_attr_get() and ndo_get_port_parent_id() operations, then get rid of switchdev_port_attr_get(). Acked-by: Jiri Pirko Signed-off-by: Florian Fainelli Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/dev.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ net/core/net-sysfs.c | 7 ++++++- net/core/rtnetlink.c | 6 +++++- 3 files changed, 68 insertions(+), 2 deletions(-) (limited to 'net/core') diff --git a/net/core/dev.c b/net/core/dev.c index bfa4be42afff..8c6d5cf8a308 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -7877,6 +7877,63 @@ int dev_get_phys_port_name(struct net_device *dev, } EXPORT_SYMBOL(dev_get_phys_port_name); +/** + * dev_get_port_parent_id - Get the device's port parent identifier + * @dev: network device + * @ppid: pointer to a storage for the port's parent identifier + * @recurse: allow/disallow recursion to lower devices + * + * Get the devices's port parent identifier + */ +int dev_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid, + bool recurse) +{ + const struct net_device_ops *ops = dev->netdev_ops; + struct netdev_phys_item_id first = { }; + struct net_device *lower_dev; + struct list_head *iter; + int err = -EOPNOTSUPP; + + if (ops->ndo_get_port_parent_id) + return ops->ndo_get_port_parent_id(dev, ppid); + + if (!recurse) + return err; + + netdev_for_each_lower_dev(dev, lower_dev, iter) { + err = dev_get_port_parent_id(lower_dev, ppid, recurse); + if (err) + break; + if (!first.id_len) + first = *ppid; + else if (memcmp(&first, ppid, sizeof(*ppid))) + return -ENODATA; + } + + return err; +} +EXPORT_SYMBOL(dev_get_port_parent_id); + +/** + * netdev_port_same_parent_id - Indicate if two network devices have + * the same port parent identifier + * @a: first network device + * @b: second network device + */ +bool netdev_port_same_parent_id(struct net_device *a, struct net_device *b) +{ + struct netdev_phys_item_id a_id = { }; + struct netdev_phys_item_id b_id = { }; + + if (dev_get_port_parent_id(a, &a_id, true) || + dev_get_port_parent_id(b, &b_id, true)) + return false; + + return netdev_phys_item_id_same(&a_id, &b_id); +} +EXPORT_SYMBOL(netdev_port_same_parent_id); + /** * dev_change_proto_down - update protocol port state information * @dev: device diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index ff9fd2bb4ce4..4eace9f1dcf9 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -495,6 +495,7 @@ static ssize_t phys_switch_id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct net_device *netdev = to_net_dev(dev); + const struct net_device_ops *ops = netdev->netdev_ops; ssize_t ret = -EINVAL; if (!rtnl_trylock()) @@ -507,7 +508,11 @@ static ssize_t phys_switch_id_show(struct device *dev, .flags = SWITCHDEV_F_NO_RECURSE, }; - ret = switchdev_port_attr_get(netdev, &attr); + if (ops->ndo_get_port_parent_id) + ret = dev_get_port_parent_id(netdev, &attr.u.ppid, + false); + else + ret = switchdev_port_attr_get(netdev, &attr); if (!ret) ret = sprintf(buf, "%*phN\n", attr.u.ppid.id_len, attr.u.ppid.id); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index f5a98082ac7a..90dd02c1f561 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1146,6 +1146,7 @@ static int rtnl_phys_port_name_fill(struct sk_buff *skb, struct net_device *dev) static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev) { + const struct net_device_ops *ops = dev->netdev_ops; int err; struct switchdev_attr attr = { .orig_dev = dev, @@ -1153,7 +1154,10 @@ static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev) .flags = SWITCHDEV_F_NO_RECURSE, }; - err = switchdev_port_attr_get(dev, &attr); + if (ops->ndo_get_port_parent_id) + err = dev_get_port_parent_id(dev, &attr.u.ppid, false); + else + err = switchdev_port_attr_get(dev, &attr); if (err) { if (err == -EOPNOTSUPP) return 0; -- cgit v1.2.3-59-g8ed1b