Add an optional timeout when a better roaming candidate is not found
after the scan-retry limit. The roam state-machine will not retry
scanning before this timeout has expired.
If the timeout is set to 0, the client is kicked instead, which
resembles the behavior prior this commit.
This is added, as without this patch, if a forced disconnect
is not desired before roam_scan_trigger is exceeded the client will
repeatedly be asked to return active beacon-reports. For battery powered
clients this can result in a noticeable battery drain.
Signed-off-by: David Bauer <mail@david-bauer.net>
config.roam_kick_delay = 100;
config.roam_process_timeout = 5 * 1000;
config.roam_scan_tries = 3;
config.roam_kick_delay = 100;
config.roam_process_timeout = 5 * 1000;
config.roam_scan_tries = 3;
+ config.roam_scan_timeout = 0;
config.roam_scan_interval = 10 * 1000;
config.roam_trigger_interval = 60 * 1000;
config.roam_scan_interval = 10 * 1000;
config.roam_trigger_interval = 60 * 1000;
# Maximum number of client roaming scan trigger attempts
#option roam_scan_tries 3
# Maximum number of client roaming scan trigger attempts
#option roam_scan_tries 3
+ # Retry scanning when roam_scan_tries is exceeded after this timeout (in ms)
+ # In case this option is set to 0, the client is kicked instead
+ #option roam_scan_timeout 0
+
# Minimum time (ms) between client roaming scan trigger attempts
#option roam_scan_interval 10000
# Minimum time (ms) between client roaming scan trigger attempts
#option roam_scan_interval 10000
remote_update_interval remote_node_timeout\
min_connect_snr min_snr signal_diff_threshold \
initial_connect_delay roam_process_timeout\
remote_update_interval remote_node_timeout\
min_connect_snr min_snr signal_diff_threshold \
initial_connect_delay roam_process_timeout\
- roam_kick_delay roam_scan_tries \
+ roam_kick_delay roam_scan_tries roam_scan_timeout \
roam_scan_snr roam_scan_interval \
roam_trigger_snr roam_trigger_interval \
load_kick_threshold load_kick_delay load_kick_min_clients \
roam_scan_snr roam_scan_interval \
roam_trigger_snr roam_trigger_interval \
load_kick_threshold load_kick_delay load_kick_min_clients \
+static void
+usteer_roam_sm_start_scan(struct sta_info *si, struct uevent *ev)
+{
+ /* Start scanning in case we are not timeout-constrained or timeout has expired */
+ if (config.roam_scan_timeout &&
+ current_time > si->roam_scan_timeout_start + config.roam_scan_timeout) {
+ usteer_roam_set_state(si, ROAM_TRIGGER_SCAN, ev);
+ return;
+ }
+
+ /* We are currently in scan timeout / cooldown.
+ * Check if we are in ROAM_TRIGGER_IDLE state and enter this stateif not.
+ */
+ if (si->roam_state == ROAM_TRIGGER_IDLE)
+ return;
+
+ /* Enter idle state */
+ usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, ev);
+}
+
static bool
usteer_roam_trigger_sm(struct sta_info *si)
{
static bool
usteer_roam_trigger_sm(struct sta_info *si)
{
- if (config.roam_scan_tries &&
- si->roam_tries >= config.roam_scan_tries) {
- usteer_roam_set_state(si, ROAM_TRIGGER_WAIT_KICK, &ev);
+ if (config.roam_scan_tries && si->roam_tries >= config.roam_scan_tries) {
+ if (!config.roam_scan_timeout) {
+ /* Prepare to kick client */
+ usteer_roam_set_state(si, ROAM_TRIGGER_WAIT_KICK, &ev);
+ } else {
+ /* Kick in scan timeout */
+ si->roam_scan_timeout_start = current_time;
+ usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
+ }
break;
}
usteer_ubus_trigger_client_scan(si);
break;
}
usteer_ubus_trigger_client_scan(si);
- usteer_roam_set_state(si, ROAM_TRIGGER_SCAN, &ev);
+ usteer_roam_sm_start_scan(si, &ev);
break;
case ROAM_TRIGGER_IDLE:
break;
case ROAM_TRIGGER_IDLE:
- usteer_roam_set_state(si, ROAM_TRIGGER_SCAN, &ev);
+ usteer_roam_sm_start_scan(si, &ev);
break;
case ROAM_TRIGGER_SCAN_DONE:
/* Check for stale scan results, kick back to SCAN state if necessary */
if (current_time - si->roam_scan_done > 2 * config.roam_scan_interval) {
break;
case ROAM_TRIGGER_SCAN_DONE:
/* Check for stale scan results, kick back to SCAN state if necessary */
if (current_time - si->roam_scan_done > 2 * config.roam_scan_interval) {
- usteer_roam_set_state(si, ROAM_TRIGGER_SCAN, &ev);
+ usteer_roam_sm_start_scan(si, &ev);
_cfg(U32, roam_process_timeout), \
_cfg(I32, roam_scan_snr), \
_cfg(U32, roam_scan_tries), \
_cfg(U32, roam_process_timeout), \
_cfg(I32, roam_scan_snr), \
_cfg(U32, roam_scan_tries), \
+ _cfg(U32, roam_scan_timeout), \
_cfg(U32, roam_scan_interval), \
_cfg(I32, roam_trigger_snr), \
_cfg(U32, roam_trigger_interval), \
_cfg(U32, roam_scan_interval), \
_cfg(I32, roam_trigger_snr), \
_cfg(U32, roam_trigger_interval), \
uint32_t roam_process_timeout;
uint32_t roam_scan_tries;
uint32_t roam_process_timeout;
uint32_t roam_scan_tries;
+ uint32_t roam_scan_timeout;
uint32_t roam_scan_interval;
int32_t roam_trigger_snr;
uint32_t roam_scan_interval;
int32_t roam_trigger_snr;
uint64_t roam_event;
uint64_t roam_kick;
uint64_t roam_scan_done;
uint64_t roam_event;
uint64_t roam_kick;
uint64_t roam_scan_done;
+ uint64_t roam_scan_timeout_start;