vxlan: leave multicast group when vxlan device down
vxlan_group_used only allows device to leave multicast group when the remote_ip of this vxlan device is difference from other vxlan devices' remote_ip. this will cause device not leave multicast group untile the vn_sock of this vxlan deivce being released. The check in vxlan_group_used is not quite precise. since even the remote_ip is same, but these vxlan devices may use different lower devices, and they may use different vn_socks. Only when some vxlan devices use the same vn_sock,same lower device and same remote_ip, the mc_list of the vn_sock should not be changed. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
79d4a94fab
commit
95ab09917a
|
@ -916,17 +916,32 @@ static bool vxlan_snoop(struct net_device *dev,
|
|||
}
|
||||
|
||||
/* See if multicast group is already in use by other ID */
|
||||
static bool vxlan_group_used(struct vxlan_net *vn, union vxlan_addr *remote_ip)
|
||||
static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
|
||||
{
|
||||
struct vxlan_dev *vxlan;
|
||||
|
||||
/* The vxlan_sock is only used by dev, leaving group has
|
||||
* no effect on other vxlan devices.
|
||||
*/
|
||||
if (atomic_read(&dev->vn_sock->refcnt) == 1)
|
||||
return false;
|
||||
|
||||
list_for_each_entry(vxlan, &vn->vxlan_list, next) {
|
||||
if (!netif_running(vxlan->dev))
|
||||
if (!netif_running(vxlan->dev) || vxlan == dev)
|
||||
continue;
|
||||
|
||||
if (vxlan_addr_equal(&vxlan->default_dst.remote_ip,
|
||||
remote_ip))
|
||||
return true;
|
||||
if (vxlan->vn_sock != dev->vn_sock)
|
||||
continue;
|
||||
|
||||
if (!vxlan_addr_equal(&vxlan->default_dst.remote_ip,
|
||||
&dev->default_dst.remote_ip))
|
||||
continue;
|
||||
|
||||
if (vxlan->default_dst.remote_ifindex !=
|
||||
dev->default_dst.remote_ifindex)
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1981,7 +1996,7 @@ static int vxlan_stop(struct net_device *dev)
|
|||
struct vxlan_sock *vs = vxlan->vn_sock;
|
||||
|
||||
if (vs && vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
|
||||
! vxlan_group_used(vn, &vxlan->default_dst.remote_ip)) {
|
||||
!vxlan_group_used(vn, vxlan)) {
|
||||
vxlan_sock_hold(vs);
|
||||
dev_hold(dev);
|
||||
queue_work(vxlan_wq, &vxlan->igmp_leave);
|
||||
|
|
Loading…
Reference in New Issue