[PATCH] Trigger 6GHz scan if RNR contains matching short SSID
Matthew Wang
matthewmwang at chromium.org
Tue Jun 4 14:02:16 PDT 2024
If a scan triggers a regdom update into a 6GHz-allowed regdom, and an
RNR IE in one of the legacy band scan results points to a 6GHz scan
result with a short SSID matching the current_ssid, delay connection in
favor of a 6GHz-only scan. This will optimize the case in which we first
connect to a 5GHz AP, then later roam to a 6GHz one by directly
connecting to the 6GHz one.
Signed-off-by: Matthew Wang <matthewmwang at chromium.org>
---
wpa_supplicant/events.c | 109 +++++++++++++++++++++++++++++++---------
1 file changed, 84 insertions(+), 25 deletions(-)
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 447fc8fd8..049cbf415 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -52,6 +52,7 @@
#include "wmm_ac.h"
#include "nan_usd.h"
#include "dpp_supplicant.h"
+#include "utils/crc32.h"
#define MAX_OWE_TRANSITION_BSS_SELECT_COUNT 5
@@ -2378,6 +2379,78 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
}
+static int wpas_trigger_6ghz_scan(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ struct wpa_driver_scan_params params;
+ unsigned int j;
+
+ wpa_dbg(wpa_s, MSG_INFO, "Triggering 6GHz-only scan");
+ os_memset(¶ms, 0, sizeof(params));
+ params.non_coloc_6ghz = wpa_s->last_scan_non_coloc_6ghz;
+ for (j = 0; j < data->scan_info.num_ssids; j++)
+ params.ssids[j] = data->scan_info.ssids[j];
+ params.num_ssids = data->scan_info.num_ssids;
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, ¶ms,
+ true, !wpa_s->last_scan_non_coloc_6ghz, false);
+ if (!wpa_supplicant_trigger_scan(wpa_s, ¶ms, true, true)) {
+ os_free(params.freqs);
+ return 1;
+ }
+ wpa_dbg(wpa_s, MSG_INFO, "Failed to trigger 6GHz-only scan");
+ os_free(params.freqs);
+ return 0;
+}
+
+
+static bool wpas_short_ssid_match(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res)
+{
+ size_t i;
+ u32 current_ssid_short = ieee80211_crc32(wpa_s->current_ssid->ssid,
+ wpa_s->current_ssid->ssid_len);
+
+ for (i = 0; i < scan_res->num; i++) {
+ struct wpa_scan_res *res = scan_res->res[i];
+ const u8 *rnr_ie, *ie_end;
+ const struct ieee80211_neighbor_ap_info *info;
+ size_t left;
+
+ rnr_ie = wpa_scan_get_ie(res, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
+ if (!rnr_ie)
+ continue;
+
+ ie_end = rnr_ie + 2 + rnr_ie[1];
+ rnr_ie += 2;
+
+ info = (const struct ieee80211_neighbor_ap_info *) rnr_ie;
+ if (info->tbtt_info_len < 11)
+ continue;
+ left = ie_end - rnr_ie;
+
+ if (left < sizeof(struct ieee80211_neighbor_ap_info))
+ continue;
+
+ left -= sizeof(struct ieee80211_neighbor_ap_info);
+ if (left < info->tbtt_info_len)
+ continue;
+
+ rnr_ie += sizeof(struct ieee80211_neighbor_ap_info);
+ while (rnr_ie + 11 <= ie_end) {
+ /* skip TBTT offset and BSSID */
+ u32 short_ssid = WPA_GET_LE32(rnr_ie + 1 + ETH_ALEN);
+
+ if (short_ssid == current_ssid_short)
+ return true;
+
+ rnr_ie += info->tbtt_info_len;
+ }
+ }
+
+ return false;
+}
+
+
/*
* Return a negative value if no scan results could be fetched or if scan
* results should not be shared with other virtual interfaces.
@@ -2395,6 +2468,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
int ret = 0;
int ap = 0;
bool trigger_6ghz_scan;
+ bool short_ssid_match_found = false;
#ifndef CONFIG_NO_RANDOM_POOL
size_t i, num;
#endif /* CONFIG_NO_RANDOM_POOL */
@@ -2538,6 +2612,12 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
wpa_s->wpa_state < WPA_COMPLETED)
goto scan_work_done;
+ if (wpa_s->current_ssid && trigger_6ghz_scan && own_request && data &&
+ wpas_short_ssid_match(wpa_s, scan_res)) {
+ wpa_dbg(wpa_s, MSG_INFO, "Short SSID match in scan results");
+ short_ssid_match_found = true;
+ }
+
wpa_scan_results_free(scan_res);
if (own_request && wpa_s->scan_work) {
@@ -2564,6 +2644,9 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
if (wpa_s->supp_pbc_active && !wpas_wps_partner_link_scan_done(wpa_s))
return ret;
+ if (short_ssid_match_found && wpas_trigger_6ghz_scan(wpa_s, data) > 0)
+ return 1;
+
return wpas_select_network_from_last_scan(wpa_s, 1, own_request,
trigger_6ghz_scan, data);
@@ -2578,30 +2661,6 @@ scan_work_done:
}
-static int wpas_trigger_6ghz_scan(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data)
-{
- struct wpa_driver_scan_params params;
- unsigned int j;
-
- wpa_dbg(wpa_s, MSG_INFO, "Triggering 6GHz-only scan");
- os_memset(¶ms, 0, sizeof(params));
- params.non_coloc_6ghz = wpa_s->last_scan_non_coloc_6ghz;
- for (j = 0; j < data->scan_info.num_ssids; j++)
- params.ssids[j] = data->scan_info.ssids[j];
- params.num_ssids = data->scan_info.num_ssids;
- wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, ¶ms,
- true, !wpa_s->last_scan_non_coloc_6ghz, false);
- if (!wpa_supplicant_trigger_scan(wpa_s, ¶ms, true, true)) {
- os_free(params.freqs);
- return 1;
- }
- wpa_dbg(wpa_s, MSG_INFO, "Failed to trigger 6GHz-only scan");
- os_free(params.freqs);
- return 0;
-}
-
-
/**
* Select a network from the last scan
* @wpa_s: Pointer to wpa_supplicant data
@@ -2692,7 +2751,7 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
wpa_supplicant_rsn_preauth_scan_results(wpa_s);
} else if (own_request) {
if (wpa_s->support_6ghz && trigger_6ghz_scan && data &&
- wpas_trigger_6ghz_scan(wpa_s, data) < 0)
+ wpas_trigger_6ghz_scan(wpa_s, data) > 0)
return 1;
/*
--
2.45.1.288.g0e0cd299f1-goog
More information about the Hostap
mailing list