diff mbox

[net-next,02/12] vxlan: fix race between flush and incoming learning

Message ID 20130610132456.2333c18b@nehalam.linuxnetplumber.net
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Stephen Hemminger June 10, 2013, 8:24 p.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>



--
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

Comments

Cong Wang June 11, 2013, 12:46 a.m. UTC | #1
On Mon, 10 Jun 2013 at 20:24 GMT, Stephen Hemminger <stephen@networkplumber.org> wrote:
> 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>
>

This doesn't apply with git am.

% git am /tmp/vxlan-fix-02.diff
Applying: vxlan: fix race between flush and incoming learning
error: patch failed: drivers/net/vxlan.c:632
error: drivers/net/vxlan.c: patch does not apply
Patch failed at 0001 vxlan: fix race between flush and incoming learning
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".

But can be applied manually... just fyi.

--
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
Cong Wang June 11, 2013, 2 a.m. UTC | #2
On Mon, 10 Jun 2013 at 20:24 GMT, Stephen Hemminger <stephen@networkplumber.org> wrote:
> 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>

Acked-by: Cong Wang <xiyou.wangcong@gmail.com>

--
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 12:19:51.290185627 -0700
+++ b/drivers/net/vxlan.c	2013-06-10 12:19:57.722112490 -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);
 	}