diff mbox series

[v4,2/3] scan: split full scans by band to enable 6GHz

Message ID 20220804220249.508207-2-prestwoj@gmail.com (mailing list archive)
State Not Applicable, archived
Headers show
Series [v4,1/3] util: add scan_freq_set_copy_bands | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
prestwoj/iwd-ci-gitlint success GitLint

Commit Message

James Prestwood Aug. 4, 2022, 10:02 p.m. UTC
The kernel's regulatory domain updates after some number of beacons
are processed. This triggers a regulatory domain update (and wiphy
dump) but only after a scan request. This means a full scan started
prior to the regdom being set will not include any 6Ghz BSS's even
if the regdom was unlocked during the scan.

This can be worked around by splitting up a large scan request into
multiple requests allowing one of the first commands to trigger a
regdom update. Once the regdom updates (and wiphy dumps) we are
hopefully still scanning and could append an additional request to
scan 6GHz.
---
 src/scan.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 76 insertions(+), 9 deletions(-)

v4:
 * Use scan_freq_set_copy_bands

Comments

Denis Kenzior Aug. 5, 2022, 5:03 p.m. UTC | #1
Hi James,

On 8/4/22 17:02, James Prestwood wrote:
> The kernel's regulatory domain updates after some number of beacons
> are processed. This triggers a regulatory domain update (and wiphy
> dump) but only after a scan request. This means a full scan started
> prior to the regdom being set will not include any 6Ghz BSS's even
> if the regdom was unlocked during the scan.
> 
> This can be worked around by splitting up a large scan request into
> multiple requests allowing one of the first commands to trigger a
> regdom update. Once the regdom updates (and wiphy dumps) we are
> hopefully still scanning and could append an additional request to
> scan 6GHz.
> ---
>   src/scan.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++------
>   1 file changed, 76 insertions(+), 9 deletions(-)
> 

<snip>

> +	/*
> +	 * Otherwise a full spectrum scan will likely open up the 6GHz
> +	 * band. The problem is the regdom update occurs after an
> +	 * individual scan request so a single request isn't going to
> +	 * include potential 6GHz results.
> +	 *
> +	 * Instead we can break this full scan up into individual bands
> +	 * and increase our chances of the regdom updating after one of
> +	 * the earlier requests. If it does update to allow 6GHz an
> +	 * extra 6GHz-only passive scan can be appended to this request
> +	 * at that time.
> +	 */
> +	subsets[0] = scan_freq_set_copy_bands(allowed, BAND_FREQ_2_4_GHZ);
> +	subsets[1] = scan_freq_set_copy_bands(allowed, BAND_FREQ_5_GHZ);

I updated these to use _clone() and ...

> +
> +	scan_freq_set_free(allowed);
> +
> +	for(i = 0; i < L_ARRAY_SIZE(subsets); i++) {
> +		scan_build_next_cmd(sr->cmds, sc, passive, params,
> +					subsets[i]);

added a scan_freq_set_isempty() check here to skip building the command in the 
unlikely event that the set is empty.

> +		scan_freq_set_free(subsets[i]);
> +	}
> +
> +	sr->split = true;
> +}
> +
>   static int scan_request_send_trigger(struct scan_context *sc,
>   					struct scan_request *sr)
>   {

Applied, thanks!

Regards,
-Denis
diff mbox series

Patch

diff --git a/src/scan.c b/src/scan.c
index b666ba2e..12c970a7 100644
--- a/src/scan.c
+++ b/src/scan.c
@@ -94,6 +94,8 @@  struct scan_request {
 	 */
 	bool triggered : 1;
 	bool in_callback : 1; /* Scan request complete, re-entrancy guard */
+	/* The request was split anticipating 6GHz will become available */
+	bool split : 1;
 	struct l_queue *cmds;
 	/* The time the current scan was started. Reported in TRIGGER_SCAN */
 	uint64_t start_time_tsf;
@@ -352,9 +354,24 @@  static bool scan_mac_address_randomization_is_disabled(void)
 	return disabled;
 }
 
+static struct scan_freq_set *scan_get_allowed_freqs(struct scan_context *sc)
+{
+	struct scan_freq_set *allowed = scan_freq_set_new();
+
+	scan_freq_set_merge(allowed, wiphy_get_supported_freqs(sc->wiphy));
+
+	if (!wiphy_constrain_freq_set(sc->wiphy, allowed)) {
+		scan_freq_set_free(allowed);
+		allowed = NULL;
+	}
+
+	return allowed;
+}
+
 static struct l_genl_msg *scan_build_cmd(struct scan_context *sc,
 					bool ignore_flush_flag, bool is_passive,
-					const struct scan_parameters *params)
+					const struct scan_parameters *params,
+					const struct scan_freq_set *freqs)
 {
 	struct l_genl_msg *msg;
 	uint32_t flags = 0;
@@ -366,8 +383,8 @@  static struct l_genl_msg *scan_build_cmd(struct scan_context *sc,
 	if (wiphy_get_max_scan_ie_len(sc->wiphy))
 		scan_build_attr_ie(msg, sc, params);
 
-	if (params->freqs)
-		scan_build_attr_scan_frequencies(msg, params->freqs);
+	if (freqs)
+		scan_build_attr_scan_frequencies(msg, freqs);
 
 	if (params->flush && !ignore_flush_flag && wiphy_has_feature(sc->wiphy,
 						NL80211_FEATURE_SCAN_FLUSH))
@@ -524,16 +541,18 @@  static bool scan_cmds_add_hidden(const struct network_info *network,
 		 * of all scans in the batch after the last scan is finished.
 		 */
 		*data->cmd = scan_build_cmd(data->sc, true, false,
-								data->params);
+							data->params,
+							data->params->freqs);
 		l_genl_msg_enter_nested(*data->cmd, NL80211_ATTR_SCAN_SSIDS);
 	}
 
 	return true;
 }
 
-static void scan_cmds_add(struct l_queue *cmds, struct scan_context *sc,
+static void scan_build_next_cmd(struct l_queue *cmds, struct scan_context *sc,
 				bool passive,
-				const struct scan_parameters *params)
+				const struct scan_parameters *params,
+				const struct scan_freq_set *freqs)
 {
 	struct l_genl_msg *cmd;
 	struct scan_cmds_add_data data = {
@@ -544,7 +563,7 @@  static void scan_cmds_add(struct l_queue *cmds, struct scan_context *sc,
 		wiphy_get_max_num_ssids_per_scan(sc->wiphy),
 	};
 
-	cmd = scan_build_cmd(sc, false, passive, params);
+	cmd = scan_build_cmd(sc, false, passive, params, freqs);
 
 	if (passive) {
 		/* passive scan */
@@ -572,6 +591,54 @@  static void scan_cmds_add(struct l_queue *cmds, struct scan_context *sc,
 	l_queue_push_tail(cmds, cmd);
 }
 
+static void scan_cmds_add(struct scan_request *sr, struct scan_context *sc,
+				bool passive,
+				const struct scan_parameters *params)
+{
+	unsigned int i;
+	struct scan_freq_set *subsets[2] = { 0 };
+	struct scan_freq_set *allowed = scan_get_allowed_freqs(sc);
+	const struct scan_freq_set *supported =
+					wiphy_get_supported_freqs(sc->wiphy);
+
+	/*
+	 * If 6GHz is not possible, or already allowed, or the frequencies are
+	 * explicit don't break up the request.
+	 */
+	if (!(scan_freq_set_get_bands(supported) & BAND_FREQ_6_GHZ) ||
+			(scan_freq_set_get_bands(allowed) & BAND_FREQ_6_GHZ) ||
+			params->freqs) {
+		scan_freq_set_free(allowed);
+		scan_build_next_cmd(sr->cmds, sc, passive, params, params->freqs);
+		return;
+	}
+
+	/*
+	 * Otherwise a full spectrum scan will likely open up the 6GHz
+	 * band. The problem is the regdom update occurs after an
+	 * individual scan request so a single request isn't going to
+	 * include potential 6GHz results.
+	 *
+	 * Instead we can break this full scan up into individual bands
+	 * and increase our chances of the regdom updating after one of
+	 * the earlier requests. If it does update to allow 6GHz an
+	 * extra 6GHz-only passive scan can be appended to this request
+	 * at that time.
+	 */
+	subsets[0] = scan_freq_set_copy_bands(allowed, BAND_FREQ_2_4_GHZ);
+	subsets[1] = scan_freq_set_copy_bands(allowed, BAND_FREQ_5_GHZ);
+
+	scan_freq_set_free(allowed);
+
+	for(i = 0; i < L_ARRAY_SIZE(subsets); i++) {
+		scan_build_next_cmd(sr->cmds, sc, passive, params,
+					subsets[i]);
+		scan_freq_set_free(subsets[i]);
+	}
+
+	sr->split = true;
+}
+
 static int scan_request_send_trigger(struct scan_context *sc,
 					struct scan_request *sr)
 {
@@ -649,7 +716,7 @@  static uint32_t scan_common(uint64_t wdev_id, bool passive,
 
 	sr = scan_request_new(sc, passive, trigger, notify, userdata, destroy);
 
-	scan_cmds_add(sr->cmds, sc, passive, params);
+	scan_cmds_add(sr, sc, passive, params);
 
 	/*
 	 * sr->work isn't initialized yet, it will be done by
@@ -743,7 +810,7 @@  static void add_owe_scan_cmd(struct scan_context *sc, struct scan_request *sr,
 	params.ssid_len = bss->owe_trans->ssid_len;
 	params.flush = true;
 
-	cmd = scan_build_cmd(sc, ignore_flush, false, &params);
+	cmd = scan_build_cmd(sc, ignore_flush, false, &params, params.freqs);
 
 	l_genl_msg_enter_nested(cmd, NL80211_ATTR_SCAN_SSIDS);
 	l_genl_msg_append_attr(cmd, 0, params.ssid_len, params.ssid);