diff --git a/policy.c b/policy.c index 67c9c75..9d03b30 100644 --- a/policy.c +++ b/policy.c @@ -110,7 +110,7 @@ is_better_candidate(struct sta_info *si_cur, struct sta_info *si_new) } static struct sta_info * -find_better_candidate(struct sta_info *si_ref, struct uevent *ev, uint32_t required_criteria) +find_better_candidate(struct sta_info *si_ref, struct uevent *ev, uint32_t required_criteria, uint64_t max_age) { struct sta_info *si; struct sta *sta = si_ref->sta; @@ -126,6 +126,9 @@ find_better_candidate(struct sta_info *si_ref, struct uevent *ev, uint32_t requi if (strcmp(si->node->ssid, si_ref->node->ssid) != 0) continue; + if (max_age && max_age < current_time - si->seen) + continue; + reasons = is_better_candidate(si_ref, si); if (!reasons) continue; @@ -204,7 +207,7 @@ usteer_check_request(struct sta_info *si, enum usteer_event_type type) goto out; } - if (!find_better_candidate(si, &ev, UEV_SELECT_REASON_ALL)) + if (!find_better_candidate(si, &ev, UEV_SELECT_REASON_ALL, 0)) goto out; ev.reason = UEV_REASON_BETTER_CANDIDATE; @@ -283,7 +286,7 @@ usteer_roam_sm_start_scan(struct sta_info *si, struct uevent *ev) } /* We are currently in scan timeout / cooldown. - * Check if we are in ROAM_TRIGGER_IDLE state and enter this stateif not. + * Check if we are in ROAM_TRIGGER_IDLE state. Enter this state if not. */ if (si->roam_state == ROAM_TRIGGER_IDLE) return; @@ -292,27 +295,47 @@ usteer_roam_sm_start_scan(struct sta_info *si, struct uevent *ev) usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, ev); } +static bool +usteer_roam_sm_found_better_node(struct sta_info *si, struct uevent *ev, enum roam_trigger_state next_state) +{ + uint64_t max_age = 2 * config.roam_scan_interval; + + if (max_age > current_time - si->roam_scan_start) + max_age = current_time - si->roam_scan_start; + + if (find_better_candidate(si, ev, (1 << UEV_SELECT_REASON_SIGNAL), max_age)) { + usteer_roam_set_state(si, next_state, ev); + return true; + } + + return false; +} + static bool usteer_roam_trigger_sm(struct sta_info *si) { struct uevent ev = { .si_cur = si, }; - int min_signal; + uint64_t min_signal; min_signal = usteer_snr_to_signal(si->node, config.roam_trigger_snr); switch (si->roam_state) { case ROAM_TRIGGER_SCAN: + if (!si->roam_tries) { + si->roam_scan_start = current_time; + } + + /* Check if we've found a better node regardless of the scan-interval */ + if (usteer_roam_sm_found_better_node(si, &ev, ROAM_TRIGGER_SCAN_DONE)) + break; + + /* Only scan every scan-interval */ if (current_time - si->roam_event < config.roam_scan_interval) break; - if (find_better_candidate(si, &ev, (1 << UEV_SELECT_REASON_SIGNAL)) || - si->roam_scan_done > si->roam_event) { - usteer_roam_set_state(si, ROAM_TRIGGER_SCAN_DONE, &ev); - break; - } - + /* Check if no node was found within roam_scan_tries tries */ if (config.roam_scan_tries && si->roam_tries >= config.roam_scan_tries) { if (!config.roam_scan_timeout) { /* Prepare to kick client */ @@ -325,29 +348,21 @@ usteer_roam_trigger_sm(struct sta_info *si) break; } + /* Send beacon-request to client */ usteer_ubus_trigger_client_scan(si); usteer_roam_sm_start_scan(si, &ev); break; case ROAM_TRIGGER_IDLE: - if (find_better_candidate(si, &ev, (1 << UEV_SELECT_REASON_SIGNAL))) { - usteer_roam_set_state(si, ROAM_TRIGGER_SCAN_DONE, &ev); - break; - } - 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) { - usteer_roam_sm_start_scan(si, &ev); + if (usteer_roam_sm_found_better_node(si, &ev, ROAM_TRIGGER_WAIT_KICK)) break; - } - - if (find_better_candidate(si, &ev, (1 << UEV_SELECT_REASON_SIGNAL))) - usteer_roam_set_state(si, ROAM_TRIGGER_WAIT_KICK, &ev); + /* Kick back to SCAN state if candidate expired */ + usteer_roam_sm_start_scan(si, &ev); break; case ROAM_TRIGGER_WAIT_KICK: @@ -495,7 +510,7 @@ usteer_local_node_kick(struct usteer_local_node *ln) if (is_more_kickable(kick1, si)) kick1 = si; - tmp = find_better_candidate(si, NULL, (1 << UEV_SELECT_REASON_LOAD)); + tmp = find_better_candidate(si, NULL, (1 << UEV_SELECT_REASON_LOAD), 0); if (!tmp) continue; diff --git a/sta.c b/sta.c index 0ec6a8a..2868a67 100644 --- a/sta.c +++ b/sta.c @@ -186,7 +186,6 @@ usteer_handle_sta_event(struct usteer_node *node, const uint8_t *addr, si = usteer_sta_info_get(sta, node, &create); usteer_sta_info_update(si, signal, false); - si->roam_scan_done = current_time; si->stats[type].requests++; diff = si->stats[type].blocked_last_time - current_time; diff --git a/usteer.h b/usteer.h index 280fdb2..f47f53e 100644 --- a/usteer.h +++ b/usteer.h @@ -229,7 +229,7 @@ struct sta_info { uint8_t roam_tries; uint64_t roam_event; uint64_t roam_kick; - uint64_t roam_scan_done; + uint64_t roam_scan_start; uint64_t roam_scan_timeout_start; int kick_count;