diff options
Diffstat (limited to 'net/bridge/br_multicast.c')
| -rw-r--r-- | net/bridge/br_multicast.c | 61 | 
1 files changed, 29 insertions, 32 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 9d265447d654..226bb05c3b42 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1593,7 +1593,8 @@ out:  	spin_unlock(&br->multicast_lock);  } -static void br_mc_disabled_update(struct net_device *dev, bool value) +static int br_mc_disabled_update(struct net_device *dev, bool value, +				 struct netlink_ext_ack *extack)  {  	struct switchdev_attr attr = {  		.orig_dev = dev, @@ -1602,11 +1603,13 @@ static void br_mc_disabled_update(struct net_device *dev, bool value)  		.u.mc_disabled = !value,  	}; -	switchdev_port_attr_set(dev, &attr, NULL); +	return switchdev_port_attr_set(dev, &attr, extack);  }  int br_multicast_add_port(struct net_bridge_port *port)  { +	int err; +  	port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;  	port->multicast_eht_hosts_limit = BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT; @@ -1618,8 +1621,12 @@ int br_multicast_add_port(struct net_bridge_port *port)  	timer_setup(&port->ip6_own_query.timer,  		    br_ip6_multicast_port_query_expired, 0);  #endif -	br_mc_disabled_update(port->dev, -			      br_opt_get(port->br, BROPT_MULTICAST_ENABLED)); +	err = br_mc_disabled_update(port->dev, +				    br_opt_get(port->br, +					       BROPT_MULTICAST_ENABLED), +				    NULL); +	if (err && err != -EOPNOTSUPP) +		return err;  	port->mcast_stats = netdev_alloc_pcpu_stats(struct bridge_mcast_stats);  	if (!port->mcast_stats) @@ -3152,25 +3159,14 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,  }  #if IS_ENABLED(CONFIG_IPV6) -static int br_ip6_multicast_mrd_rcv(struct net_bridge *br, -				    struct net_bridge_port *port, -				    struct sk_buff *skb) +static void br_ip6_multicast_mrd_rcv(struct net_bridge *br, +				     struct net_bridge_port *port, +				     struct sk_buff *skb)  { -	int ret; - -	if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6) -		return -ENOMSG; - -	ret = ipv6_mc_check_icmpv6(skb); -	if (ret < 0) -		return ret; -  	if (icmp6_hdr(skb)->icmp6_type != ICMPV6_MRDISC_ADV) -		return -ENOMSG; +		return;  	br_multicast_mark_router(br, port); - -	return 0;  }  static int br_multicast_ipv6_rcv(struct net_bridge *br, @@ -3184,18 +3180,12 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,  	err = ipv6_mc_check_mld(skb); -	if (err == -ENOMSG) { +	if (err == -ENOMSG || err == -ENODATA) {  		if (!ipv6_addr_is_ll_all_nodes(&ipv6_hdr(skb)->daddr))  			BR_INPUT_SKB_CB(skb)->mrouters_only = 1; - -		if (ipv6_addr_is_all_snoopers(&ipv6_hdr(skb)->daddr)) { -			err = br_ip6_multicast_mrd_rcv(br, port, skb); - -			if (err < 0 && err != -ENOMSG) { -				br_multicast_err_count(br, port, skb->protocol); -				return err; -			} -		} +		if (err == -ENODATA && +		    ipv6_addr_is_all_snoopers(&ipv6_hdr(skb)->daddr)) +			br_ip6_multicast_mrd_rcv(br, port, skb);  		return 0;  	} else if (err < 0) { @@ -3560,16 +3550,23 @@ static void br_multicast_start_querier(struct net_bridge *br,  	rcu_read_unlock();  } -int br_multicast_toggle(struct net_bridge *br, unsigned long val) +int br_multicast_toggle(struct net_bridge *br, unsigned long val, +			struct netlink_ext_ack *extack)  {  	struct net_bridge_port *port;  	bool change_snoopers = false; +	int err = 0;  	spin_lock_bh(&br->multicast_lock);  	if (!!br_opt_get(br, BROPT_MULTICAST_ENABLED) == !!val)  		goto unlock; -	br_mc_disabled_update(br->dev, val); +	err = br_mc_disabled_update(br->dev, val, extack); +	if (err == -EOPNOTSUPP) +		err = 0; +	if (err) +		goto unlock; +  	br_opt_toggle(br, BROPT_MULTICAST_ENABLED, !!val);  	if (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) {  		change_snoopers = true; @@ -3607,7 +3604,7 @@ unlock:  			br_multicast_leave_snoopers(br);  	} -	return 0; +	return err;  }  bool br_multicast_enabled(const struct net_device *dev)  |