]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
net: bridge: Publish bridge accessor functions
authorPetr Machata <petrm@mellanox.com>
Sun, 29 Apr 2018 07:56:08 +0000 (10:56 +0300)
committerDavid S. Miller <davem@davemloft.net>
Mon, 30 Apr 2018 16:42:40 +0000 (12:42 -0400)
Add a couple new functions to allow querying FDB and vlan settings of a
bridge.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/if_bridge.h
net/bridge/br_fdb.c
net/bridge/br_private.h
net/bridge/br_vlan.c

index 02639ebea2f068f2e4b026610501a5a1768c58dc..585d271824250e2595f8d1c66fd1c7ac18e6fefc 100644 (file)
@@ -93,11 +93,39 @@ static inline bool br_multicast_router(const struct net_device *dev)
 
 #if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING)
 bool br_vlan_enabled(const struct net_device *dev);
+int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid);
+int br_vlan_get_info(const struct net_device *dev, u16 vid,
+                    struct bridge_vlan_info *p_vinfo);
 #else
 static inline bool br_vlan_enabled(const struct net_device *dev)
 {
        return false;
 }
+
+static inline int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid)
+{
+       return -1;
+}
+
+static inline int br_vlan_get_info(const struct net_device *dev, u16 vid,
+                                  struct bridge_vlan_info *p_vinfo)
+{
+       return -1;
+}
+#endif
+
+#if IS_ENABLED(CONFIG_BRIDGE)
+struct net_device *br_fdb_find_port(const struct net_device *br_dev,
+                                   const unsigned char *addr,
+                                   __u16 vid);
+#else
+static inline struct net_device *
+br_fdb_find_port(const struct net_device *br_dev,
+                const unsigned char *addr,
+                __u16 vid)
+{
+       return NULL;
+}
 #endif
 
 #endif
index d9e69e4514beb20d5d8a3672e26d5cc9edfc16fa..a1c409cacec4e8bb298cc3a94fda55f8f02cc3cc 100644 (file)
@@ -121,6 +121,28 @@ static struct net_bridge_fdb_entry *br_fdb_find(struct net_bridge *br,
        return fdb;
 }
 
+struct net_device *br_fdb_find_port(const struct net_device *br_dev,
+                                   const unsigned char *addr,
+                                   __u16 vid)
+{
+       struct net_bridge_fdb_entry *f;
+       struct net_device *dev = NULL;
+       struct net_bridge *br;
+
+       ASSERT_RTNL();
+
+       if (!netif_is_bridge_master(br_dev))
+               return NULL;
+
+       br = netdev_priv(br_dev);
+       f = br_fdb_find(br, addr, vid);
+       if (f && f->dst)
+               dev = f->dst->dev;
+
+       return dev;
+}
+EXPORT_SYMBOL_GPL(br_fdb_find_port);
+
 struct net_bridge_fdb_entry *br_fdb_find_rcu(struct net_bridge *br,
                                             const unsigned char *addr,
                                             __u16 vid)
index a7cb3ece5031092f9df529864affdfafdfd1cf28..1a5093115534290ae63ee8e1cf6d4811a3eba4f0 100644 (file)
@@ -594,11 +594,22 @@ static inline bool br_rx_handler_check_rcu(const struct net_device *dev)
        return rcu_dereference(dev->rx_handler) == br_handle_frame;
 }
 
+static inline bool br_rx_handler_check_rtnl(const struct net_device *dev)
+{
+       return rcu_dereference_rtnl(dev->rx_handler) == br_handle_frame;
+}
+
 static inline struct net_bridge_port *br_port_get_check_rcu(const struct net_device *dev)
 {
        return br_rx_handler_check_rcu(dev) ? br_port_get_rcu(dev) : NULL;
 }
 
+static inline struct net_bridge_port *
+br_port_get_check_rtnl(const struct net_device *dev)
+{
+       return br_rx_handler_check_rtnl(dev) ? br_port_get_rtnl_rcu(dev) : NULL;
+}
+
 /* br_ioctl.c */
 int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd,
index 9896f4975353db00af2ebf7432633c5e84ff7f7d..df37a5137c25450e18c16d255236a0e6d4b8140c 100644 (file)
@@ -1149,3 +1149,42 @@ void br_vlan_get_stats(const struct net_bridge_vlan *v,
                stats->tx_packets += txpackets;
        }
 }
+
+int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid)
+{
+       struct net_bridge_vlan_group *vg;
+
+       ASSERT_RTNL();
+       if (netif_is_bridge_master(dev))
+               vg = br_vlan_group(netdev_priv(dev));
+       else
+               return -EINVAL;
+
+       *p_pvid = br_get_pvid(vg);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(br_vlan_get_pvid);
+
+int br_vlan_get_info(const struct net_device *dev, u16 vid,
+                    struct bridge_vlan_info *p_vinfo)
+{
+       struct net_bridge_vlan_group *vg;
+       struct net_bridge_vlan *v;
+       struct net_bridge_port *p;
+
+       ASSERT_RTNL();
+       p = br_port_get_check_rtnl(dev);
+       if (p)
+               vg = nbp_vlan_group(p);
+       else
+               return -EINVAL;
+
+       v = br_vlan_find(vg, vid);
+       if (!v)
+               return -ENOENT;
+
+       p_vinfo->vid = vid;
+       p_vinfo->flags = v->flags;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(br_vlan_get_info);