diff mbox

P2P: Ignore the DEAUTH event from cfg80211 incase of locally generated disconnect

Message ID 1369748463.13596.19.camel@lbblr-jithu01.broadcom.com
State Superseded
Headers show

Commit Message

Jithu Jance May 28, 2013, 1:41 p.m. UTC
Hi Jouni,

With the fast association enabled supplicant, I see an additional
disassoc issue while doing a P2P/WPS connection. When EAP-FAILURE
happens, the DEAUTH event from cfg80211 is received after supplicant has
moved to ASSOCIATING state. 

The wpa_supplicant_deauthenticate function sends disconnect command down
to the cfg80211/driver, generates the DEAUTH event locally and then
starts the connect process. Since now the supplicant has fast
association enabled, it moves to ASSOCIATING state pretty fast. Hence
the DEAUTH event from cfg80211 stack (as a result of nl80211_disconnect)
is received mostly after the supplicant has moved to ASSOCIATING state.
This results in an ASSOCIATING -> DISCONNECTED state change
unnecessarily. 

Is it safe to ignore this DEAUTH event since the
wpa_supplicant_deathenticate function already generated a local DEAUTH
event? I have generated a patch adding an additional arg to
wpa_drv_deauthenticate ignore the deauth event. I haven't changed the
driver_* files other than driver_nl80211.c since I am not sure whether
changing the wpa_driver_ops interface is the right way. If the changes
are fine, I can generate a fresh patch including other driver_* files.

++++++++++++++++++++++++++++++++++++++++++++++ logs  ++++++
05-28 09:13:00.915 I/wpa_supplicant(12913): p2p-p2p0-0: Trying to
associate with 0a:d4:2b:11:db:48 (SSID='DIRECT-AA-Android_6a0b'
freq=2437 MHz)
05-28 09:13:01.120 I/wpa_supplicant(12913): p2p-p2p0-0: Associated with
0a:d4:2b:11:db:48
05-28 09:13:01.135 I/wpa_supplicant(12913): p2p-p2p0-0:
CTRL-EVENT-EAP-STARTED EAP authentication started
05-28 09:13:01.145 I/wpa_supplicant(12913): p2p-p2p0-0:
CTRL-EVENT-EAP-PROPOSED-METHOD vendor=14122 method=1
05-28 09:13:01.145 I/wpa_supplicant(12913): p2p-p2p0-0:
CTRL-EVENT-EAP-METHOD EAP vendor 14122 method 1 (WSC) selected
05-28 09:13:01.320 I/wpa_supplicant(12913): p2p-p2p0-0:
WPS-CRED-RECEIVED 
05-28 09:13:01.320 I/wpa_supplicant(12913): p2p-p2p0-0: WPS-SUCCESS 
05-28 09:13:01.320 I/wpa_supplicant(12913): p2p0:
P2P-GROUP-FORMATION-SUCCESS 
05-28 09:13:01.350 I/wpa_supplicant(12913): p2p-p2p0-0:
CTRL-EVENT-EAP-FAILURE EAP authentication failed
05-28 09:13:01.355 I/wpa_supplicant(12913): p2p-p2p0-0: 

CTRL-EVENT-DISCONNECTED bssid=0a:d4:2b:11:db:48 reason=3
locally_generated=1  <============ locally generated at
wpa_supplicant_deauthenticate


05-28 09:13:01.360 I/wpa_supplicant(12913): p2p-p2p0-0: Trying to
associate with 0a:d4:2b:11:db:48 (SSID='DIRECT-AA-Android_6a0b'
freq=2437 MHz)


05-28 09:13:01.365 I/wpa_supplicant(12913): p2p-p2p0-0:
CTRL-EVENT-DISCONNECTED bssid=0a:d4:2b:11:db:48 reason=0
locally_generated=1  <============================= Event from cfg80211
stack


05-28 09:13:01.510 I/wpa_supplicant(12913): p2p-p2p0-0: Associated with
0a:d4:2b:11:db:48
05-28 09:13:01.875 I/wpa_supplicant(12913): p2p-p2p0-0: WPA: Key
negotiation completed with 0a:d4:2b:11:db:48 [PTK=CCMP GTK=CCMP]
05-28 09:13:01.875 I/wpa_supplicant(12913): p2p-p2p0-0:
CTRL-EVENT-CONNECTED - Connection to 0a:d4:2b:11:db:48 completed (auth)
[id=0 id_str=]
05-28 09:13:01.880 I/wpa_supplicant(12913): p2p0: P2P-GROUP-STARTED
p2p-p2p0-0 client ssid="DIRECT-AA-Android_6a0b" freq=2437 
...
+++++++++++++++++++++++++++++++++++++++++++++++++++++++



From 214eea6b0eac7361c03b5397d13d9e6404b5a435 Mon Sep 17 00:00:00 2001
From: Jithu Jance <jithu@broadcom.com>
Date: Tue, 28 May 2013 18:37:23 +0530
Subject: [PATCH] Ignore the DEAUTH event from cfg80211 for cases where a
 local DEAUTH event is generated by supplicant.
 Signed-hostap: Jithu Jance <jithu@broadcom.com>

---
 src/drivers/driver.h            |    5 ++++-
 src/drivers/driver_nl80211.c    |   21 +++++++++++++--------
 wpa_supplicant/driver_i.h       |    2 +-
 wpa_supplicant/sme.c            |    4 ++--
 wpa_supplicant/wpa_supplicant.c |    2 +-
 5 files changed, 21 insertions(+), 13 deletions(-)

 		event.deauth_info.locally_generated = 1;

Comments

Jouni Malinen May 28, 2013, 9:33 p.m. UTC | #1
On Tue, May 28, 2013 at 07:11:03PM +0530, jithu Jance wrote:
> With the fast association enabled supplicant, I see an additional
> disassoc issue while doing a P2P/WPS connection. When EAP-FAILURE
> happens, the DEAUTH event from cfg80211 is received after supplicant has
> moved to ASSOCIATING state. 

It looks like this is handled with mac80211-based drivers (or well,
anything where wpa_supplicant SME is used) since
sme_disassoc_while_authenticating() allows the new connection attempt to
continue in such a case.

> The wpa_supplicant_deauthenticate function sends disconnect command down
> to the cfg80211/driver, generates the DEAUTH event locally and then
> starts the connect process. Since now the supplicant has fast
> association enabled, it moves to ASSOCIATING state pretty fast. Hence
> the DEAUTH event from cfg80211 stack (as a result of nl80211_disconnect)
> is received mostly after the supplicant has moved to ASSOCIATING state.
> This results in an ASSOCIATING -> DISCONNECTED state change
> unnecessarily. 
> 
> Is it safe to ignore this DEAUTH event since the
> wpa_supplicant_deathenticate function already generated a local DEAUTH
> event?

Yes and that is already done with some drivers.

> I have generated a patch adding an additional arg to
> wpa_drv_deauthenticate ignore the deauth event. I haven't changed the
> driver_* files other than driver_nl80211.c since I am not sure whether
> changing the wpa_driver_ops interface is the right way. If the changes
> are fine, I can generate a fresh patch including other driver_* files.

I would prefer to do this without changing the wpa_driver_ops API since
that type of changes are inconvenient for number of driver_*
implementations and different branches pulling in changes from
hostap.git.

If a wpa_driver_ops change is really needed, that should be a new
function that can either be used as a replacement for the old ones or
can be separately indicate to ignore the next disconnection event from
the current AP. Actually even better would be to just handle this
automatically within driver_nl80211.c. It should be clear there that
cfg80211 will send a disconnection event after disconnection request.
Such an event could be ignored if we have already started new connection
process. I did actually do something quite similar yesterday for FT:
http://w1.fi/gitweb/gitweb.cgi?p=hostap.git;a=commitdiff;h=add9b7a46a017d0fe3089247f98e5a67dbc250a5
diff mbox

Patch

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 0c1fd2f..3f5436f 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1269,11 +1269,14 @@  struct wpa_driver_ops {
 	 * @priv: private driver interface data
 	 * @addr: peer address (BSSID of the AP)
 	 * @reason_code: 16-bit reason code to be sent in the deauthentication
+	 * @ignore_disassoc_event: Ignore the disassoc event generated as a
+	 * result of the local deauth.
 	 *	frame
 	 *
 	 * Returns: 0 on success, -1 on failure
 	 */
-	int (*deauthenticate)(void *priv, const u8 *addr, int reason_code);
+	int (*deauthenticate)(void *priv, const u8 *addr,
+			int reason_code, int ignore_disassoc_event);
 
 	/**
 	 * associate - Request driver to associate
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index f403189..6b13289 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -4890,11 +4890,12 @@  nla_put_failure:
 
 
 static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data
*drv,
-					 int reason_code)
+					 int reason_code, int ignore_disassoc_event)
 {
 	wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
 	nl80211_mark_disconnected(drv);
-	drv->ignore_next_local_disconnect = 0;
+
+	drv->ignore_next_local_disconnect = ignore_disassoc_event;
 	/* Disconnect command doesn't need BSSID - it uses cached value */
 	return wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
 				       reason_code, 0);
@@ -4902,11 +4903,14 @@  static int wpa_driver_nl80211_disconnect(struct
wpa_driver_nl80211_data *drv,
 
 
 static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
-					     const u8 *addr, int reason_code)
+					     const u8 *addr, int reason_code,
+					     int ignore_disassoc_event)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))
-		return wpa_driver_nl80211_disconnect(drv, reason_code);
+		return wpa_driver_nl80211_disconnect(drv,
+				reason_code, ignore_disassoc_event);
+
 	wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
 		   __func__, MAC2STR(addr), reason_code);
 	nl80211_mark_disconnected(drv);
@@ -5079,7 +5083,7 @@  retry:
 				   "after forced deauthentication");
 			wpa_driver_nl80211_deauthenticate(
 				bss, params->bssid,
-				WLAN_REASON_PREV_AUTH_NOT_VALID);
+				WLAN_REASON_PREV_AUTH_NOT_VALID, 0);
 			nlmsg_free(msg);
 			goto retry;
 		}
@@ -7510,7 +7514,7 @@  static int wpa_driver_nl80211_connect(
 			   "disconnecting before reassociation "
 			   "attempt");
 		if (wpa_driver_nl80211_disconnect(
-			    drv, WLAN_REASON_PREV_AUTH_NOT_VALID))
+			    drv, WLAN_REASON_PREV_AUTH_NOT_VALID, 0))
 			return -1;
 		/* Ignore the next local disconnect message. */
 		drv->ignore_next_local_disconnect = 1;
@@ -9890,10 +9894,11 @@  static int driver_nl80211_scan2(void *priv,
 
 
 static int driver_nl80211_deauthenticate(void *priv, const u8 *addr,
-					 int reason_code)
+					 int reason_code, int ignore_disassoc_event)
 {
 	struct i802_bss *bss = priv;
-	return wpa_driver_nl80211_deauthenticate(bss, addr, reason_code);
+	return wpa_driver_nl80211_deauthenticate(bss, addr,
+			reason_code, ignore_disassoc_event);
 }
 
 
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 847600d..9c1e06d 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -130,7 +130,7 @@  static inline int wpa_drv_set_key(struct
wpa_supplicant *wpa_s,
 }
 
 static inline int wpa_drv_deauthenticate(struct wpa_supplicant *wpa_s,
-					 const u8 *addr, int reason_code)
+					 const u8 *addr, int reason_code, int ignore_disassoc_event)
 {
 	if (wpa_s->driver->deauthenticate) {
 		return wpa_s->driver->deauthenticate(wpa_s->drv_priv, addr,
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 0371628..20e2d51 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -751,7 +751,7 @@  static void sme_deauth(struct wpa_supplicant *wpa_s)
 	bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
 
 	if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
-				   WLAN_REASON_DEAUTH_LEAVING) < 0) {
+				   WLAN_REASON_DEAUTH_LEAVING, 0) < 0) {
 		wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
 			"failed");
 	}
@@ -818,7 +818,7 @@  void sme_event_disassoc(struct wpa_supplicant
*wpa_s,
 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
 			"driver state");
 		wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
-				       WLAN_REASON_DEAUTH_LEAVING);
+				       WLAN_REASON_DEAUTH_LEAVING, 0);
 	}
 }
 
diff --git a/wpa_supplicant/wpa_supplicant.c
b/wpa_supplicant/wpa_supplicant.c
index 248bf0e..6330b9f 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1749,7 +1749,7 @@  void wpa_supplicant_deauthenticate(struct
wpa_supplicant *wpa_s,
 #endif /* CONFIG_TDLS */
 
 	if (addr) {
-		wpa_drv_deauthenticate(wpa_s, addr, reason_code);
+		wpa_drv_deauthenticate(wpa_s, addr, reason_code, 1);
 		os_memset(&event, 0, sizeof(event));
 		event.deauth_info.reason_code = (u16) reason_code;