diff options
Diffstat (limited to 'net/8021q/vlan_core.c')
| -rw-r--r-- | net/8021q/vlan_core.c | 25 | 
1 files changed, 14 insertions, 11 deletions
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 65e06abe023f..f3b6f515eba6 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -60,21 +60,25 @@ bool vlan_do_receive(struct sk_buff **skbp)  	return true;  } -/* Must be invoked with rcu_read_lock or with RTNL. */ -struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, +/* Must be invoked with rcu_read_lock. */ +struct net_device *__vlan_find_dev_deep(struct net_device *dev,  					u16 vlan_id)  { -	struct vlan_info *vlan_info = rcu_dereference_rtnl(real_dev->vlan_info); +	struct vlan_info *vlan_info = rcu_dereference(dev->vlan_info);  	if (vlan_info) {  		return vlan_group_get_device(&vlan_info->grp, vlan_id);  	} else {  		/* -		 * Bonding slaves do not have grp assigned to themselves. -		 * Grp is assigned to bonding master instead. +		 * Lower devices of master uppers (bonding, team) do not have +		 * grp assigned to themselves. Grp is assigned to upper device +		 * instead.  		 */ -		if (netif_is_bond_slave(real_dev)) -			return __vlan_find_dev_deep(real_dev->master, vlan_id); +		struct net_device *upper_dev; + +		upper_dev = netdev_master_upper_dev_get_rcu(dev); +		if (upper_dev) +			return __vlan_find_dev_deep(upper_dev, vlan_id);  	}  	return NULL; @@ -140,6 +144,7 @@ err_free:  	kfree_skb(skb);  	return NULL;  } +EXPORT_SYMBOL(vlan_untag);  /* @@ -220,8 +225,7 @@ static int __vlan_vid_add(struct vlan_info *vlan_info, unsigned short vid,  	if (!vid_info)  		return -ENOMEM; -	if ((dev->features & NETIF_F_HW_VLAN_FILTER) && -	    ops->ndo_vlan_rx_add_vid) { +	if (dev->features & NETIF_F_HW_VLAN_FILTER) {  		err =  ops->ndo_vlan_rx_add_vid(dev, vid);  		if (err) {  			kfree(vid_info); @@ -278,8 +282,7 @@ static void __vlan_vid_del(struct vlan_info *vlan_info,  	unsigned short vid = vid_info->vid;  	int err; -	if ((dev->features & NETIF_F_HW_VLAN_FILTER) && -	     ops->ndo_vlan_rx_kill_vid) { +	if (dev->features & NETIF_F_HW_VLAN_FILTER) {  		err = ops->ndo_vlan_rx_kill_vid(dev, vid);  		if (err) {  			pr_warn("failed to kill vid %d for device %s\n",  |