Commit 613d61db authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller

net: bridge: vlan: add global and per-port multicast context

Add global and per-port vlan multicast context, only initialized but
still not used. No functional changes intended.
Signed-off-by: default avatarNikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent adc47037
...@@ -80,6 +80,7 @@ __br_multicast_add_group(struct net_bridge_mcast *brmctx, ...@@ -80,6 +80,7 @@ __br_multicast_add_group(struct net_bridge_mcast *brmctx,
bool blocked); bool blocked);
static void br_multicast_find_del_pg(struct net_bridge *br, static void br_multicast_find_del_pg(struct net_bridge *br,
struct net_bridge_port_group *pg); struct net_bridge_port_group *pg);
static void __br_multicast_stop(struct net_bridge_mcast *brmctx);
static struct net_bridge_port_group * static struct net_bridge_port_group *
br_sg_port_find(struct net_bridge *br, br_sg_port_find(struct net_bridge *br,
...@@ -1696,10 +1697,12 @@ static int br_mc_disabled_update(struct net_device *dev, bool value, ...@@ -1696,10 +1697,12 @@ 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);
} }
static void br_multicast_port_ctx_init(struct net_bridge_port *port, void br_multicast_port_ctx_init(struct net_bridge_port *port,
struct net_bridge_mcast_port *pmctx) struct net_bridge_vlan *vlan,
struct net_bridge_mcast_port *pmctx)
{ {
pmctx->port = port; pmctx->port = port;
pmctx->vlan = vlan;
pmctx->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; pmctx->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
timer_setup(&pmctx->ip4_mc_router_timer, timer_setup(&pmctx->ip4_mc_router_timer,
br_ip4_multicast_router_expired, 0); br_ip4_multicast_router_expired, 0);
...@@ -1713,7 +1716,7 @@ static void br_multicast_port_ctx_init(struct net_bridge_port *port, ...@@ -1713,7 +1716,7 @@ static void br_multicast_port_ctx_init(struct net_bridge_port *port,
#endif #endif
} }
static void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx) void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx)
{ {
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
del_timer_sync(&pmctx->ip6_mc_router_timer); del_timer_sync(&pmctx->ip6_mc_router_timer);
...@@ -1726,7 +1729,7 @@ int br_multicast_add_port(struct net_bridge_port *port) ...@@ -1726,7 +1729,7 @@ int br_multicast_add_port(struct net_bridge_port *port)
int err; int err;
port->multicast_eht_hosts_limit = BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT; port->multicast_eht_hosts_limit = BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT;
br_multicast_port_ctx_init(port, &port->multicast_ctx); br_multicast_port_ctx_init(port, NULL, &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,
...@@ -3571,48 +3574,63 @@ static void br_multicast_gc_work(struct work_struct *work) ...@@ -3571,48 +3574,63 @@ static void br_multicast_gc_work(struct work_struct *work)
br_multicast_gc(&deleted_head); br_multicast_gc(&deleted_head);
} }
void br_multicast_init(struct net_bridge *br) void br_multicast_ctx_init(struct net_bridge *br,
struct net_bridge_vlan *vlan,
struct net_bridge_mcast *brmctx)
{ {
br->hash_max = BR_MULTICAST_DEFAULT_HASH_MAX; brmctx->br = br;
brmctx->vlan = vlan;
brmctx->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
brmctx->multicast_last_member_count = 2;
brmctx->multicast_startup_query_count = 2;
br->multicast_ctx.br = br; brmctx->multicast_last_member_interval = HZ;
br->multicast_ctx.multicast_router = MDB_RTR_TYPE_TEMP_QUERY; brmctx->multicast_query_response_interval = 10 * HZ;
br->multicast_ctx.multicast_last_member_count = 2; brmctx->multicast_startup_query_interval = 125 * HZ / 4;
br->multicast_ctx.multicast_startup_query_count = 2; brmctx->multicast_query_interval = 125 * HZ;
brmctx->multicast_querier_interval = 255 * HZ;
br->multicast_ctx.multicast_last_member_interval = HZ; brmctx->multicast_membership_interval = 260 * HZ;
br->multicast_ctx.multicast_query_response_interval = 10 * HZ;
br->multicast_ctx.multicast_startup_query_interval = 125 * HZ / 4; brmctx->ip4_other_query.delay_time = 0;
br->multicast_ctx.multicast_query_interval = 125 * HZ; brmctx->ip4_querier.port = NULL;
br->multicast_ctx.multicast_querier_interval = 255 * HZ; brmctx->multicast_igmp_version = 2;
br->multicast_ctx.multicast_membership_interval = 260 * HZ;
br->multicast_ctx.ip4_other_query.delay_time = 0;
br->multicast_ctx.ip4_querier.port = NULL;
br->multicast_ctx.multicast_igmp_version = 2;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
br->multicast_ctx.multicast_mld_version = 1; brmctx->multicast_mld_version = 1;
br->multicast_ctx.ip6_other_query.delay_time = 0; brmctx->ip6_other_query.delay_time = 0;
br->multicast_ctx.ip6_querier.port = NULL; brmctx->ip6_querier.port = NULL;
#endif #endif
br_opt_toggle(br, BROPT_MULTICAST_ENABLED, true);
br_opt_toggle(br, BROPT_HAS_IPV6_ADDR, true);
spin_lock_init(&br->multicast_lock); timer_setup(&brmctx->ip4_mc_router_timer,
timer_setup(&br->multicast_ctx.ip4_mc_router_timer,
br_ip4_multicast_local_router_expired, 0); br_ip4_multicast_local_router_expired, 0);
timer_setup(&br->multicast_ctx.ip4_other_query.timer, timer_setup(&brmctx->ip4_other_query.timer,
br_ip4_multicast_querier_expired, 0); br_ip4_multicast_querier_expired, 0);
timer_setup(&br->multicast_ctx.ip4_own_query.timer, timer_setup(&brmctx->ip4_own_query.timer,
br_ip4_multicast_query_expired, 0); br_ip4_multicast_query_expired, 0);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
timer_setup(&br->multicast_ctx.ip6_mc_router_timer, timer_setup(&brmctx->ip6_mc_router_timer,
br_ip6_multicast_local_router_expired, 0); br_ip6_multicast_local_router_expired, 0);
timer_setup(&br->multicast_ctx.ip6_other_query.timer, timer_setup(&brmctx->ip6_other_query.timer,
br_ip6_multicast_querier_expired, 0); br_ip6_multicast_querier_expired, 0);
timer_setup(&br->multicast_ctx.ip6_own_query.timer, timer_setup(&brmctx->ip6_own_query.timer,
br_ip6_multicast_query_expired, 0); br_ip6_multicast_query_expired, 0);
#endif #endif
}
void br_multicast_ctx_deinit(struct net_bridge_mcast *brmctx)
{
__br_multicast_stop(brmctx);
}
void br_multicast_init(struct net_bridge *br)
{
br->hash_max = BR_MULTICAST_DEFAULT_HASH_MAX;
br_multicast_ctx_init(br, NULL, &br->multicast_ctx);
br_opt_toggle(br, BROPT_MULTICAST_ENABLED, true);
br_opt_toggle(br, BROPT_HAS_IPV6_ADDR, true);
spin_lock_init(&br->multicast_lock);
INIT_HLIST_HEAD(&br->mdb_list); INIT_HLIST_HEAD(&br->mdb_list);
INIT_HLIST_HEAD(&br->mcast_gc_list); INIT_HLIST_HEAD(&br->mcast_gc_list);
INIT_WORK(&br->mcast_gc_work, br_multicast_gc_work); INIT_WORK(&br->mcast_gc_work, br_multicast_gc_work);
...@@ -3699,18 +3717,23 @@ void br_multicast_open(struct net_bridge *br) ...@@ -3699,18 +3717,23 @@ void br_multicast_open(struct net_bridge *br)
#endif #endif
} }
void br_multicast_stop(struct net_bridge *br) static void __br_multicast_stop(struct net_bridge_mcast *brmctx)
{ {
del_timer_sync(&br->multicast_ctx.ip4_mc_router_timer); del_timer_sync(&brmctx->ip4_mc_router_timer);
del_timer_sync(&br->multicast_ctx.ip4_other_query.timer); del_timer_sync(&brmctx->ip4_other_query.timer);
del_timer_sync(&br->multicast_ctx.ip4_own_query.timer); del_timer_sync(&brmctx->ip4_own_query.timer);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
del_timer_sync(&br->multicast_ctx.ip6_mc_router_timer); del_timer_sync(&brmctx->ip6_mc_router_timer);
del_timer_sync(&br->multicast_ctx.ip6_other_query.timer); del_timer_sync(&brmctx->ip6_other_query.timer);
del_timer_sync(&br->multicast_ctx.ip6_own_query.timer); del_timer_sync(&brmctx->ip6_own_query.timer);
#endif #endif
} }
void br_multicast_stop(struct net_bridge *br)
{
__br_multicast_stop(&br->multicast_ctx);
}
void br_multicast_dev_del(struct net_bridge *br) void br_multicast_dev_del(struct net_bridge *br)
{ {
struct net_bridge_mdb_entry *mp; struct net_bridge_mdb_entry *mp;
...@@ -3723,6 +3746,7 @@ void br_multicast_dev_del(struct net_bridge *br) ...@@ -3723,6 +3746,7 @@ void br_multicast_dev_del(struct net_bridge *br)
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_ctx_deinit(&br->multicast_ctx);
br_multicast_gc(&deleted_head); br_multicast_gc(&deleted_head);
cancel_work_sync(&br->mcast_gc_work); cancel_work_sync(&br->mcast_gc_work);
......
...@@ -93,6 +93,7 @@ struct bridge_mcast_stats { ...@@ -93,6 +93,7 @@ struct bridge_mcast_stats {
struct net_bridge_mcast_port { struct net_bridge_mcast_port {
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
struct net_bridge_port *port; struct net_bridge_port *port;
struct net_bridge_vlan *vlan;
struct bridge_mcast_own_query ip4_own_query; struct bridge_mcast_own_query ip4_own_query;
struct timer_list ip4_mc_router_timer; struct timer_list ip4_mc_router_timer;
...@@ -110,6 +111,7 @@ struct net_bridge_mcast_port { ...@@ -110,6 +111,7 @@ struct net_bridge_mcast_port {
struct net_bridge_mcast { struct net_bridge_mcast {
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
struct net_bridge *br; struct net_bridge *br;
struct net_bridge_vlan *vlan;
u32 multicast_last_member_count; u32 multicast_last_member_count;
u32 multicast_startup_query_count; u32 multicast_startup_query_count;
...@@ -165,6 +167,9 @@ enum { ...@@ -165,6 +167,9 @@ enum {
* @refcnt: if MASTER flag set, this is bumped for each port referencing it * @refcnt: if MASTER flag set, this is bumped for each port referencing it
* @brvlan: if MASTER flag unset, this points to the global per-VLAN context * @brvlan: if MASTER flag unset, this points to the global per-VLAN context
* for this VLAN entry * for this VLAN entry
* @br_mcast_ctx: if MASTER flag set, this is the global vlan multicast context
* @port_mcast_ctx: if MASTER flag unset, this is the per-port/vlan multicast
* context
* @vlist: sorted list of VLAN entries * @vlist: sorted list of VLAN entries
* @rcu: used for entry destruction * @rcu: used for entry destruction
* *
...@@ -192,6 +197,11 @@ struct net_bridge_vlan { ...@@ -192,6 +197,11 @@ struct net_bridge_vlan {
struct br_tunnel_info tinfo; struct br_tunnel_info tinfo;
union {
struct net_bridge_mcast br_mcast_ctx;
struct net_bridge_mcast_port port_mcast_ctx;
};
struct list_head vlist; struct list_head vlist;
struct rcu_head rcu; struct rcu_head rcu;
...@@ -883,6 +893,14 @@ struct net_bridge_group_src * ...@@ -883,6 +893,14 @@ struct net_bridge_group_src *
br_multicast_find_group_src(struct net_bridge_port_group *pg, struct br_ip *ip); br_multicast_find_group_src(struct net_bridge_port_group *pg, struct br_ip *ip);
void br_multicast_del_group_src(struct net_bridge_group_src *src, void br_multicast_del_group_src(struct net_bridge_group_src *src,
bool fastleave); bool fastleave);
void br_multicast_ctx_init(struct net_bridge *br,
struct net_bridge_vlan *vlan,
struct net_bridge_mcast *brmctx);
void br_multicast_ctx_deinit(struct net_bridge_mcast *brmctx);
void br_multicast_port_ctx_init(struct net_bridge_port *port,
struct net_bridge_vlan *vlan,
struct net_bridge_mcast_port *pmctx);
void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx);
static inline bool br_group_is_l2(const struct br_ip *group) static inline bool br_group_is_l2(const struct br_ip *group)
{ {
...@@ -1157,6 +1175,26 @@ static inline int br_multicast_igmp_type(const struct sk_buff *skb) ...@@ -1157,6 +1175,26 @@ static inline int br_multicast_igmp_type(const struct sk_buff *skb)
{ {
return 0; return 0;
} }
static inline void br_multicast_ctx_init(struct net_bridge *br,
struct net_bridge_vlan *vlan,
struct net_bridge_mcast *brmctx)
{
}
static inline void br_multicast_ctx_deinit(struct net_bridge_mcast *brmctx)
{
}
static inline void br_multicast_port_ctx_init(struct net_bridge_port *port,
struct net_bridge_vlan *vlan,
struct net_bridge_mcast_port *pmctx)
{
}
static inline void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx)
{
}
#endif #endif
/* br_vlan.c */ /* br_vlan.c */
......
...@@ -190,6 +190,7 @@ static void br_vlan_put_master(struct net_bridge_vlan *masterv) ...@@ -190,6 +190,7 @@ static void br_vlan_put_master(struct net_bridge_vlan *masterv)
rhashtable_remove_fast(&vg->vlan_hash, rhashtable_remove_fast(&vg->vlan_hash,
&masterv->vnode, br_vlan_rht_params); &masterv->vnode, br_vlan_rht_params);
__vlan_del_list(masterv); __vlan_del_list(masterv);
br_multicast_ctx_deinit(&masterv->br_mcast_ctx);
call_rcu(&masterv->rcu, br_master_vlan_rcu_free); call_rcu(&masterv->rcu, br_master_vlan_rcu_free);
} }
} }
...@@ -280,10 +281,12 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags, ...@@ -280,10 +281,12 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags,
} else { } else {
v->stats = masterv->stats; v->stats = masterv->stats;
} }
br_multicast_port_ctx_init(p, v, &v->port_mcast_ctx);
} else { } else {
err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack); err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack);
if (err && err != -EOPNOTSUPP) if (err && err != -EOPNOTSUPP)
goto out; goto out;
br_multicast_ctx_init(br, v, &v->br_mcast_ctx);
} }
/* Add the dev mac and count the vlan only if it's usable */ /* Add the dev mac and count the vlan only if it's usable */
...@@ -374,6 +377,7 @@ static int __vlan_del(struct net_bridge_vlan *v) ...@@ -374,6 +377,7 @@ static int __vlan_del(struct net_bridge_vlan *v)
br_vlan_rht_params); br_vlan_rht_params);
__vlan_del_list(v); __vlan_del_list(v);
nbp_vlan_set_vlan_dev_state(p, v->vid); nbp_vlan_set_vlan_dev_state(p, v->vid);
br_multicast_port_ctx_deinit(&v->port_mcast_ctx);
call_rcu(&v->rcu, nbp_vlan_rcu_free); call_rcu(&v->rcu, nbp_vlan_rcu_free);
} }
......
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