wpa_supplicant: Initial connection speedup

Add initial_freq_list to wpa_supplicant configuration. This option
allows wpa_supplicant to scan a smaller list of frequencies when it
starts. This in turn allows for a faster connection to an already known
network. This limit applies only for the initial scan operation and does
not restrict other channels from being used in consecutive scans.

Tests have shown this to reduce the amount of time for connecting to a
network from roughly 3 seconds to roughly 0.1 second.

Signed-off-by: Frederik Juul <frederik.juul@3shape.com>
This commit is contained in:
Frederik Juul 2020-07-23 08:39:41 +00:00 committed by Jouni Malinen
parent 67d5328b3c
commit f2a0101401
4 changed files with 50 additions and 1 deletions

View File

@ -2890,6 +2890,7 @@ void wpa_config_free(struct wpa_config *config)
os_free(config->p2p_no_go_freq.range); os_free(config->p2p_no_go_freq.range);
os_free(config->autoscan); os_free(config->autoscan);
os_free(config->freq_list); os_free(config->freq_list);
os_free(config->initial_freq_list);
wpabuf_free(config->wps_nfc_dh_pubkey); wpabuf_free(config->wps_nfc_dh_pubkey);
wpabuf_free(config->wps_nfc_dh_privkey); wpabuf_free(config->wps_nfc_dh_privkey);
wpabuf_free(config->wps_nfc_dev_pw); wpabuf_free(config->wps_nfc_dev_pw);
@ -4547,6 +4548,26 @@ static int wpa_config_process_freq_list(const struct global_parse_data *data,
} }
static int
wpa_config_process_initial_freq_list(const struct global_parse_data *data,
struct wpa_config *config, int line,
const char *value)
{
int *freqs;
freqs = wpa_config_parse_int_array(value);
if (!freqs)
return -1;
if (freqs[0] == 0) {
os_free(freqs);
freqs = NULL;
}
os_free(config->initial_freq_list);
config->initial_freq_list = freqs;
return 0;
}
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
static int wpa_global_config_parse_ipv4(const struct global_parse_data *data, static int wpa_global_config_parse_ipv4(const struct global_parse_data *data,
struct wpa_config *config, int line, struct wpa_config *config, int line,
@ -5082,6 +5103,7 @@ static const struct global_parse_data global_fields[] = {
{ FUNC(ap_vendor_elements), 0 }, { FUNC(ap_vendor_elements), 0 },
{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 }, { INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
{ FUNC(freq_list), 0 }, { FUNC(freq_list), 0 },
{ FUNC(initial_freq_list), 0},
{ INT(scan_cur_freq), 0 }, { INT(scan_cur_freq), 0 },
{ INT(sched_scan_interval), 0 }, { INT(sched_scan_interval), 0 },
{ INT(sched_scan_start_delay), 0 }, { INT(sched_scan_start_delay), 0 },

View File

@ -916,6 +916,19 @@ struct wpa_config {
*/ */
int *freq_list; int *freq_list;
/**
* initial_freq_list - like freq_list but for initial scan
*
* This is an optional zero-terminated array of frequencies in
* megahertz (MHz) to allow for narrowing scanning range when
* the application is started.
*
* This can be used to speed up initial connection time if the
* channel is known ahead of time, without limiting the scanned
* frequencies during normal use.
*/
int *initial_freq_list;
/** /**
* scan_cur_freq - Whether to scan only the current channel * scan_cur_freq - Whether to scan only the current channel
* *

View File

@ -1475,6 +1475,15 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
} }
fprintf(f, "\n"); fprintf(f, "\n");
} }
if (config->initial_freq_list && config->initial_freq_list[0]) {
int i;
fprintf(f, "initial_freq_list=");
for (i = 0; config->initial_freq_list[i]; i++) {
fprintf(f, "%s%d", i > 0 ? " " : "",
config->initial_freq_list[i]);
}
fprintf(f, "\n");
}
if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ) if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ)
fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq); fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq);

View File

@ -1201,7 +1201,12 @@ ssid_list_set:
wpa_setband_scan_freqs(wpa_s, &params); wpa_setband_scan_freqs(wpa_s, &params);
/* See if user specified frequencies. If so, scan only those. */ /* See if user specified frequencies. If so, scan only those. */
if (wpa_s->conf->freq_list && !params.freqs) { if (wpa_s->last_scan_req == INITIAL_SCAN_REQ &&
wpa_s->conf->initial_freq_list && !params.freqs) {
wpa_dbg(wpa_s, MSG_DEBUG,
"Optimize scan based on conf->initial_freq_list");
int_array_concat(&params.freqs, wpa_s->conf->initial_freq_list);
} else if (wpa_s->conf->freq_list && !params.freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, wpa_dbg(wpa_s, MSG_DEBUG,
"Optimize scan based on conf->freq_list"); "Optimize scan based on conf->freq_list");
int_array_concat(&params.freqs, wpa_s->conf->freq_list); int_array_concat(&params.freqs, wpa_s->conf->freq_list);