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.
This commit is contained in:
Denis Kenzior 2020-06-30 12:34:41 -05:00
parent b026e6740b
commit a1b41f786e
1 changed files with 25 additions and 0 deletions

View File

@ -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), &params,
station_roam_scan_triggered,