l3mdev: add function to retreive upper master
authorAlexis Bauvin <abauvin@scaleway.com>
Mon, 3 Dec 2018 09:54:39 +0000 (10:54 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 3 Dec 2018 22:15:26 +0000 (14:15 -0800)
Existing functions to retreive the l3mdev of a device did not walk the
master chain to find the upper master. This patch adds a function to
find the l3mdev, even indirect through e.g. a bridge:

+----------+
|          |
| vrf-blue |
|          |
+----+-----+
     |
     |
+----+-----+
|          |
| br-blue  |
|          |
+----+-----+
     |
     |
+----+-----+
|          |
|   eth0   |
|          |
+----------+

This will properly resolve the l3mdev of eth0 to vrf-blue.

Signed-off-by: Alexis Bauvin <abauvin@scaleway.com>
Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
Tested-by: Amine Kherbouche <akherbouche@scaleway.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/l3mdev.h
net/l3mdev/l3mdev.c

index 3832099289c5aa607ed89bc6eb711a8e412980f0..78fa0ac4613c3946590677f53d946d37d97f7bde 100644 (file)
@@ -101,6 +101,17 @@ struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev)
        return master;
 }
 
+int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex);
+static inline
+int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
+{
+       rcu_read_lock();
+       ifindex = l3mdev_master_upper_ifindex_by_index_rcu(net, ifindex);
+       rcu_read_unlock();
+
+       return ifindex;
+}
+
 u32 l3mdev_fib_table_rcu(const struct net_device *dev);
 u32 l3mdev_fib_table_by_index(struct net *net, int ifindex);
 static inline u32 l3mdev_fib_table(const struct net_device *dev)
@@ -207,6 +218,17 @@ static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
        return 0;
 }
 
+static inline
+int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex)
+{
+       return 0;
+}
+static inline
+int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
+{
+       return 0;
+}
+
 static inline
 struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev)
 {
index 8da86ceca33ddf4c4e5d61850ce54f22a29e6fb9..309dee76724e505c804da9195f7f9d3c4cdfbdee 100644 (file)
@@ -46,6 +46,24 @@ int l3mdev_master_ifindex_rcu(const struct net_device *dev)
 }
 EXPORT_SYMBOL_GPL(l3mdev_master_ifindex_rcu);
 
+/**
+ *     l3mdev_master_upper_ifindex_by_index - get index of upper l3 master
+ *                                            device
+ *     @net: network namespace for device index lookup
+ *     @ifindex: targeted interface
+ */
+int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex)
+{
+       struct net_device *dev;
+
+       dev = dev_get_by_index_rcu(net, ifindex);
+       while (dev && !netif_is_l3_master(dev))
+               dev = netdev_master_upper_dev_get(dev);
+
+       return dev ? dev->ifindex : 0;
+}
+EXPORT_SYMBOL_GPL(l3mdev_master_upper_ifindex_by_index_rcu);
+
 /**
  *     l3mdev_fib_table - get FIB table id associated with an L3
  *                             master interface