aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2020-06-30 12:34:41 -0500
committerDenis Kenzior <denkenz@gmail.com>2020-06-30 12:34:41 -0500
commita1b41f786e9ce5eb936093c7f5082d53bf89eaac (patch)
tree2c075f3c2d1f794513f90a760b69460cb7be6f10
parentb026e6740be480fc8d2012c0aedbf36758f8e4f3 (diff)
downloadiwd-a1b41f786e9ce5eb936093c7f5082d53bf89eaac.tar.gz
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.
-rw-r--r--src/station.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/station.c b/src/station.c
index de1c05cec..3719e0b90 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);
@@ -1376,11 +1381,28 @@ static void station_roam_failed(struct station *station)
}
/*
+ * 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), &params,
station_roam_scan_triggered,