Add a scan result cache to improve roaming speed if the driver gave us a background scan before losing the connection. --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -97,6 +97,12 @@ struct wpa_config { int ap_scan; /** + * scan_cache - controls the time in seconds after the last scan results + * before a new scan may be initiated + */ + int scan_cache; + + /** * ctrl_interface - Parameters for the control interface * * If this is specified, %wpa_supplicant will open a control interface --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -306,6 +306,13 @@ static int wpa_config_parse_int(const st return 0; } +static int wpa_config_process_scan_cache(struct wpa_config *config, char *pos) +{ + config->scan_cache = atoi(pos); + wpa_printf(MSG_DEBUG, "scan_cache=%d", config->scan_cache); + return 0; +} + static int wpa_config_parse_str(const struct global_parse_data *data, struct wpa_config *config, int line, @@ -433,6 +440,7 @@ static const struct global_parse_data gl #endif /* CONFIG_CTRL_IFACE */ { INT_RANGE(eapol_version, 1, 2) }, { INT(ap_scan) }, + { INT(scan_cache) }, { INT(fast_reauth) }, #ifdef EAP_TLS_OPENSSL { STR(opensc_engine_path) }, @@ -834,6 +842,8 @@ static void wpa_config_write_global(FILE fprintf(f, "eapol_version=%d\n", config->eapol_version); if (config->ap_scan != DEFAULT_AP_SCAN) fprintf(f, "ap_scan=%d\n", config->ap_scan); + if (config->scan_cache != 0) + fprintf(f, "scan_cache=%d\n", config->scan_cache); if (config->fast_reauth != DEFAULT_FAST_REAUTH) fprintf(f, "fast_reauth=%d\n", config->fast_reauth); #ifdef EAP_TLS_OPENSSL --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -633,6 +633,9 @@ static void wpa_supplicant_event_scan_re wpa_s->disconnected) return; + if (wpa_s->wpa_state > WPA_ASSOCIATED) + goto done; + while (selected == NULL) { for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { selected = wpa_supplicant_select_bss( @@ -645,6 +648,7 @@ static void wpa_supplicant_event_scan_re wpa_printf(MSG_DEBUG, "No APs found - clear blacklist " "and try again"); wpa_blacklist_clear(wpa_s); + memset(&wpa_s->last_scan_results, 0, sizeof(wpa_s->last_scan_results)); } else if (selected == NULL) { break; } @@ -679,10 +683,12 @@ static void wpa_supplicant_event_scan_re rsn_preauth_scan_results(wpa_s->wpa, wpa_s->scan_res); } else { wpa_printf(MSG_DEBUG, "No suitable AP found."); - timeout = 5; + timeout = 0; goto req_scan; } +done: + os_get_time(&wpa_s->last_scan_results); return; req_scan: @@ -886,6 +892,9 @@ static void wpa_supplicant_event_disasso } if (wpa_s->wpa_state >= WPA_ASSOCIATED) wpa_supplicant_req_scan(wpa_s, 0, 100000); + else if (wpa_s->wpa_state == WPA_ASSOCIATING) + wpa_supplicant_req_auth_timeout(wpa_s, 0, 100000); + bssid = wpa_s->bssid; if (is_zero_ether_addr(bssid)) bssid = wpa_s->pending_bssid; --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -349,6 +349,7 @@ struct wpa_supplicant { struct wpa_client_mlme mlme; int use_client_mlme; int driver_4way_handshake; + struct os_time last_scan_results; int pending_mic_error_report; int pending_mic_error_pairwise; @@ -402,6 +403,7 @@ int wpa_supplicant_scard_init(struct wpa /* scan.c */ void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec); +int wpa_supplicant_may_scan(struct wpa_supplicant *wpa_s); void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s); /* events.c */ --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -40,6 +40,18 @@ static void wpa_supplicant_gen_assoc_eve wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data); } +int wpa_supplicant_may_scan(struct wpa_supplicant *wpa_s) +{ + struct os_time time; + + if (wpa_s->conf->scan_cache > 0) { + os_get_time(&time); + time.sec -= wpa_s->conf->scan_cache; + if (os_time_before(&time, &wpa_s->last_scan_results)) + return 0; + } + return 1; +} #ifdef CONFIG_WPS static int wpas_wps_in_use(struct wpa_config *conf, @@ -183,8 +195,9 @@ static void wpa_supplicant_scan(void *el wps = wpas_wps_in_use(wpa_s->conf, &req_type); #endif /* CONFIG_WPS */ - if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 && - !wpa_s->use_client_mlme && wps != 2) { + if (!wpa_supplicant_may_scan(wpa_s) || + (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 && + !wpa_s->use_client_mlme && wps != 2)) { wpa_s->scan_res_tried++; wpa_s->scan_req = scan_req; wpa_printf(MSG_DEBUG, "Trying to get current scan results " --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1491,6 +1491,9 @@ void wpa_supplicant_rx_eapol(void *ctx, { struct wpa_supplicant *wpa_s = ctx; + if (wpa_s->wpa_state < WPA_ASSOCIATING) + return; + wpa_printf(MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr)); wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);