]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Try to reconnect to the same BSS on recoverable disconnection
authorJouni Malinen <j@w1.fi>
Sun, 4 Dec 2011 19:57:14 +0000 (21:57 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 4 Dec 2011 19:57:14 +0000 (21:57 +0200)
If the AP disconnects us with a reason code that indicates that it has
dropped the association, but could allow us to connect again, try to
reconnect to the same BSS without going through the full scan. This can
save quite a bit of time in some common use cases, e.g., when inactivity
timeout is used on the AP (and especially, when waking up from suspend
which has likely triggered some timeout on the AP).

Signed-hostap: Jouni Malinen <j@w1.fi>

wpa_supplicant/events.c

index dd17a4280cc928d00fe1ea7196324843df63413e..9823501ba9829c10b75f5e3bbdddae81e657a361 100644 (file)
@@ -1533,12 +1533,22 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
 }
 
 
+static int disconnect_reason_recoverable(u16 reason_code)
+{
+       return reason_code == WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY ||
+               reason_code == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA ||
+               reason_code == WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
+}
+
+
 static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s,
                                          u16 reason_code)
 {
        const u8 *bssid;
        int authenticating;
        u8 prev_pending_bssid[ETH_ALEN];
+       struct wpa_bss *fast_reconnect = NULL;
+       struct wpa_ssid *fast_reconnect_ssid = NULL;
 
        authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING;
        os_memcpy(prev_pending_bssid, wpa_s->pending_bssid, ETH_ALEN);
@@ -1561,17 +1571,29 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s,
        }
        if (!wpa_s->auto_reconnect_disabled ||
            wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
-               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Auto connect enabled: try to "
+               wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect enabled: try to "
                        "reconnect (wps=%d wpa_state=%d)",
                        wpa_s->key_mgmt == WPA_KEY_MGMT_WPS,
                        wpa_s->wpa_state);
-               if (wpa_s->wpa_state >= WPA_ASSOCIATING)
+               if (wpa_s->wpa_state == WPA_COMPLETED &&
+                   wpa_s->current_ssid &&
+                   wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
+                   disconnect_reason_recoverable(reason_code)) {
+                       /*
+                        * It looks like the AP has dropped association with
+                        * us, but could allow us to get back in. Try to
+                        * reconnect to the same BSS without full scan to save
+                        * time for some common cases.
+                        */
+                       fast_reconnect = wpa_s->current_bss;
+                       fast_reconnect_ssid = wpa_s->current_ssid;
+               } else if (wpa_s->wpa_state >= WPA_ASSOCIATING)
                        wpa_supplicant_req_scan(wpa_s, 0, 100000);
                else
                        wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new "
                                "immediate scan");
        } else {
-               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Auto connect disabled: do not "
+               wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not "
                        "try to re-connect");
                wpa_s->reassociate = 0;
                wpa_s->disconnected = 1;
@@ -1594,6 +1616,15 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s,
 
        if (authenticating && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
                sme_disassoc_while_authenticating(wpa_s, prev_pending_bssid);
+
+       if (fast_reconnect) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS");
+               if (wpa_supplicant_connect(wpa_s, fast_reconnect,
+                                          fast_reconnect_ssid) < 0) {
+                       /* Recover through full scan */
+                       wpa_supplicant_req_scan(wpa_s, 0, 100000);
+               }
+       }
 }