]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SME: Optimize recovery from common load balancing mechanisms
authorJouni Malinen <jouni.malinen@atheros.com>
Thu, 25 Nov 2010 20:51:56 +0000 (22:51 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 25 Nov 2010 20:51:56 +0000 (22:51 +0200)
When authentication or association fails when trying to connect to
a BSS in an ESS that has multiple BSSes based on previous scans,
limit the first recovery scan to only the known channels that has
been seen previously. This speeds up recovery in some of the most
commonly used load balancing mechanisms in enterprise WLAN
networks.

wpa_supplicant/scan.c
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 2769c2f84631c14a373983b95495f24abfd7d304..68c8ce0530932114854801cf4c7c5d2b2a9e4c39 100644 (file)
@@ -448,6 +448,14 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
        }
 #endif /* CONFIG_P2P */
 
+       if (params.freqs == NULL && wpa_s->next_scan_freqs) {
+               wpa_printf(MSG_DEBUG, "Optimize scan based on previously "
+                          "generated frequency list");
+               params.freqs = wpa_s->next_scan_freqs;
+       } else
+               os_free(wpa_s->next_scan_freqs);
+       wpa_s->next_scan_freqs = NULL;
+
        params.filter_ssids = wpa_supplicant_build_filter_ssids(
                wpa_s->conf, &params.num_filter_ssids);
 
index 55788de010ce36db510f96f0bc3cf65c104b6c81..604b0a5a747189c233e892e8e5e3caa3f70bf16b 100644 (file)
 #include "scan.h"
 #include "sme.h"
 
-static int sme_another_bss_in_ess(struct wpa_supplicant *wpa_s)
+static void add_freq(int *freqs, int *num_freqs, int freq)
+{
+       int i;
+
+       for (i = 0; i < *num_freqs; i++) {
+               if (freqs[i] == freq)
+                       return;
+       }
+
+       freqs[*num_freqs] = freq;
+       (*num_freqs)++;
+}
+
+
+static int * sme_another_bss_in_ess(struct wpa_supplicant *wpa_s)
 {
        struct wpa_bss *bss, *cbss;
+       const int max_freqs = 10;
+       int *freqs;
+       int num_freqs = 0;
+
+       freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
+       if (freqs == NULL)
+               return NULL;
 
        cbss = wpa_s->current_bss;
 
@@ -44,11 +65,19 @@ static int sme_another_bss_in_ess(struct wpa_supplicant *wpa_s)
                        continue;
                if (bss->ssid_len == cbss->ssid_len &&
                    os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
-                   wpa_blacklist_get(wpa_s, bss->bssid) == NULL)
-                       return 1;
+                   wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
+                       add_freq(freqs, &num_freqs, bss->freq);
+                       if (num_freqs == max_freqs)
+                               break;
+               }
        }
 
-       return 0;
+       if (num_freqs == 0) {
+               os_free(freqs);
+               freqs = NULL;
+       }
+
+       return freqs;
 }
 
 
@@ -57,6 +86,7 @@ static void sme_connection_failed(struct wpa_supplicant *wpa_s,
 {
        int timeout;
        int count;
+       int *freqs = NULL;
 
        /*
         * Add the failed BSSID into the blacklist and speed up next scan
@@ -74,10 +104,18 @@ static void sme_connection_failed(struct wpa_supplicant *wpa_s,
                 * next. Otherwise, we may as well try this one once more
                 * before allowing other, likely worse, ESSes to be considered.
                 */
-               if (sme_another_bss_in_ess(wpa_s)) {
+               freqs = sme_another_bss_in_ess(wpa_s);
+               if (freqs) {
                        wpa_printf(MSG_DEBUG, "SME: Another BSS in this ESS "
                                   "has been seen; try it next");
                        wpa_blacklist_add(wpa_s, bssid);
+                       /*
+                        * On the next scan, go through only the known channels
+                        * used in this ESS based on previous scans to speed up
+                        * common load balancing use case.
+                        */
+                       os_free(wpa_s->next_scan_freqs);
+                       wpa_s->next_scan_freqs = freqs;
                }
        }
 
index 0a603af06a82b29a59d7286ac17bab5a77a981e6..e9909118683d7c4d0586e911664c6602229272ef 100644 (file)
@@ -433,6 +433,9 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
 #ifdef CONFIG_P2P
        wpas_p2p_deinit(wpa_s);
 #endif /* CONFIG_P2P */
+
+       os_free(wpa_s->next_scan_freqs);
+       wpa_s->next_scan_freqs = NULL;
 }
 
 
index 853968ce7574e60943ae267392138fc9218e706c..4c6fa4ff371507233c048d1e67f6c8a0bf7252af 100644 (file)
@@ -404,6 +404,7 @@ struct wpa_supplicant {
        int scan_req; /* manual scan request; this forces a scan even if there
                       * are no enabled networks in the configuration */
        int scan_runs; /* number of scan runs since WPS was started */
+       int *next_scan_freqs;
 
        struct wpa_client_mlme mlme;
        unsigned int drv_flags;