Commit 95ab0991 authored by Gao feng's avatar Gao feng Committed by David S. Miller

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: default avatarGao feng <gaofeng@cn.fujitsu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 79d4a94f
...@@ -916,16 +916,31 @@ static bool vxlan_snoop(struct net_device *dev, ...@@ -916,16 +916,31 @@ static bool vxlan_snoop(struct net_device *dev,
} }
/* See if multicast group is already in use by other ID */ /* 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; 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) { list_for_each_entry(vxlan, &vn->vxlan_list, next) {
if (!netif_running(vxlan->dev)) if (!netif_running(vxlan->dev) || vxlan == dev)
continue;
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; continue;
if (vxlan_addr_equal(&vxlan->default_dst.remote_ip,
remote_ip))
return true; return true;
} }
...@@ -1981,7 +1996,7 @@ static int vxlan_stop(struct net_device *dev) ...@@ -1981,7 +1996,7 @@ static int vxlan_stop(struct net_device *dev)
struct vxlan_sock *vs = vxlan->vn_sock; struct vxlan_sock *vs = vxlan->vn_sock;
if (vs && vxlan_addr_multicast(&vxlan->default_dst.remote_ip) && 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); vxlan_sock_hold(vs);
dev_hold(dev); dev_hold(dev);
queue_work(vxlan_wq, &vxlan->igmp_leave); queue_work(vxlan_wq, &vxlan->igmp_leave);
......
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