diff mbox

[v3,net,5/5] vxlan: fix race between flush and incoming learning

Message ID 20130610173719.438d0c03@nehalam.linuxnetplumber.net
State Rejected, archived
Delegated to: David Miller
Headers show

Commit Message

Stephen Hemminger June 11, 2013, 12:37 a.m. UTC
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

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>

---
v3 - no changes

Should go to -net. Too much of a "theoritical race" for stable.



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

--- a/drivers/net/vxlan.c	2013-06-10 15:10:43.271357218 -0700
+++ b/drivers/net/vxlan.c	2013-06-10 15:23:19.541044803 -0700
@@ -611,7 +611,6 @@  static bool vxlan_snoop(struct net_devic
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct vxlan_fdb *f;
-	int err;
 
 	f = vxlan_find_mac(vxlan, src_mac);
 	if (likely(f)) {
@@ -632,12 +631,15 @@  static bool vxlan_snoop(struct net_devic
 	} else {
 		/* learned new entry */
 		spin_lock(&vxlan->hash_lock);
-		err = vxlan_fdb_create(vxlan, src_mac, src_ip,
-				       NUD_REACHABLE,
-				       NLM_F_EXCL|NLM_F_CREATE,
-				       vxlan->dst_port,
-				       vxlan->default_dst.remote_vni,
-				       0, NTF_SELF);
+
+		/* close off race between vxlan_flush and incoming packets */
+		if (netif_running(dev))
+			vxlan_fdb_create(vxlan, src_mac, src_ip,
+					 NUD_REACHABLE,
+					 NLM_F_EXCL|NLM_F_CREATE,
+					 vxlan->dst_port,
+					 vxlan->default_dst.remote_vni,
+					 0, NTF_SELF);
 		spin_unlock(&vxlan->hash_lock);
 	}