From patchwork Sat Jun 9 11:47:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Speed up connection time during ASSOC retry Date: Sat, 09 Jun 2012 01:47:51 -0000 From: Jouni Malinen X-Patchwork-Id: 163909 Message-Id: <20120609114751.GB9290@w1.fi> To: hostap@lists.shmoo.com On Mon, May 21, 2012 at 06:24:31AM +0000, Jithu Jance wrote: > In current implementation, authentication timer continues to run even after the > driver has reported ASSOC_REJECT. Then the association is retried on authentication > timeout which is 10secs. This is actually not the case for SME-in-wpa_supplicant, i.e., this patch did not change anything for my mac80211_hwsim test.. As such, this change should probably be conditional on WPA_DRIVER_FLAGS_SME not being set.. > The below patch cancels the authentication timeout on ASSOC_REJECT and initiates an > scan for association. Kindly see whether the patch is fine. The patch was whitespace damaged (tabs converted to spaces). > diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c > @@ -2238,6 +2238,25 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, > if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) > sme_event_assoc_reject(wpa_s, data); > + > + /* If assoc reject is reported by the driver, then avoid sme_event_assoc_reject() handles this with similar mechanism to initiate new attempt immediately. > + * waiting for the authentication timeout. Cancel the > + * authentication timeout and retry the assoc. > + */ > + if(wpa_s->assoc_retries++ < 3) { This should probably not be run with WPA_DRIVER_FLAGS_SME.. > + wpa_printf(MSG_ERROR, "Retrying assoc " > + "Iteration:%d", wpa_s->assoc_retries); > + wpa_supplicant_cancel_auth_timeout(wpa_s); > + > + /* Clear the states */ > + wpa_sm_notify_disassoc(wpa_s->wpa); > + wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); wpa_supplicant_deauthenticate() would sound more appropriate in this case since association was rejected. > + wpa_s->reassociate = 1; > + wpa_supplicant_req_scan(wpa_s, 1, 0); This could use wpas_connection_failed() to remain consistent with other similar connection failure cases.. I have not tested this, but something like this could handle this a bit more cleanly. Could you please check whether this works in the case you are seeing? diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index d09be6c..0b4feb8 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2320,6 +2320,27 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->assoc_reject.status_code); if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) sme_event_assoc_reject(wpa_s, data); + else if (wpa_s->assoc_retries++ < 3) { + /* + * If association reject is reported by the driver, + * avoid waiting for the authentication timeout. Cancel + * the authentication timeout and retry the + * association. + */ + wpa_printf(MSG_DEBUG, "Retrying association " + "(iteration %d)", wpa_s->assoc_retries); + + /* Clear the state */ + wpa_sm_notify_disassoc(wpa_s->wpa); + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + + wpa_s->reassociate = 1; + wpas_connection_failed(wpa_s, + data->assoc_reject.bssid); + } else { + wpa_s->assoc_retries = 0; + } break; case EVENT_AUTH_TIMED_OUT: if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 3cb954d..fdfcc5d 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -587,6 +587,9 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_supplicant_state_txt(wpa_s->wpa_state), wpa_supplicant_state_txt(state)); + if (state == WPA_ASSOCIATED || state <= WPA_INACTIVE) + wpa_s->assoc_retries = 0; + if (state != WPA_SCANNING) wpa_supplicant_notify_scanning(wpa_s, 0); @@ -3199,8 +3202,11 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) * either not available or has already been tried, so that we can start * increasing the delay here to avoid constant scanning. */ - count = wpa_blacklist_add(wpa_s, bssid); - if (count == 1 && wpa_s->current_bss) { + if (bssid) + count = wpa_blacklist_add(wpa_s, bssid); + else + count = 3; + if (count == 1 && wpa_s->current_bss && bssid) { /* * This BSS was not in the blacklist before. If there is * another BSS available for the same ESS, we should try that diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 84e8fa4..50eef00 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -286,6 +286,7 @@ struct wpa_supplicant { struct wpa_bss *current_bss; int ap_ies_from_associnfo; unsigned int assoc_freq; + unsigned int assoc_retries; /* Selected configuration (based on Beacon/ProbeResp WPA IE) */ int pairwise_cipher;