diff options
| -rw-r--r-- | net/bridge/br_mst.c | 4 | ||||
| -rw-r--r-- | net/bridge/br_multicast.c | 26 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 11 | 
3 files changed, 38 insertions, 3 deletions
| diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c index 1820f09ff59c..3f24b4ee49c2 100644 --- a/net/bridge/br_mst.c +++ b/net/bridge/br_mst.c @@ -80,10 +80,10 @@ static void br_mst_vlan_set_state(struct net_bridge_vlan_group *vg,  	if (br_vlan_get_state(v) == state)  		return; -	br_vlan_set_state(v, state); -  	if (v->vid == vg->pvid)  		br_vlan_set_pvid_state(vg, state); + +	br_vlan_set_state(v, state);  }  int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state, diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index ce07fda6a848..7e0b2362b9ee 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -4272,6 +4272,32 @@ static void __br_multicast_stop(struct net_bridge_mcast *brmctx)  #endif  } +void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v, u8 state) +{ +#if IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING) +	struct net_bridge *br; + +	if (!br_vlan_should_use(v)) +		return; + +	if (br_vlan_is_master(v)) +		return; + +	br = v->port->br; + +	if (!br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) +		return; + +	if (br_vlan_state_allowed(state, true)) +		br_multicast_enable_port_ctx(&v->port_mcast_ctx); + +	/* Multicast is not disabled for the vlan when it goes in +	 * blocking state because the timers will expire and stop by +	 * themselves without sending more queries. +	 */ +#endif +} +  void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on)  {  	struct net_bridge *br; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 71f351a6ce1b..db1bddb330ff 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1055,6 +1055,7 @@ 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); +void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v, u8 state);  void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on);  int br_multicast_toggle_vlan_snooping(struct net_bridge *br, bool on,  				      struct netlink_ext_ack *extack); @@ -1521,6 +1522,11 @@ static inline void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pm  {  } +static inline void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v, +						      u8 state) +{ +} +  static inline void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan,  						bool on)  { @@ -1881,7 +1887,9 @@ bool br_vlan_global_opts_can_enter_range(const struct net_bridge_vlan *v_curr,  bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,  			      const struct net_bridge_vlan *v_opts); -/* vlan state manipulation helpers using *_ONCE to annotate lock-free access */ +/* vlan state manipulation helpers using *_ONCE to annotate lock-free access, + * while br_vlan_set_state() may access data protected by multicast_lock. + */  static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v)  {  	return READ_ONCE(v->state); @@ -1890,6 +1898,7 @@ static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v)  static inline void br_vlan_set_state(struct net_bridge_vlan *v, u8 state)  {  	WRITE_ONCE(v->state, state); +	br_multicast_update_vlan_mcast_ctx(v, state);  }  static inline u8 br_vlan_get_pvid_state(const struct net_bridge_vlan_group *vg) | 
