diff options
author | stephen hemminger <stephen@networkplumber.org> | 2013-06-17 15:09:57 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-17 18:55:46 -0400 |
commit | 3bf74b1aecdce719f1445200d5db7dfee2297bba (patch) | |
tree | 3c219f5bbe142d0e5c096caf9169b546d7d669e1 /drivers/net | |
parent | 8177a9d79c0e942dcac3312f15585d0344d505a5 (diff) |
vxlan: fix race between flush and incoming learning
It is possible for a packet to arrive during vxlan_stop(), and
have a dynamic entry created. Close this by checking if device
is up.
CPU1 CPU2
vxlan_stop
vxlan_flush
hash_lock acquired
vxlan_encap_recv
vxlan_snoop
waiting for hash_lock
hash_lock relased
vxlan_flush done
hash_lock acquired
vxlan_fdb_create
This is a day-one bug in vxlan goes back to 3.7.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/vxlan.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 3b1d2ee7156b..577a069a6dde 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -571,7 +571,6 @@ static void vxlan_snoop(struct net_device *dev, | |||
571 | { | 571 | { |
572 | struct vxlan_dev *vxlan = netdev_priv(dev); | 572 | struct vxlan_dev *vxlan = netdev_priv(dev); |
573 | struct vxlan_fdb *f; | 573 | struct vxlan_fdb *f; |
574 | int err; | ||
575 | 574 | ||
576 | f = vxlan_find_mac(vxlan, src_mac); | 575 | f = vxlan_find_mac(vxlan, src_mac); |
577 | if (likely(f)) { | 576 | if (likely(f)) { |
@@ -588,12 +587,15 @@ static void vxlan_snoop(struct net_device *dev, | |||
588 | } else { | 587 | } else { |
589 | /* learned new entry */ | 588 | /* learned new entry */ |
590 | spin_lock(&vxlan->hash_lock); | 589 | spin_lock(&vxlan->hash_lock); |
591 | err = vxlan_fdb_create(vxlan, src_mac, src_ip, | 590 | |
592 | NUD_REACHABLE, | 591 | /* close off race between vxlan_flush and incoming packets */ |
593 | NLM_F_EXCL|NLM_F_CREATE, | 592 | if (netif_running(dev)) |
594 | vxlan->dst_port, | 593 | vxlan_fdb_create(vxlan, src_mac, src_ip, |
595 | vxlan->default_dst.remote_vni, | 594 | NUD_REACHABLE, |
596 | 0, NTF_SELF); | 595 | NLM_F_EXCL|NLM_F_CREATE, |
596 | vxlan->dst_port, | ||
597 | vxlan->default_dst.remote_vni, | ||
598 | 0, NTF_SELF); | ||
597 | spin_unlock(&vxlan->hash_lock); | 599 | spin_unlock(&vxlan->hash_lock); |
598 | } | 600 | } |
599 | } | 601 | } |