diff mbox series

supplicant: Allow simple bgscan to do btm queries.

Message ID 20230608235401.3637832-1-greearb@candelatech.com
State Changes Requested
Headers show
Series supplicant: Allow simple bgscan to do btm queries. | expand

Commit Message

Ben Greear June 8, 2023, 11:54 p.m. UTC
From: Ben Greear <greearb@candelatech.com>

Allow doing X bss_transition_mgmt_query calls before falling back to
scan.

Example format to do 4 btm before attempting a scan: bgscan="simple:30:-65:300:4"

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 wpa_supplicant/bgscan_simple.c     | 28 ++++++++++++++++++++++++++++
 wpa_supplicant/wpa_supplicant.conf |  5 +++--
 2 files changed, 31 insertions(+), 2 deletions(-)

Comments

Jouni Malinen Nov. 5, 2023, 5:55 p.m. UTC | #1
On Thu, Jun 08, 2023 at 04:54:01PM -0700, greearb@candelatech.com wrote:
> Allow doing X bss_transition_mgmt_query calls before falling back to
> scan.
> 
> Example format to do 4 btm before attempting a scan: bgscan="simple:30:-65:300:4"

> diff --git a/wpa_supplicant/bgscan_simple.c b/wpa_supplicant/bgscan_simple.c
> @@ -36,6 +40,22 @@ static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
> +	if (data->use_wnm_query && !wpa_s->conf->disable_btm) {

wnm_query is a misleading name since WNM includes much more than just
BTM.. btm_query would be clearer.

This should check whether the current AP supports BTM before deciding to
use BTM queries instead of scans.

> +		int mod;
> +
> +		/* try wnm x times, scan on x + 1 */
> +		data->scan_action_count++;
> +		mod = data->scan_action_count % (data->use_wnm_query + 1);
> +		if (mod < data->use_wnm_query) {
> +			wpa_printf(MSG_DEBUG, "bgscan simple: Send bss transition mgt query %d/%d",
> +				   mod, data->use_wnm_query);
> +			if (wnm_send_bss_transition_mgmt_query(wpa_s, 6 /* better AP found */, NULL, 0))
> +				wpa_printf(MSG_DEBUG, "bgscan simple: Failed send bss transition mgt query");
> +			else
> +				goto scan_ok;
> +		}
> +	}

This success case would skip starting of the scan and this timeout on
failure:

>  	os_memset(&params, 0, sizeof(params));
>  	params.num_ssids = 1;
>  	params.ssids[0].ssid = data->ssid->ssid;
> @@ -58,6 +78,7 @@ static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
>  		eloop_register_timeout(data->scan_interval, 0,
>  				       bgscan_simple_timeout, data, NULL);
>  	} else {
> +	scan_ok:
>  		if (data->scan_interval == data->short_interval) {
>  			data->short_scan_count++;
>  			if (data->short_scan_count >= data->max_short_scans) {

And instead, would not leave any new trigger to get
bgscan_simple_timeout called again. In other words, this would leave
bgscan stuck not doing anything. The BTM query case should schedule a
new timeout to cover cases where BTM request is not received and also to
cover cases where BTM request is received but no transition is
performed.
Ben Greear Nov. 20, 2023, 7:51 p.m. UTC | #2
On 11/5/23 09:55, Jouni Malinen wrote:
> On Thu, Jun 08, 2023 at 04:54:01PM -0700, greearb@candelatech.com wrote:
>> Allow doing X bss_transition_mgmt_query calls before falling back to
>> scan.
>>
>> Example format to do 4 btm before attempting a scan: bgscan="simple:30:-65:300:4"
> 
>> diff --git a/wpa_supplicant/bgscan_simple.c b/wpa_supplicant/bgscan_simple.c
>> @@ -36,6 +40,22 @@ static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
>> +	if (data->use_wnm_query && !wpa_s->conf->disable_btm) {
> 
> wnm_query is a misleading name since WNM includes much more than just
> BTM.. btm_query would be clearer.
> 
> This should check whether the current AP supports BTM before deciding to
> use BTM queries instead of scans.

Any hints on how to tell if AP supports BTM or not?  I didn't see anything
obvious when digging through the code.

Thanks,
Ben
Jouni Malinen Nov. 22, 2023, 4:42 p.m. UTC | #3
On Mon, Nov 20, 2023 at 11:51:39AM -0800, Ben Greear wrote:
> Any hints on how to tell if AP supports BTM or not?  I didn't see anything
> obvious when digging through the code.

Bit 19 (BSS Transition) in the Extended Capabilities field, i.e.,
WLAN_EXT_CAPAB_BSS_TRANSITION indicates this.
diff mbox series

Patch

diff --git a/wpa_supplicant/bgscan_simple.c b/wpa_supplicant/bgscan_simple.c
index 320ba92f5..51517ba0d 100644
--- a/wpa_supplicant/bgscan_simple.c
+++ b/wpa_supplicant/bgscan_simple.c
@@ -16,10 +16,14 @@ 
 #include "driver_i.h"
 #include "scan.h"
 #include "bgscan.h"
+#include "config.h"
+#include "wnm_sta.h"
 
 struct bgscan_simple_data {
 	struct wpa_supplicant *wpa_s;
 	const struct wpa_ssid *ssid;
+	int use_wnm_query;
+	unsigned int scan_action_count;
 	int scan_interval;
 	int signal_threshold;
 	int short_scan_count; /* counter for scans using short scan interval */
@@ -36,6 +40,22 @@  static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
 	struct wpa_supplicant *wpa_s = data->wpa_s;
 	struct wpa_driver_scan_params params;
 
+	if (data->use_wnm_query && !wpa_s->conf->disable_btm) {
+		int mod;
+
+		/* try wnm x times, scan on x + 1 */
+		data->scan_action_count++;
+		mod = data->scan_action_count % (data->use_wnm_query + 1);
+		if (mod < data->use_wnm_query) {
+			wpa_printf(MSG_DEBUG, "bgscan simple: Send bss transition mgt query %d/%d",
+				   mod, data->use_wnm_query);
+			if (wnm_send_bss_transition_mgmt_query(wpa_s, 6 /* better AP found */, NULL, 0))
+				wpa_printf(MSG_DEBUG, "bgscan simple: Failed send bss transition mgt query");
+			else
+				goto scan_ok;
+		}
+	}
+
 	os_memset(&params, 0, sizeof(params));
 	params.num_ssids = 1;
 	params.ssids[0].ssid = data->ssid->ssid;
@@ -58,6 +78,7 @@  static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
 		eloop_register_timeout(data->scan_interval, 0,
 				       bgscan_simple_timeout, data, NULL);
 	} else {
+	scan_ok:
 		if (data->scan_interval == data->short_interval) {
 			data->short_scan_count++;
 			if (data->short_scan_count >= data->max_short_scans) {
@@ -84,6 +105,8 @@  static int bgscan_simple_get_params(struct bgscan_simple_data *data,
 {
 	const char *pos;
 
+	data->use_wnm_query = 0;
+
 	data->short_interval = atoi(params);
 
 	pos = os_strchr(params, ':');
@@ -99,6 +122,11 @@  static int bgscan_simple_get_params(struct bgscan_simple_data *data,
 	}
 	pos++;
 	data->long_interval = atoi(pos);
+	pos = os_strchr(pos, ':');
+	if (pos) {
+		pos++;
+		data->use_wnm_query = atoi(pos);
+	}
 
 	return 0;
 }
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 29d6f6e7a..5e41139e0 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -1024,9 +1024,10 @@  fast_reauth=1
 # parameter uses following format: "<bgscan module name>:<module parameters>"
 # Following bgscan modules are available:
 # simple - Periodic background scans based on signal strength
+# send_wnm_query > 0 means do this many wnm queries before attempting a scan.
 # bgscan="simple:<short bgscan interval in seconds>:<signal strength threshold>:
-# <long interval>"
-# bgscan="simple:30:-45:300"
+# <long interval>:<send_wnm_query>"
+# bgscan="simple:30:-45:300:3"
 # learn - Learn channels used by the network and try to avoid bgscans on other
 # channels (experimental)
 # bgscan="learn:<short bgscan interval in seconds>:<signal strength threshold>: