From a1b41f786e9ce5eb936093c7f5082d53bf89eaac Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 30 Jun 2020 12:34:41 -0500 Subject: [PATCH] station: Re-attempt roam with a full scan When roaming, iwd tries to scan a limited number of frequencies to keep the roaming latency down. Ideally the frequency list would come in from a neighbor report, but if neighbor reports are not supported, we fall back to our internal database for known frequencies of this network. iwd tries to keep the number of scans down to a bare minimum, which means that we might miss APs that are in range. This could happen because the user might have moved physically and our frequency list is no longer up to date, or if the AP frequencies have been reconfigured. If a limited scan fails to find any good roaming candidates, re-attempt a full scan right away. --- src/station.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/station.c b/src/station.c index de1c05ce..3719e0b9 100644 --- a/src/station.c +++ b/src/station.c @@ -96,6 +96,7 @@ struct station { struct netconfig *netconfig; bool preparing_roam : 1; + bool roam_scan_full : 1; bool signal_low : 1; bool roam_no_orig_ap : 1; bool ap_directed_roaming : 1; @@ -1282,6 +1283,7 @@ static void station_roam_state_clear(struct station *station) l_timeout_remove(station->roam_trigger_timeout); station->roam_trigger_timeout = NULL; station->preparing_roam = false; + station->roam_scan_full = false; station->signal_low = false; station->roam_min_time.tv_sec = 0; @@ -1345,6 +1347,8 @@ static void station_disconnect_event(struct station *station, void *event_data) } static void station_roam_timeout_rearm(struct station *station, int seconds); +static int station_roam_scan(struct station *station, + struct scan_freq_set *freq_set); static void station_roamed(struct station *station) { @@ -1355,6 +1359,7 @@ static void station_roamed(struct station *station) station->signal_low = false; station->roam_min_time.tv_sec = 0; station->roam_no_orig_ap = false; + station->roam_scan_full = false; if (station->netconfig) netconfig_reconfigure(station->netconfig); @@ -1375,12 +1380,29 @@ static void station_roam_failed(struct station *station) return; } + /* + * We were told by the AP to roam, but failed. Try ourselves or + * wait for the AP to tell us to roam again + */ + if (station->ap_directed_roaming) + goto delayed_retry; + + /* + * If we tried a limited scan, failed and the signal is still low, + * repeat with a full scan right away + */ + if (station->signal_low && !station->roam_scan_full && + !station_roam_scan(station, NULL)) + return; + +delayed_retry: /* * If we're still connected to the old BSS, only clear preparing_roam * and reattempt in 60 seconds if signal level is still low at that * time. */ station->preparing_roam = false; + station->roam_scan_full = false; station->ap_directed_roaming = false; if (station->signal_low) @@ -1784,6 +1806,9 @@ static int station_roam_scan(struct station *station, /* Use direct probe request */ params.ssid = network_get_ssid(station->connected_network); + if (!freq_set) + station->roam_scan_full = true; + station->roam_scan_id = scan_active_full(netdev_get_wdev_id(station->netdev), ¶ms, station_roam_scan_triggered,