Commit 9632233e authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller

net: bridge: multicast: factor out port multicast context

Factor out the port's multicast context into a separate structure which
will later be shared for per-port,vlan context. No functional changes
intended. We need the structure even if bridge multicast is not defined
to pass down as pointer to forwarding functions.
Signed-off-by: default avatarNikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 23d2b940
...@@ -29,16 +29,16 @@ static bool br_rports_have_mc_router(struct net_bridge *br) ...@@ -29,16 +29,16 @@ static bool br_rports_have_mc_router(struct net_bridge *br)
static bool static bool
br_ip4_rports_get_timer(struct net_bridge_port *port, unsigned long *timer) br_ip4_rports_get_timer(struct net_bridge_port *port, unsigned long *timer)
{ {
*timer = br_timer_value(&port->ip4_mc_router_timer); *timer = br_timer_value(&port->multicast_ctx.ip4_mc_router_timer);
return !hlist_unhashed(&port->ip4_rlist); return !hlist_unhashed(&port->multicast_ctx.ip4_rlist);
} }
static bool static bool
br_ip6_rports_get_timer(struct net_bridge_port *port, unsigned long *timer) br_ip6_rports_get_timer(struct net_bridge_port *port, unsigned long *timer)
{ {
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
*timer = br_timer_value(&port->ip6_mc_router_timer); *timer = br_timer_value(&port->multicast_ctx.ip6_mc_router_timer);
return !hlist_unhashed(&port->ip6_rlist); return !hlist_unhashed(&port->multicast_ctx.ip6_rlist);
#else #else
*timer = 0; *timer = 0;
return false; return false;
...@@ -79,7 +79,7 @@ static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb, ...@@ -79,7 +79,7 @@ static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
nla_put_u32(skb, MDBA_ROUTER_PATTR_TIMER, nla_put_u32(skb, MDBA_ROUTER_PATTR_TIMER,
max(ip4_timer, ip6_timer)) || max(ip4_timer, ip6_timer)) ||
nla_put_u8(skb, MDBA_ROUTER_PATTR_TYPE, nla_put_u8(skb, MDBA_ROUTER_PATTR_TYPE,
p->multicast_router) || p->multicast_ctx.multicast_router) ||
(have_ip4_mc_rtr && (have_ip4_mc_rtr &&
nla_put_u32(skb, MDBA_ROUTER_PATTR_INET_TIMER, nla_put_u32(skb, MDBA_ROUTER_PATTR_INET_TIMER,
ip4_timer)) || ip4_timer)) ||
......
...@@ -1368,50 +1368,52 @@ static bool br_multicast_rport_del(struct hlist_node *rlist) ...@@ -1368,50 +1368,52 @@ static bool br_multicast_rport_del(struct hlist_node *rlist)
static bool br_ip4_multicast_rport_del(struct net_bridge_port *p) static bool br_ip4_multicast_rport_del(struct net_bridge_port *p)
{ {
return br_multicast_rport_del(&p->ip4_rlist); return br_multicast_rport_del(&p->multicast_ctx.ip4_rlist);
} }
static bool br_ip6_multicast_rport_del(struct net_bridge_port *p) static bool br_ip6_multicast_rport_del(struct net_bridge_port *p)
{ {
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
return br_multicast_rport_del(&p->ip6_rlist); return br_multicast_rport_del(&p->multicast_ctx.ip6_rlist);
#else #else
return false; return false;
#endif #endif
} }
static void br_multicast_router_expired(struct net_bridge_port *port, static void br_multicast_router_expired(struct net_bridge_mcast_port *pmctx,
struct timer_list *t, struct timer_list *t,
struct hlist_node *rlist) struct hlist_node *rlist)
{ {
struct net_bridge *br = port->br; struct net_bridge *br = pmctx->port->br;
bool del; bool del;
spin_lock(&br->multicast_lock); spin_lock(&br->multicast_lock);
if (port->multicast_router == MDB_RTR_TYPE_DISABLED || if (pmctx->multicast_router == MDB_RTR_TYPE_DISABLED ||
port->multicast_router == MDB_RTR_TYPE_PERM || pmctx->multicast_router == MDB_RTR_TYPE_PERM ||
timer_pending(t)) timer_pending(t))
goto out; goto out;
del = br_multicast_rport_del(rlist); del = br_multicast_rport_del(rlist);
br_multicast_rport_del_notify(port, del); br_multicast_rport_del_notify(pmctx->port, del);
out: out:
spin_unlock(&br->multicast_lock); spin_unlock(&br->multicast_lock);
} }
static void br_ip4_multicast_router_expired(struct timer_list *t) static void br_ip4_multicast_router_expired(struct timer_list *t)
{ {
struct net_bridge_port *port = from_timer(port, t, ip4_mc_router_timer); struct net_bridge_mcast_port *pmctx = from_timer(pmctx, t,
ip4_mc_router_timer);
br_multicast_router_expired(port, t, &port->ip4_rlist); br_multicast_router_expired(pmctx, t, &pmctx->ip4_rlist);
} }
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
static void br_ip6_multicast_router_expired(struct timer_list *t) static void br_ip6_multicast_router_expired(struct timer_list *t)
{ {
struct net_bridge_port *port = from_timer(port, t, ip6_mc_router_timer); struct net_bridge_mcast_port *pmctx = from_timer(pmctx, t,
ip6_mc_router_timer);
br_multicast_router_expired(port, t, &port->ip6_rlist); br_multicast_router_expired(pmctx, t, &pmctx->ip6_rlist);
} }
#endif #endif
...@@ -1555,7 +1557,7 @@ static void br_multicast_send_query(struct net_bridge *br, ...@@ -1555,7 +1557,7 @@ static void br_multicast_send_query(struct net_bridge *br,
memset(&br_group.dst, 0, sizeof(br_group.dst)); memset(&br_group.dst, 0, sizeof(br_group.dst));
if (port ? (own_query == &port->ip4_own_query) : if (port ? (own_query == &port->multicast_ctx.ip4_own_query) :
(own_query == &br->ip4_own_query)) { (own_query == &br->ip4_own_query)) {
other_query = &br->ip4_other_query; other_query = &br->ip4_other_query;
br_group.proto = htons(ETH_P_IP); br_group.proto = htons(ETH_P_IP);
...@@ -1580,20 +1582,20 @@ static void br_multicast_send_query(struct net_bridge *br, ...@@ -1580,20 +1582,20 @@ static void br_multicast_send_query(struct net_bridge *br,
} }
static void static void
br_multicast_port_query_expired(struct net_bridge_port *port, br_multicast_port_query_expired(struct net_bridge_mcast_port *pmctx,
struct bridge_mcast_own_query *query) struct bridge_mcast_own_query *query)
{ {
struct net_bridge *br = port->br; struct net_bridge *br = pmctx->port->br;
spin_lock(&br->multicast_lock); spin_lock(&br->multicast_lock);
if (port->state == BR_STATE_DISABLED || if (pmctx->port->state == BR_STATE_DISABLED ||
port->state == BR_STATE_BLOCKING) pmctx->port->state == BR_STATE_BLOCKING)
goto out; goto out;
if (query->startup_sent < br->multicast_startup_query_count) if (query->startup_sent < br->multicast_startup_query_count)
query->startup_sent++; query->startup_sent++;
br_multicast_send_query(port->br, port, query); br_multicast_send_query(pmctx->port->br, pmctx->port, query);
out: out:
spin_unlock(&br->multicast_lock); spin_unlock(&br->multicast_lock);
...@@ -1601,17 +1603,19 @@ br_multicast_port_query_expired(struct net_bridge_port *port, ...@@ -1601,17 +1603,19 @@ br_multicast_port_query_expired(struct net_bridge_port *port,
static void br_ip4_multicast_port_query_expired(struct timer_list *t) static void br_ip4_multicast_port_query_expired(struct timer_list *t)
{ {
struct net_bridge_port *port = from_timer(port, t, ip4_own_query.timer); struct net_bridge_mcast_port *pmctx = from_timer(pmctx, t,
ip4_own_query.timer);
br_multicast_port_query_expired(port, &port->ip4_own_query); br_multicast_port_query_expired(pmctx, &pmctx->ip4_own_query);
} }
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
static void br_ip6_multicast_port_query_expired(struct timer_list *t) static void br_ip6_multicast_port_query_expired(struct timer_list *t)
{ {
struct net_bridge_port *port = from_timer(port, t, ip6_own_query.timer); struct net_bridge_mcast_port *pmctx = from_timer(pmctx, t,
ip6_own_query.timer);
br_multicast_port_query_expired(port, &port->ip6_own_query); br_multicast_port_query_expired(pmctx, &pmctx->ip6_own_query);
} }
#endif #endif
...@@ -1666,23 +1670,38 @@ static int br_mc_disabled_update(struct net_device *dev, bool value, ...@@ -1666,23 +1670,38 @@ static int br_mc_disabled_update(struct net_device *dev, bool value,
return switchdev_port_attr_set(dev, &attr, extack); return switchdev_port_attr_set(dev, &attr, extack);
} }
int br_multicast_add_port(struct net_bridge_port *port) static void br_multicast_port_ctx_init(struct net_bridge_port *port,
struct net_bridge_mcast_port *pmctx)
{ {
int err; pmctx->port = port;
pmctx->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; timer_setup(&pmctx->ip4_mc_router_timer,
port->multicast_eht_hosts_limit = BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT;
timer_setup(&port->ip4_mc_router_timer,
br_ip4_multicast_router_expired, 0); br_ip4_multicast_router_expired, 0);
timer_setup(&port->ip4_own_query.timer, timer_setup(&pmctx->ip4_own_query.timer,
br_ip4_multicast_port_query_expired, 0); br_ip4_multicast_port_query_expired, 0);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
timer_setup(&port->ip6_mc_router_timer, timer_setup(&pmctx->ip6_mc_router_timer,
br_ip6_multicast_router_expired, 0); br_ip6_multicast_router_expired, 0);
timer_setup(&port->ip6_own_query.timer, timer_setup(&pmctx->ip6_own_query.timer,
br_ip6_multicast_port_query_expired, 0); br_ip6_multicast_port_query_expired, 0);
#endif #endif
}
static void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx)
{
#if IS_ENABLED(CONFIG_IPV6)
del_timer_sync(&pmctx->ip6_mc_router_timer);
#endif
del_timer_sync(&pmctx->ip4_mc_router_timer);
}
int br_multicast_add_port(struct net_bridge_port *port)
{
int err;
port->multicast_eht_hosts_limit = BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT;
br_multicast_port_ctx_init(port, &port->multicast_ctx);
err = br_mc_disabled_update(port->dev, err = br_mc_disabled_update(port->dev,
br_opt_get(port->br, br_opt_get(port->br,
BROPT_MULTICAST_ENABLED), BROPT_MULTICAST_ENABLED),
...@@ -1711,10 +1730,7 @@ void br_multicast_del_port(struct net_bridge_port *port) ...@@ -1711,10 +1730,7 @@ void br_multicast_del_port(struct net_bridge_port *port)
hlist_move_list(&br->mcast_gc_list, &deleted_head); hlist_move_list(&br->mcast_gc_list, &deleted_head);
spin_unlock_bh(&br->multicast_lock); spin_unlock_bh(&br->multicast_lock);
br_multicast_gc(&deleted_head); br_multicast_gc(&deleted_head);
del_timer_sync(&port->ip4_mc_router_timer); br_multicast_port_ctx_deinit(&port->multicast_ctx);
#if IS_ENABLED(CONFIG_IPV6)
del_timer_sync(&port->ip6_mc_router_timer);
#endif
free_percpu(port->mcast_stats); free_percpu(port->mcast_stats);
} }
...@@ -1734,11 +1750,11 @@ static void __br_multicast_enable_port(struct net_bridge_port *port) ...@@ -1734,11 +1750,11 @@ static void __br_multicast_enable_port(struct net_bridge_port *port)
if (!br_opt_get(br, BROPT_MULTICAST_ENABLED) || !netif_running(br->dev)) if (!br_opt_get(br, BROPT_MULTICAST_ENABLED) || !netif_running(br->dev))
return; return;
br_multicast_enable(&port->ip4_own_query); br_multicast_enable(&port->multicast_ctx.ip4_own_query);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
br_multicast_enable(&port->ip6_own_query); br_multicast_enable(&port->multicast_ctx.ip6_own_query);
#endif #endif
if (port->multicast_router == MDB_RTR_TYPE_PERM) { if (port->multicast_ctx.multicast_router == MDB_RTR_TYPE_PERM) {
br_ip4_multicast_add_router(br, port); br_ip4_multicast_add_router(br, port);
br_ip6_multicast_add_router(br, port); br_ip6_multicast_add_router(br, port);
} }
...@@ -1766,12 +1782,12 @@ void br_multicast_disable_port(struct net_bridge_port *port) ...@@ -1766,12 +1782,12 @@ void br_multicast_disable_port(struct net_bridge_port *port)
br_multicast_find_del_pg(br, pg); br_multicast_find_del_pg(br, pg);
del |= br_ip4_multicast_rport_del(port); del |= br_ip4_multicast_rport_del(port);
del_timer(&port->ip4_mc_router_timer); del_timer(&port->multicast_ctx.ip4_mc_router_timer);
del_timer(&port->ip4_own_query.timer); del_timer(&port->multicast_ctx.ip4_own_query.timer);
del |= br_ip6_multicast_rport_del(port); del |= br_ip6_multicast_rport_del(port);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
del_timer(&port->ip6_mc_router_timer); del_timer(&port->multicast_ctx.ip6_mc_router_timer);
del_timer(&port->ip6_own_query.timer); del_timer(&port->multicast_ctx.ip6_own_query.timer);
#endif #endif
br_multicast_rport_del_notify(port, del); br_multicast_rport_del_notify(port, del);
spin_unlock(&br->multicast_lock); spin_unlock(&br->multicast_lock);
...@@ -2713,11 +2729,18 @@ br_multicast_rport_from_node(struct net_bridge *br, ...@@ -2713,11 +2729,18 @@ br_multicast_rport_from_node(struct net_bridge *br,
struct hlist_head *mc_router_list, struct hlist_head *mc_router_list,
struct hlist_node *rlist) struct hlist_node *rlist)
{ {
struct net_bridge_mcast_port *pmctx;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
if (mc_router_list == &br->ip6_mc_router_list) if (mc_router_list == &br->ip6_mc_router_list)
return hlist_entry(rlist, struct net_bridge_port, ip6_rlist); pmctx = hlist_entry(rlist, struct net_bridge_mcast_port,
ip6_rlist);
else
#endif #endif
return hlist_entry(rlist, struct net_bridge_port, ip4_rlist); pmctx = hlist_entry(rlist, struct net_bridge_mcast_port,
ip4_rlist);
return pmctx->port;
} }
static struct hlist_node * static struct hlist_node *
...@@ -2746,10 +2769,10 @@ static bool br_multicast_no_router_otherpf(struct net_bridge_port *port, ...@@ -2746,10 +2769,10 @@ static bool br_multicast_no_router_otherpf(struct net_bridge_port *port,
struct hlist_node *rnode) struct hlist_node *rnode)
{ {
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
if (rnode != &port->ip6_rlist) if (rnode != &port->multicast_ctx.ip6_rlist)
return hlist_unhashed(&port->ip6_rlist); return hlist_unhashed(&port->multicast_ctx.ip6_rlist);
else else
return hlist_unhashed(&port->ip4_rlist); return hlist_unhashed(&port->multicast_ctx.ip4_rlist);
#else #else
return true; return true;
#endif #endif
...@@ -2793,7 +2816,7 @@ static void br_multicast_add_router(struct net_bridge *br, ...@@ -2793,7 +2816,7 @@ static void br_multicast_add_router(struct net_bridge *br,
static void br_ip4_multicast_add_router(struct net_bridge *br, static void br_ip4_multicast_add_router(struct net_bridge *br,
struct net_bridge_port *port) struct net_bridge_port *port)
{ {
br_multicast_add_router(br, port, &port->ip4_rlist, br_multicast_add_router(br, port, &port->multicast_ctx.ip4_rlist,
&br->ip4_mc_router_list); &br->ip4_mc_router_list);
} }
...@@ -2805,7 +2828,7 @@ static void br_ip6_multicast_add_router(struct net_bridge *br, ...@@ -2805,7 +2828,7 @@ static void br_ip6_multicast_add_router(struct net_bridge *br,
struct net_bridge_port *port) struct net_bridge_port *port)
{ {
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
br_multicast_add_router(br, port, &port->ip6_rlist, br_multicast_add_router(br, port, &port->multicast_ctx.ip6_rlist,
&br->ip6_mc_router_list); &br->ip6_mc_router_list);
#endif #endif
} }
...@@ -2828,8 +2851,8 @@ static void br_multicast_mark_router(struct net_bridge *br, ...@@ -2828,8 +2851,8 @@ static void br_multicast_mark_router(struct net_bridge *br,
return; return;
} }
if (port->multicast_router == MDB_RTR_TYPE_DISABLED || if (port->multicast_ctx.multicast_router == MDB_RTR_TYPE_DISABLED ||
port->multicast_router == MDB_RTR_TYPE_PERM) port->multicast_ctx.multicast_router == MDB_RTR_TYPE_PERM)
return; return;
br_multicast_add_router(br, port, rlist, mc_router_list); br_multicast_add_router(br, port, rlist, mc_router_list);
...@@ -2843,8 +2866,8 @@ static void br_ip4_multicast_mark_router(struct net_bridge *br, ...@@ -2843,8 +2866,8 @@ static void br_ip4_multicast_mark_router(struct net_bridge *br,
struct hlist_node *rlist = NULL; struct hlist_node *rlist = NULL;
if (port) { if (port) {
timer = &port->ip4_mc_router_timer; timer = &port->multicast_ctx.ip4_mc_router_timer;
rlist = &port->ip4_rlist; rlist = &port->multicast_ctx.ip4_rlist;
} }
br_multicast_mark_router(br, port, timer, rlist, br_multicast_mark_router(br, port, timer, rlist,
...@@ -2859,8 +2882,8 @@ static void br_ip6_multicast_mark_router(struct net_bridge *br, ...@@ -2859,8 +2882,8 @@ static void br_ip6_multicast_mark_router(struct net_bridge *br,
struct hlist_node *rlist = NULL; struct hlist_node *rlist = NULL;
if (port) { if (port) {
timer = &port->ip6_mc_router_timer; timer = &port->multicast_ctx.ip6_mc_router_timer;
rlist = &port->ip6_rlist; rlist = &port->multicast_ctx.ip6_rlist;
} }
br_multicast_mark_router(br, port, timer, rlist, br_multicast_mark_router(br, port, timer, rlist,
...@@ -3183,7 +3206,8 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br, ...@@ -3183,7 +3206,8 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
if (ipv4_is_local_multicast(group)) if (ipv4_is_local_multicast(group))
return; return;
own_query = port ? &port->ip4_own_query : &br->ip4_own_query; own_query = port ? &port->multicast_ctx.ip4_own_query :
&br->ip4_own_query;
memset(&br_group, 0, sizeof(br_group)); memset(&br_group, 0, sizeof(br_group));
br_group.dst.ip4 = group; br_group.dst.ip4 = group;
...@@ -3207,7 +3231,8 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br, ...@@ -3207,7 +3231,8 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
if (ipv6_addr_is_ll_all_nodes(group)) if (ipv6_addr_is_ll_all_nodes(group))
return; return;
own_query = port ? &port->ip6_own_query : &br->ip6_own_query; own_query = port ? &port->multicast_ctx.ip6_own_query :
&br->ip6_own_query;
memset(&br_group, 0, sizeof(br_group)); memset(&br_group, 0, sizeof(br_group));
br_group.dst.ip6 = *group; br_group.dst.ip6 = *group;
...@@ -3668,10 +3693,10 @@ br_multicast_rport_del_notify(struct net_bridge_port *p, bool deleted) ...@@ -3668,10 +3693,10 @@ br_multicast_rport_del_notify(struct net_bridge_port *p, bool deleted)
/* For backwards compatibility for now, only notify if there is /* For backwards compatibility for now, only notify if there is
* no multicast router anymore for both IPv4 and IPv6. * no multicast router anymore for both IPv4 and IPv6.
*/ */
if (!hlist_unhashed(&p->ip4_rlist)) if (!hlist_unhashed(&p->multicast_ctx.ip4_rlist))
return; return;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
if (!hlist_unhashed(&p->ip6_rlist)) if (!hlist_unhashed(&p->multicast_ctx.ip6_rlist))
return; return;
#endif #endif
...@@ -3679,8 +3704,8 @@ br_multicast_rport_del_notify(struct net_bridge_port *p, bool deleted) ...@@ -3679,8 +3704,8 @@ br_multicast_rport_del_notify(struct net_bridge_port *p, bool deleted)
br_port_mc_router_state_change(p, false); br_port_mc_router_state_change(p, false);
/* don't allow timer refresh */ /* don't allow timer refresh */
if (p->multicast_router == MDB_RTR_TYPE_TEMP) if (p->multicast_ctx.multicast_router == MDB_RTR_TYPE_TEMP)
p->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; p->multicast_ctx.multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
} }
int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val)
...@@ -3691,13 +3716,13 @@ int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) ...@@ -3691,13 +3716,13 @@ int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val)
bool del = false; bool del = false;
spin_lock(&br->multicast_lock); spin_lock(&br->multicast_lock);
if (p->multicast_router == val) { if (p->multicast_ctx.multicast_router == val) {
/* Refresh the temp router port timer */ /* Refresh the temp router port timer */
if (p->multicast_router == MDB_RTR_TYPE_TEMP) { if (p->multicast_ctx.multicast_router == MDB_RTR_TYPE_TEMP) {
mod_timer(&p->ip4_mc_router_timer, mod_timer(&p->multicast_ctx.ip4_mc_router_timer,
now + br->multicast_querier_interval); now + br->multicast_querier_interval);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
mod_timer(&p->ip6_mc_router_timer, mod_timer(&p->multicast_ctx.ip6_mc_router_timer,
now + br->multicast_querier_interval); now + br->multicast_querier_interval);
#endif #endif
} }
...@@ -3706,32 +3731,32 @@ int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) ...@@ -3706,32 +3731,32 @@ int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val)
} }
switch (val) { switch (val) {
case MDB_RTR_TYPE_DISABLED: case MDB_RTR_TYPE_DISABLED:
p->multicast_router = MDB_RTR_TYPE_DISABLED; p->multicast_ctx.multicast_router = MDB_RTR_TYPE_DISABLED;
del |= br_ip4_multicast_rport_del(p); del |= br_ip4_multicast_rport_del(p);
del_timer(&p->ip4_mc_router_timer); del_timer(&p->multicast_ctx.ip4_mc_router_timer);
del |= br_ip6_multicast_rport_del(p); del |= br_ip6_multicast_rport_del(p);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
del_timer(&p->ip6_mc_router_timer); del_timer(&p->multicast_ctx.ip6_mc_router_timer);
#endif #endif
br_multicast_rport_del_notify(p, del); br_multicast_rport_del_notify(p, del);
break; break;
case MDB_RTR_TYPE_TEMP_QUERY: case MDB_RTR_TYPE_TEMP_QUERY:
p->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; p->multicast_ctx.multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
del |= br_ip4_multicast_rport_del(p); del |= br_ip4_multicast_rport_del(p);
del |= br_ip6_multicast_rport_del(p); del |= br_ip6_multicast_rport_del(p);
br_multicast_rport_del_notify(p, del); br_multicast_rport_del_notify(p, del);
break; break;
case MDB_RTR_TYPE_PERM: case MDB_RTR_TYPE_PERM:
p->multicast_router = MDB_RTR_TYPE_PERM; p->multicast_ctx.multicast_router = MDB_RTR_TYPE_PERM;
del_timer(&p->ip4_mc_router_timer); del_timer(&p->multicast_ctx.ip4_mc_router_timer);
br_ip4_multicast_add_router(br, p); br_ip4_multicast_add_router(br, p);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
del_timer(&p->ip6_mc_router_timer); del_timer(&p->multicast_ctx.ip6_mc_router_timer);
#endif #endif
br_ip6_multicast_add_router(br, p); br_ip6_multicast_add_router(br, p);
break; break;
case MDB_RTR_TYPE_TEMP: case MDB_RTR_TYPE_TEMP:
p->multicast_router = MDB_RTR_TYPE_TEMP; p->multicast_ctx.multicast_router = MDB_RTR_TYPE_TEMP;
br_ip4_multicast_mark_router(br, p); br_ip4_multicast_mark_router(br, p);
br_ip6_multicast_mark_router(br, p); br_ip6_multicast_mark_router(br, p);
break; break;
...@@ -3759,10 +3784,10 @@ static void br_multicast_start_querier(struct net_bridge *br, ...@@ -3759,10 +3784,10 @@ static void br_multicast_start_querier(struct net_bridge *br,
continue; continue;
if (query == &br->ip4_own_query) if (query == &br->ip4_own_query)
br_multicast_enable(&port->ip4_own_query); br_multicast_enable(&port->multicast_ctx.ip4_own_query);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
else else
br_multicast_enable(&port->ip6_own_query); br_multicast_enable(&port->multicast_ctx.ip6_own_query);
#endif #endif
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -4071,7 +4096,8 @@ EXPORT_SYMBOL_GPL(br_multicast_has_querier_adjacent); ...@@ -4071,7 +4096,8 @@ EXPORT_SYMBOL_GPL(br_multicast_has_querier_adjacent);
*/ */
bool br_multicast_has_router_adjacent(struct net_device *dev, int proto) bool br_multicast_has_router_adjacent(struct net_device *dev, int proto)
{ {
struct net_bridge_port *port, *p; struct net_bridge_mcast_port *pmctx;
struct net_bridge_port *port;
bool ret = false; bool ret = false;
rcu_read_lock(); rcu_read_lock();
...@@ -4081,9 +4107,9 @@ bool br_multicast_has_router_adjacent(struct net_device *dev, int proto) ...@@ -4081,9 +4107,9 @@ bool br_multicast_has_router_adjacent(struct net_device *dev, int proto)
switch (proto) { switch (proto) {
case ETH_P_IP: case ETH_P_IP:
hlist_for_each_entry_rcu(p, &port->br->ip4_mc_router_list, hlist_for_each_entry_rcu(pmctx, &port->br->ip4_mc_router_list,
ip4_rlist) { ip4_rlist) {
if (p == port) if (pmctx->port == port)
continue; continue;
ret = true; ret = true;
...@@ -4092,9 +4118,9 @@ bool br_multicast_has_router_adjacent(struct net_device *dev, int proto) ...@@ -4092,9 +4118,9 @@ bool br_multicast_has_router_adjacent(struct net_device *dev, int proto)
break; break;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
case ETH_P_IPV6: case ETH_P_IPV6:
hlist_for_each_entry_rcu(p, &port->br->ip6_mc_router_list, hlist_for_each_entry_rcu(pmctx, &port->br->ip6_mc_router_list,
ip6_rlist) { ip6_rlist) {
if (p == port) if (pmctx->port == port)
continue; continue;
ret = true; ret = true;
......
...@@ -287,7 +287,7 @@ static int br_port_fill_attrs(struct sk_buff *skb, ...@@ -287,7 +287,7 @@ static int br_port_fill_attrs(struct sk_buff *skb,
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
if (nla_put_u8(skb, IFLA_BRPORT_MULTICAST_ROUTER, if (nla_put_u8(skb, IFLA_BRPORT_MULTICAST_ROUTER,
p->multicast_router) || p->multicast_ctx.multicast_router) ||
nla_put_u32(skb, IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT, nla_put_u32(skb, IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT,
p->multicast_eht_hosts_limit) || p->multicast_eht_hosts_limit) ||
nla_put_u32(skb, IFLA_BRPORT_MCAST_EHT_HOSTS_CNT, nla_put_u32(skb, IFLA_BRPORT_MCAST_EHT_HOSTS_CNT,
......
...@@ -89,6 +89,23 @@ struct bridge_mcast_stats { ...@@ -89,6 +89,23 @@ struct bridge_mcast_stats {
}; };
#endif #endif
/* net_bridge_mcast_port must be always defined due to forwarding stubs */
struct net_bridge_mcast_port {
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
struct net_bridge_port *port;
struct bridge_mcast_own_query ip4_own_query;
struct timer_list ip4_mc_router_timer;
struct hlist_node ip4_rlist;
#if IS_ENABLED(CONFIG_IPV6)
struct bridge_mcast_own_query ip6_own_query;
struct timer_list ip6_mc_router_timer;
struct hlist_node ip6_rlist;
#endif /* IS_ENABLED(CONFIG_IPV6) */
unsigned char multicast_router;
#endif /* CONFIG_BRIDGE_IGMP_SNOOPING */
};
struct br_tunnel_info { struct br_tunnel_info {
__be64 tunnel_id; __be64 tunnel_id;
struct metadata_dst __rcu *tunnel_dst; struct metadata_dst __rcu *tunnel_dst;
...@@ -305,19 +322,13 @@ struct net_bridge_port { ...@@ -305,19 +322,13 @@ struct net_bridge_port {
struct kobject kobj; struct kobject kobj;
struct rcu_head rcu; struct rcu_head rcu;
struct net_bridge_mcast_port multicast_ctx;
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
struct bridge_mcast_own_query ip4_own_query; struct bridge_mcast_stats __percpu *mcast_stats;
struct timer_list ip4_mc_router_timer;
struct hlist_node ip4_rlist;
#if IS_ENABLED(CONFIG_IPV6)
struct bridge_mcast_own_query ip6_own_query;
struct timer_list ip6_mc_router_timer;
struct hlist_node ip6_rlist;
#endif /* IS_ENABLED(CONFIG_IPV6) */
u32 multicast_eht_hosts_limit; u32 multicast_eht_hosts_limit;
u32 multicast_eht_hosts_cnt; u32 multicast_eht_hosts_cnt;
unsigned char multicast_router;
struct bridge_mcast_stats __percpu *mcast_stats;
struct hlist_head mglist; struct hlist_head mglist;
#endif #endif
...@@ -879,11 +890,21 @@ br_multicast_get_first_rport_node(struct net_bridge *b, struct sk_buff *skb) { ...@@ -879,11 +890,21 @@ br_multicast_get_first_rport_node(struct net_bridge *b, struct sk_buff *skb) {
static inline struct net_bridge_port * static inline struct net_bridge_port *
br_multicast_rport_from_node_skb(struct hlist_node *rp, struct sk_buff *skb) { br_multicast_rport_from_node_skb(struct hlist_node *rp, struct sk_buff *skb) {
struct net_bridge_mcast_port *mctx;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
if (skb->protocol == htons(ETH_P_IPV6)) if (skb->protocol == htons(ETH_P_IPV6))
return hlist_entry_safe(rp, struct net_bridge_port, ip6_rlist); mctx = hlist_entry_safe(rp, struct net_bridge_mcast_port,
ip6_rlist);
else
#endif #endif
return hlist_entry_safe(rp, struct net_bridge_port, ip4_rlist); mctx = hlist_entry_safe(rp, struct net_bridge_mcast_port,
ip4_rlist);
if (mctx)
return mctx->port;
else
return NULL;
} }
static inline bool br_ip4_multicast_is_router(struct net_bridge *br) static inline bool br_ip4_multicast_is_router(struct net_bridge *br)
......
...@@ -244,7 +244,7 @@ BRPORT_ATTR_FLAG(isolated, BR_ISOLATED); ...@@ -244,7 +244,7 @@ BRPORT_ATTR_FLAG(isolated, BR_ISOLATED);
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
{ {
return sprintf(buf, "%d\n", p->multicast_router); return sprintf(buf, "%d\n", p->multicast_ctx.multicast_router);
} }
static int store_multicast_router(struct net_bridge_port *p, static int store_multicast_router(struct net_bridge_port *p,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment