[PATCH] wpa_supplicant: Initial connection speedup

Frederik Juul Frederik.Juul at 3shape.com
Thu Jul 23 04:39:41 EDT 2020


Hi!

We've been using wpa_supplicant for managing wifi connections in
our headless devices and it's been working well.
However the device sees a lot of turning on and off by pulling
the battery and we need to reconnect as fast as possible when the
device is turned on.

>From battery being inserted and device being turned on to
connecting to wifi, it would roughly takes us 6 seconds. We found
that 3 of these seconds were spent scanning for networks.

Our solution to this was to set the freq_list to the last known
frequency we were connected to. 
Our devices are usually used in the same setting, so the
frequency is unlikely to change. In the event that it does
change, we had some scripts which kept track and handled that
scenario.
The gains, however, were great. We were able to bring initial
connection time down from 3 seconds to roughly 0.1 second.

It did feel very hacky though.

I finally took the time to look into the wpa_supplicant code and
found a way to implement the functionality in a way which only
limits the frequencies of the very first scan.
This speeds up the connection time when starting the application,
in the event that it's connecting to the same network, without
limiting performance afterwards.

This is done by providing an `initial_freq_list` parameter in the
configuration file. This list follows the same rules as the
`freq_list` list.

Some machinery is required to then provide this list - we have a
separate script which saves the list in a file.
This file is then concatenated to a copy of the conf file, before
being loaded by wpa_supplicant.

I've verified that it works, but would love to see additional
verification from someone else, just to ensure that I didn't miss
anything.

For now this scratches my own itch. However, a better way to do
this could be to provide a path to a file, as part of the
configuration.
Wpa_supplicant could then take care of updating this file with
the last known frequency as it switches networks, and use the
contents of the file when  starting to do the initial scan.
This would eliminate the need for additional work outside of
wpa_supplicant and would probably be the better implementation.
For now, this works though :-)

This is my first time contributing to an open-source project like
this, so please let me know if my patch does not adhere to
guidelines or similar - I'll do what I can to fix it.

>From a21895fa1389180509a1bf9104c4ab36684b255f Mon Sep 17 00:00:00
2001
From: Frederik Juul <frederik.juul at 3shape.com>
Date: Thu, 23 Jul 2020 10:00:23 +0200
Subject: [PATCH] Add initial_freq_list to 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.

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 at 3shape.com>
---
 wpa_supplicant/config.c | 20 ++++++++++++++++++++
 wpa_supplicant/config.h | 13 +++++++++++++
 wpa_supplicant/scan.c   |  8 +++++++-
 3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 0b4a66ad7..7027e23ce 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2888,6 +2888,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);
@@ -4508,6 +4509,24 @@ static int
wpa_config_process_freq_list(const struct global_parse_data
*data,
 	return 0;
 }
 
+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 == NULL)
+		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,
@@ -5039,6 +5058,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 a385da528..54c7c98b4 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -913,6 +913,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/scan.c b/wpa_supplicant/scan.c
index 7415eae9f..3a6bd818e 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -1197,7 +1197,13 @@ ssid_list_set:
 	wpa_setband_scan_freqs(wpa_s, &params);
 
 	/* 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,
 			"Optimize scan based on
conf->freq_list");
 		int_array_concat(&params.freqs,
wpa_s->conf->freq_list);
-- 
2.19.1


Frederik Juul
Scanner Developer
IOS Scanner Development

3Shape
Holmens Kanal 7
1060 Copenhagen
Denmark
Mobile:   +45 31 35 19 84 
E-mail:   frederik.juul at 3shape.com 
Web:   www.3shape.com 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4511 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/hostap/attachments/20200723/c08d52a2/attachment.p7s>


More information about the Hostap mailing list