From f2a01014019a07868618c7c8489164b3019c0203 Mon Sep 17 00:00:00 2001 From: Frederik Juul Date: Thu, 23 Jul 2020 08:39:41 +0000 Subject: [PATCH] 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 --- wpa_supplicant/config.c | 22 ++++++++++++++++++++++ wpa_supplicant/config.h | 13 +++++++++++++ wpa_supplicant/config_file.c | 9 +++++++++ wpa_supplicant/scan.c | 7 ++++++- 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index c5161544d..0aa92a28c 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2890,6 +2890,7 @@ void wpa_config_free(struct wpa_config *config) os_free(config->p2p_no_go_freq.range); os_free(config->autoscan); os_free(config->freq_list); + os_free(config->initial_freq_list); wpabuf_free(config->wps_nfc_dh_pubkey); wpabuf_free(config->wps_nfc_dh_privkey); 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 static int wpa_global_config_parse_ipv4(const struct global_parse_data *data, struct wpa_config *config, int line, @@ -5082,6 +5103,7 @@ static const struct global_parse_data global_fields[] = { { FUNC(ap_vendor_elements), 0 }, { INT_RANGE(ignore_old_scan_res, 0, 1), 0 }, { FUNC(freq_list), 0 }, + { FUNC(initial_freq_list), 0}, { INT(scan_cur_freq), 0 }, { INT(sched_scan_interval), 0 }, { INT(sched_scan_start_delay), 0 }, diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 648573de0..d128cd9bf 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -916,6 +916,19 @@ struct wpa_config { */ 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 * diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 246644a33..cb04a78a2 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1475,6 +1475,15 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) } 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) fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq); diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 78371d3ad..9ac658151 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1201,7 +1201,12 @@ ssid_list_set: wpa_setband_scan_freqs(wpa_s, ¶ms); /* 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(¶ms.freqs, wpa_s->conf->initial_freq_list); + } else if (wpa_s->conf->freq_list && !params.freqs) { wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on conf->freq_list"); int_array_concat(¶ms.freqs, wpa_s->conf->freq_list);