Drivers will often report regdom changes in the middle of a scan if it detects during that scan that the regulatory domain has changed. If this happens and we enter a regdom that supports 6ghz channels when the previous one didn't (this often happens in 6ghz-capable regdoms for devices after suspend/resume), immediately trigger a 6ghz-only scan if we were not able to connect to an AP on a legacy band. This should significantly improve connection time to 6ghz AP after regdom has been reset. Signed-off-by: Matthew Wang <matthewmwang@xxxxxxxxxxxx> --- wpa_supplicant/bgscan_learn.c | 2 +- wpa_supplicant/bgscan_simple.c | 2 +- wpa_supplicant/dbus/dbus_new_handlers.c | 7 +-- wpa_supplicant/events.c | 65 +++++++++++++++++++++++-- wpa_supplicant/rrm.c | 2 +- wpa_supplicant/scan.c | 9 ++-- wpa_supplicant/scan.h | 2 +- wpa_supplicant/sme.c | 2 +- wpa_supplicant/wpa_supplicant_i.h | 4 ++ 9 files changed, 79 insertions(+), 16 deletions(-) diff --git a/wpa_supplicant/bgscan_learn.c b/wpa_supplicant/bgscan_learn.c index 3db425963eb..9830c4aa16e 100644 --- a/wpa_supplicant/bgscan_learn.c +++ b/wpa_supplicant/bgscan_learn.c @@ -305,7 +305,7 @@ static void bgscan_learn_timeout(void *eloop_ctx, void *timeout_ctx) } wpa_printf(MSG_DEBUG, "bgscan learn: Request a background scan"); - if (wpa_supplicant_trigger_scan(wpa_s, ¶ms, true)) { + if (wpa_supplicant_trigger_scan(wpa_s, ¶ms, true, false)) { wpa_printf(MSG_DEBUG, "bgscan learn: Failed to trigger scan"); eloop_register_timeout(data->scan_interval, 0, bgscan_learn_timeout, data, NULL); diff --git a/wpa_supplicant/bgscan_simple.c b/wpa_supplicant/bgscan_simple.c index 1b12726d203..f398b850776 100644 --- a/wpa_supplicant/bgscan_simple.c +++ b/wpa_supplicant/bgscan_simple.c @@ -49,7 +49,7 @@ static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx) */ wpa_printf(MSG_DEBUG, "bgscan simple: Request a background scan"); - if (wpa_supplicant_trigger_scan(wpa_s, ¶ms, true)) { + if (wpa_supplicant_trigger_scan(wpa_s, ¶ms, true, false)) { wpa_printf(MSG_DEBUG, "bgscan simple: Failed to trigger scan"); eloop_register_timeout(data->scan_interval, 0, bgscan_simple_timeout, data, NULL); diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index d7fdea0ed90..0692f0dfab3 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -1704,8 +1704,8 @@ DBusMessage * wpas_dbus_handler_scan(DBusMessage *message, if (params.freqs && params.freqs[0]) { wpa_s->last_scan_req = MANUAL_SCAN_REQ; - if (wpa_supplicant_trigger_scan(wpa_s, - ¶ms, false)) { + if (wpa_supplicant_trigger_scan(wpa_s, ¶ms, + false, false)) { reply = wpas_dbus_error_scan_error( message, "Scan request rejected"); @@ -1731,7 +1731,8 @@ DBusMessage * wpas_dbus_handler_scan(DBusMessage *message, } wpa_s->last_scan_req = MANUAL_SCAN_REQ; - if (wpa_supplicant_trigger_scan(wpa_s, ¶ms, !custom_ies)) { + if (wpa_supplicant_trigger_scan(wpa_s, ¶ms, !custom_ies, + false)) { reply = wpas_dbus_error_scan_error( message, "Scan request rejected"); } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e7aaa1a1284..74ecd0d7b71 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -57,7 +57,9 @@ #ifndef CONFIG_NO_SCAN_PROCESSING static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s, - int new_scan, int own_request); + int new_scan, int own_request, + bool trigger_6ghz_scan, + union wpa_event_data *data); #endif /* CONFIG_NO_SCAN_PROCESSING */ #ifdef CONFIG_OWE static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, @@ -2196,6 +2198,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, struct wpa_scan_results *scan_res = NULL; int ret = 0; int ap = 0; + bool trigger_6ghz_scan; #ifndef CONFIG_NO_RANDOM_POOL size_t i, num; #endif /* CONFIG_NO_RANDOM_POOL */ @@ -2205,6 +2208,10 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, ap = 1; #endif /* CONFIG_AP */ + trigger_6ghz_scan = wpa_s->crossed_6ghz_dom && wpa_s->last_scan_all_chan; + wpa_s->crossed_6ghz_dom = false; + wpa_s->last_scan_all_chan = false; + wpa_supplicant_notify_scanning(wpa_s, 0); scan_res = wpa_supplicant_get_scan_results(wpa_s, @@ -2355,7 +2362,8 @@ 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; - return wpas_select_network_from_last_scan(wpa_s, 1, own_request); + return wpas_select_network_from_last_scan(wpa_s, 1, own_request, + trigger_6ghz_scan, data); scan_work_done: wpa_scan_results_free(scan_res); @@ -2368,8 +2376,20 @@ scan_work_done: } +/** + * Select a network from the last scan. + * @wpa_s: pointer to wpa_supplicant data + * @new_scan: whether this function was called right after a scan has finished + * @own_request: whether the scan was requested by this interface + * @trigger_6ghz_scan: whether to trigger a 6ghz-only scan when applicable + * @data: scan data from scan that finished if applicable + * + * See _wpa_supplicant_event_scan_results for return values. + */ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s, - int new_scan, int own_request) + int new_scan, int own_request, + bool trigger_6ghz_scan, + union wpa_event_data *data) { struct wpa_bss *selected; struct wpa_ssid *ssid = NULL; @@ -2441,6 +2461,33 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s, if (new_scan) wpa_supplicant_rsn_preauth_scan_results(wpa_s); } else if (own_request) { + if (wpa_s->support_6ghz && trigger_6ghz_scan && data) { + struct wpa_driver_scan_params params; + 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); + } + /* * No SSID found. If SCAN results are as a result of * own scan request and not due to a scan request on @@ -2588,7 +2635,7 @@ int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s) return -1; } - return wpas_select_network_from_last_scan(wpa_s, 0, 1); + return wpas_select_network_from_last_scan(wpa_s, 0, 1, false, NULL); #endif /* CONFIG_NO_SCAN_PROCESSING */ } @@ -2598,7 +2645,7 @@ int wpa_wps_supplicant_fast_associate(struct wpa_supplicant *wpa_s) #ifdef CONFIG_NO_SCAN_PROCESSING return -1; #else /* CONFIG_NO_SCAN_PROCESSING */ - return wpas_select_network_from_last_scan(wpa_s, 1, 1); + return wpas_select_network_from_last_scan(wpa_s, 1, 1, false, NULL); #endif /* CONFIG_NO_SCAN_PROCESSING */ } @@ -4683,6 +4730,9 @@ void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s, ifs->hw.modes = wpa_drv_get_hw_feature_data( ifs, &ifs->hw.num_modes, &ifs->hw.flags, &dfs_domain); + bool was_6ghz_enabled = ifs->is_6ghz_enabled; + ifs->is_6ghz_enabled = wpas_is_6ghz_supported(ifs, true); + /* Restart PNO/sched_scan with updated channel list */ if (ifs->pno) { wpas_stop_pno(ifs); @@ -4691,6 +4741,11 @@ void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s, wpa_dbg(ifs, MSG_DEBUG, "Channel list changed - restart sched_scan"); wpas_scan_restart_sched_scan(ifs); + } else if (ifs->scanning && !was_6ghz_enabled && ifs->is_6ghz_enabled) { + /* Look for APs in the 6GHz band */ + wpa_dbg(ifs, MSG_INFO, + "Channel list changed - trigger 6GHz-only scan"); + ifs->crossed_6ghz_dom = true; } } diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c index bf6575a0bf3..8e51717ab12 100644 --- a/wpa_supplicant/rrm.c +++ b/wpa_supplicant/rrm.c @@ -1033,7 +1033,7 @@ static void wpas_rrm_scan_timeout(void *eloop_ctx, void *timeout_ctx) } os_get_reltime(&wpa_s->beacon_rep_scan); if (wpa_s->scanning || wpas_p2p_in_progress(wpa_s) || - wpa_supplicant_trigger_scan(wpa_s, params, true)) + wpa_supplicant_trigger_scan(wpa_s, params, true, false)) wpas_rrm_refuse_request(wpa_s); params->duration = prev_duration; } diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 8287d88af18..5ffe7040b52 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -279,6 +279,7 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit) * @wpa_s: Pointer to wpa_supplicant data * @params: Scan parameters * @default_ies: Whether or not to use the default IEs in the probe request. + * @next: Whether or not to perform this scan as the next radio work. * Note that this will free any existing IEs set in @params, so this shouldn't * be set if the IEs have already been set with wpa_supplicant_extra_ies. * Otherwise, wpabuf_free will lead to a double-free. @@ -286,7 +287,7 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit) */ int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params, - bool default_ies) + bool default_ies, bool next) { struct wpa_driver_scan_params *ctx; struct wpabuf *ies = NULL; @@ -314,8 +315,10 @@ int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, params->extra_ies = NULL; params->extra_ies_len = 0; } + wpa_s->last_scan_all_chan = !params->freqs; + wpa_s->last_scan_non_coloc_6ghz = params->non_coloc_6ghz; if (!ctx || - radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0) + radio_add_work(wpa_s, 0, "scan", next, wpas_trigger_scan_cb, ctx) < 0) { wpa_scan_free_params(ctx); wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=-1"); @@ -1474,7 +1477,7 @@ scan: wpas_p2p_scan_freqs(wpa_s, ¶ms, true); #endif /* CONFIG_P2P */ - ret = wpa_supplicant_trigger_scan(wpa_s, scan_params, false); + ret = wpa_supplicant_trigger_scan(wpa_s, scan_params, false, false); if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs && !wpa_s->manual_scan_freqs) { diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h index 17c7b06a6bd..c4aefab559e 100644 --- a/wpa_supplicant/scan.h +++ b/wpa_supplicant/scan.h @@ -46,7 +46,7 @@ void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params; int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params, - bool default_ies); + bool default_ies, bool next); struct wpa_scan_results * wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, struct scan_info *info, int new_scan); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 8e72643f1dc..51e6e8f7a19 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -3083,7 +3083,7 @@ static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx) params.low_priority = 1; wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan"); - if (wpa_supplicant_trigger_scan(wpa_s, ¶ms, true)) + if (wpa_supplicant_trigger_scan(wpa_s, ¶ms, true, false)) wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan"); else wpa_s->sme.sched_obss_scan = 1; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index efd83c79eb5..011e0aa72a4 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1527,6 +1527,10 @@ struct wpa_supplicant { unsigned int enable_dscp_policy_capa:1; unsigned int connection_dscp:1; unsigned int wait_for_dscp_req:1; + bool is_6ghz_enabled; + bool crossed_6ghz_dom; + bool last_scan_all_chan; + bool last_scan_non_coloc_6ghz; bool support_6ghz; struct wpa_signal_info last_signal_info; -- 2.39.2 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap