summaryrefslogtreecommitdiff
path: root/net/bridge
diff options
context:
space:
mode:
authorNikolay Aleksandrov <nikolay@nvidia.com>2021-08-10 18:29:32 +0300
committerDavid S. Miller <davem@davemloft.net>2021-08-11 13:34:41 +0100
commite04d377ff6ce915d2d95ba13e7aff3ca64d50781 (patch)
tree322bdc127f617a8a85bba9db3d9a2ef49f605e48 /net/bridge
parenta97df080b6a86c105f98052ca3a9d66149b461b3 (diff)
net: bridge: mcast: use the proper multicast context when dumping router ports
When we are dumping the router ports of a vlan mcast context we need to use the bridge/vlan and port/vlan's multicast contexts to check if IPv4/IPv6 router port is present and later to dump the vlan id. Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_mdb.c49
1 files changed, 31 insertions, 18 deletions
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 73a8915b0148..7c16e2c76220 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -16,7 +16,7 @@
#include "br_private.h"
-static bool br_rports_have_mc_router(struct net_bridge_mcast *brmctx)
+static bool br_rports_have_mc_router(const struct net_bridge_mcast *brmctx)
{
#if IS_ENABLED(CONFIG_IPV6)
return !hlist_empty(&brmctx->ip4_mc_router_list) ||
@@ -27,46 +27,58 @@ static bool br_rports_have_mc_router(struct net_bridge_mcast *brmctx)
}
static bool
-br_ip4_rports_get_timer(struct net_bridge_port *port, unsigned long *timer)
+br_ip4_rports_get_timer(struct net_bridge_mcast_port *pmctx,
+ unsigned long *timer)
{
- *timer = br_timer_value(&port->multicast_ctx.ip4_mc_router_timer);
- return !hlist_unhashed(&port->multicast_ctx.ip4_rlist);
+ *timer = br_timer_value(&pmctx->ip4_mc_router_timer);
+ return !hlist_unhashed(&pmctx->ip4_rlist);
}
static bool
-br_ip6_rports_get_timer(struct net_bridge_port *port, unsigned long *timer)
+br_ip6_rports_get_timer(struct net_bridge_mcast_port *pmctx,
+ unsigned long *timer)
{
#if IS_ENABLED(CONFIG_IPV6)
- *timer = br_timer_value(&port->multicast_ctx.ip6_mc_router_timer);
- return !hlist_unhashed(&port->multicast_ctx.ip6_rlist);
+ *timer = br_timer_value(&pmctx->ip6_mc_router_timer);
+ return !hlist_unhashed(&pmctx->ip6_rlist);
#else
*timer = 0;
return false;
#endif
}
-static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
- struct net_device *dev)
+static int br_rports_fill_info(struct sk_buff *skb,
+ const struct net_bridge_mcast *brmctx)
{
- struct net_bridge *br = netdev_priv(dev);
+ u16 vid = brmctx->vlan ? brmctx->vlan->vid : 0;
bool have_ip4_mc_rtr, have_ip6_mc_rtr;
unsigned long ip4_timer, ip6_timer;
struct nlattr *nest, *port_nest;
struct net_bridge_port *p;
- if (!br->multicast_ctx.multicast_router)
- return 0;
-
- if (!br_rports_have_mc_router(&br->multicast_ctx))
+ if (!brmctx->multicast_router || !br_rports_have_mc_router(brmctx))
return 0;
nest = nla_nest_start_noflag(skb, MDBA_ROUTER);
if (nest == NULL)
return -EMSGSIZE;
- list_for_each_entry_rcu(p, &br->port_list, list) {
- have_ip4_mc_rtr = br_ip4_rports_get_timer(p, &ip4_timer);
- have_ip6_mc_rtr = br_ip6_rports_get_timer(p, &ip6_timer);
+ list_for_each_entry_rcu(p, &brmctx->br->port_list, list) {
+ struct net_bridge_mcast_port *pmctx;
+
+ if (vid) {
+ struct net_bridge_vlan *v;
+
+ v = br_vlan_find(nbp_vlan_group(p), vid);
+ if (!v)
+ continue;
+ pmctx = &v->port_mcast_ctx;
+ } else {
+ pmctx = &p->multicast_ctx;
+ }
+
+ have_ip4_mc_rtr = br_ip4_rports_get_timer(pmctx, &ip4_timer);
+ have_ip6_mc_rtr = br_ip6_rports_get_timer(pmctx, &ip6_timer);
if (!have_ip4_mc_rtr && !have_ip6_mc_rtr)
continue;
@@ -390,6 +402,7 @@ static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
for_each_netdev_rcu(net, dev) {
if (dev->priv_flags & IFF_EBRIDGE) {
+ struct net_bridge *br = netdev_priv(dev);
struct br_port_msg *bpm;
if (idx < s_idx)
@@ -406,7 +419,7 @@ static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
bpm->ifindex = dev->ifindex;
if (br_mdb_fill_info(skb, cb, dev) < 0)
goto out;
- if (br_rports_fill_info(skb, cb, dev) < 0)
+ if (br_rports_fill_info(skb, &br->multicast_ctx) < 0)
goto out;
cb->args[1] = 0;