SME: Improve processing of association rejection
authorJouni Malinen <j@w1.fi>
Sat, 31 Oct 2009 21:21:43 +0000 (23:21 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 31 Oct 2009 21:21:43 +0000 (23:21 +0200)
Force deauthentication from the AP to clear mac80211 state (it would get
stuck with future scans if the AP is left in authenticated, but not
associated, state).

Add blacklist entry for the AP to allow other APs with worse signal
strength to be tried (e.g., when APs are trying to do load balancing
with status code 17). Reduce wait for the next scan to speed up
connection in cases where there could be other APs that could accept
association, but which show worse signal strength.

wpa_supplicant/sme.c

index 60d0fa9..e148595 100644 (file)
@@ -26,6 +26,7 @@
 #include "wpas_glue.h"
 #include "wps_supplicant.h"
 #include "notify.h"
+#include "blacklist.h"
 #include "sme.h"
 
 void sme_authenticate(struct wpa_supplicant *wpa_s,
@@ -357,12 +358,39 @@ void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
                            union wpa_event_data *data)
 {
        int bssid_changed;
+       int timeout = 5000;
 
-       wpa_printf(MSG_DEBUG, "SME: Association failed: status code %d",
+       wpa_printf(MSG_DEBUG, "SME: Association with " MACSTR " failed: "
+                  "status code %d", MAC2STR(wpa_s->pending_bssid),
                   data->assoc_reject.status_code);
 
-       wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
        bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
+
+       /*
+        * For now, unconditionally terminate the previous authentication. In
+        * theory, this should not be needed, but mac80211 gets quite confused
+        * if the authentication is left pending.. Some roaming cases might
+        * benefit from using the previous authentication, so this could be
+        * optimized in the future.
+        */
+       if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
+                                  WLAN_REASON_DEAUTH_LEAVING) < 0) {
+               wpa_msg(wpa_s, MSG_INFO,
+                       "Deauth request to the driver failed");
+       }
+
+       if (wpa_blacklist_add(wpa_s, wpa_s->pending_bssid) == 0) {
+               struct wpa_blacklist *b;
+               b = wpa_blacklist_get(wpa_s, wpa_s->pending_bssid);
+               if (b && b->count < 3) {
+                       /*
+                        * Speed up next attempt if there could be other APs
+                        * that could accept association.
+                        */
+                       timeout = 100;
+               }
+       }
+       wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
        os_memset(wpa_s->bssid, 0, ETH_ALEN);
        os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
        if (bssid_changed)
@@ -372,7 +400,8 @@ void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
         * TODO: if more than one possible AP is available in scan results,
         * could try the other ones before requesting a new scan.
         */
-       wpa_supplicant_req_scan(wpa_s, 5, 0);
+       wpa_supplicant_req_scan(wpa_s, timeout / 1000,
+                               1000 * (timeout % 1000));
 }