Ido Schimmel
2018-Apr-27 15:11 UTC
[Bridge] [PATCH net-next v2 1/6] net: bridge: Publish bridge accessor functions
From: Petr Machata <petrm at mellanox.com>
Add a couple new functions to allow querying FDB and vlan settings of a
bridge.
Signed-off-by: Petr Machata <petrm at mellanox.com>
Signed-off-by: Ido Schimmel <idosch at mellanox.com>
---
include/linux/if_bridge.h | 28 ++++++++++++++++++++++++++++
net/bridge/br_fdb.c | 22 ++++++++++++++++++++++
net/bridge/br_private.h | 11 +++++++++++
net/bridge/br_vlan.c | 39 +++++++++++++++++++++++++++++++++++++++
4 files changed, 100 insertions(+)
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 02639ebea2f0..769cf71efbdf 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -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_pvid_rtnl(const struct net_device *dev, u16 *p_pvid);
+int br_vlan_info_rtnl(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_pvid_rtnl(const struct net_device *dev, u16 *p_pvid)
+{
+ return -1;
+}
+
+static inline int br_vlan_info_rtnl(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_rtnl(const struct net_device *br_dev,
+ const unsigned char *addr,
+ __u16 vid);
+#else
+static inline struct net_device *
+br_fdb_find_port_rtnl(const struct net_device *br_dev,
+ const unsigned char *addr,
+ __u16 vid)
+{
+ return NULL;
+}
#endif
#endif
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index d9e69e4514be..51c7720aaba9 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -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_rtnl(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_rtnl);
+
struct net_bridge_fdb_entry *br_fdb_find_rcu(struct net_bridge *br,
const unsigned char *addr,
__u16 vid)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index a7cb3ece5031..1a5093115534 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -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,
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 9896f4975353..821014da3ef3 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1149,3 +1149,42 @@ void br_vlan_get_stats(const struct net_bridge_vlan *v,
stats->tx_packets += txpackets;
}
}
+
+int br_vlan_pvid_rtnl(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_pvid_rtnl);
+
+int br_vlan_info_rtnl(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_info_rtnl);
--
2.14.3
Nikolay Aleksandrov
2018-Apr-27 15:38 UTC
[Bridge] [PATCH net-next v2 1/6] net: bridge: Publish bridge accessor functions
On 27/04/18 18:11, Ido Schimmel wrote:> From: Petr Machata <petrm at mellanox.com> > > Add a couple new functions to allow querying FDB and vlan settings of a > bridge. > > Signed-off-by: Petr Machata <petrm at mellanox.com> > Signed-off-by: Ido Schimmel <idosch at mellanox.com> > --- > include/linux/if_bridge.h | 28 ++++++++++++++++++++++++++++ > net/bridge/br_fdb.c | 22 ++++++++++++++++++++++ > net/bridge/br_private.h | 11 +++++++++++ > net/bridge/br_vlan.c | 39 +++++++++++++++++++++++++++++++++++++++ > 4 files changed, 100 insertions(+) >Thanks! This looks good to me although the new exported helpers could've taken both bridge or port and return the result. Usually when adding a port-only functions we name them with nbp_ prefix instead of br_. Anyway this can be done later since the API is internal, Signed-off-by: Nikolay Aleksandrov <nikolay at cumulusnetworks.com>
Stephen Hemminger
2018-Apr-27 16:28 UTC
[Bridge] [PATCH net-next v2 1/6] net: bridge: Publish bridge accessor functions
On Fri, 27 Apr 2018 18:11:06 +0300 Ido Schimmel <idosch at mellanox.com> wrote:> +int br_vlan_pvid_rtnl(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_pvid_rtnl);Unless there is a RCU version, no need for _rtnl suffix. Minor style issue, why not make error then go on and return -1 on error. int br_vlan_pvid(const struct net_device *dev) { const struct net_bridge_vlan_group *vg; ASSERT_RTNL(); if (!netif_is_bridge_master(dev)) return -1; vg = br_vlan_group(netdev_priv(dev)); return br_get_pvid(vg); }