From 648c6f3bc3730b5e437212d5c02b9adcf818597a Mon Sep 17 00:00:00 2001 From: David Bauer Date: Wed, 23 Feb 2022 23:34:12 +0100 Subject: [PATCH] policy: make roam-steers client-rejectable While usteer tries it's best to determine the availability of a better node for a certain client, it might still attempt to direct the client to a unsuitable AP. Transition away from using BSS-Transition-Requests with the disassoc-imminent bit set and instead unset this bit. This way, the client can inform the AP it will not transition to a different BSS but instead wishes to remain connected to the current AP. usteer will still kick clients in case they either accepted the BSS-transition-request and do not roam or ignore the request completely. Signed-off-by: David Bauer --- local_node.c | 5 +++++ policy.c | 50 +++++++++++++++++++++----------------------------- sta.c | 1 + usteer.h | 5 ++--- 4 files changed, 29 insertions(+), 32 deletions(-) diff --git a/local_node.c b/local_node.c index 9961f95..92c2dcb 100644 --- a/local_node.c +++ b/local_node.c @@ -180,6 +180,11 @@ usteer_handle_bss_tm_response(struct usteer_local_node *ln, struct blob_attr *ms si->bss_transition_response.status_code = blobmsg_get_u8(tb[BSS_TM_RESPONSE_STATUS_CODE]); si->bss_transition_response.timestamp = current_time; + if (si->bss_transition_response.status_code) { + /* Cancel imminent kick in case BSS transition was rejected */ + si->kick_time = 0; + } + return 0; } diff --git a/policy.c b/policy.c index 1481dd5..b99a361 100644 --- a/policy.c +++ b/policy.c @@ -314,14 +314,11 @@ usteer_roam_sm_found_better_node(struct sta_info *si, struct uevent *ev, enum ro } static bool -usteer_roam_trigger_sm(struct sta_info *si) +usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si) { struct uevent ev = { .si_cur = si, }; - uint64_t min_signal; - - min_signal = usteer_snr_to_signal(si->node, config.roam_trigger_snr); switch (si->roam_state) { case ROAM_TRIGGER_SCAN: @@ -341,7 +338,7 @@ usteer_roam_trigger_sm(struct sta_info *si) 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); + usteer_roam_set_state(si, ROAM_TRIGGER_SCAN_DONE, &ev); } else { /* Kick in scan timeout */ si->roam_scan_timeout_start = current_time; @@ -360,30 +357,10 @@ usteer_roam_trigger_sm(struct sta_info *si) break; case ROAM_TRIGGER_SCAN_DONE: - if (usteer_roam_sm_found_better_node(si, &ev, ROAM_TRIGGER_WAIT_KICK)) - break; - - /* Kick back to SCAN state if candidate expired */ - usteer_roam_sm_start_scan(si, &ev); - break; - - case ROAM_TRIGGER_WAIT_KICK: - if (si->signal > min_signal) - break; - - usteer_roam_set_state(si, ROAM_TRIGGER_NOTIFY_KICK, &ev); - usteer_ubus_notify_client_disassoc(si); - break; - case ROAM_TRIGGER_NOTIFY_KICK: - if (current_time - si->roam_event < config.roam_kick_delay * 100) - break; - - usteer_roam_set_state(si, ROAM_TRIGGER_KICK, &ev); - break; - case ROAM_TRIGGER_KICK: - usteer_ubus_kick_client(si); + usteer_ubus_bss_transition_request(si, 1, false, false, 100); + si->kick_time = current_time; usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev); - return true; + break; } return false; @@ -407,6 +384,7 @@ usteer_local_node_roam_check(struct usteer_local_node *ln, struct uevent *ev) list_for_each_entry(si, &ln->node.sta_info, node_list) { if (si->connected != STA_CONNECTED || si->signal >= min_signal || + si->kick_time || current_time - si->roam_kick < config.roam_trigger_interval) { usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, ev); continue; @@ -416,7 +394,7 @@ usteer_local_node_roam_check(struct usteer_local_node *ln, struct uevent *ev) * If the state machine kicked a client, other clients should wait * until the next turn */ - if (usteer_roam_trigger_sm(si)) + if (usteer_roam_trigger_sm(ln, si)) return; } } @@ -548,6 +526,18 @@ out: usteer_event(&ev); } +static void +usteer_local_node_perform_kick(struct usteer_local_node *ln) +{ + struct sta_info *si; + + list_for_each_entry(si, &ln->node.sta_info, node_list) { + if (!si->kick_time || si->kick_time > current_time) + continue; + + usteer_ubus_kick_client(si); + } +} void usteer_local_node_kick(struct usteer_local_node *ln) @@ -556,6 +546,8 @@ usteer_local_node_kick(struct usteer_local_node *ln) .node_local = &ln->node, }; + usteer_local_node_perform_kick(ln); + usteer_local_node_snr_kick(ln); usteer_local_node_load_kick(ln); usteer_local_node_roam_check(ln, &ev); diff --git a/sta.c b/sta.c index 9934ccf..53f203a 100644 --- a/sta.c +++ b/sta.c @@ -149,6 +149,7 @@ usteer_sta_get(const uint8_t *addr, bool create) void usteer_sta_disconnected(struct sta_info *si) { si->connected = STA_NOT_CONNECTED; + si->kick_time = 0; usteer_sta_info_update_timeout(si, config.local_sta_timeout); } diff --git a/usteer.h b/usteer.h index 49c3651..6a58659 100644 --- a/usteer.h +++ b/usteer.h @@ -219,9 +219,6 @@ enum roam_trigger_state { ROAM_TRIGGER_IDLE, ROAM_TRIGGER_SCAN, ROAM_TRIGGER_SCAN_DONE, - ROAM_TRIGGER_WAIT_KICK, - ROAM_TRIGGER_NOTIFY_KICK, - ROAM_TRIGGER_KICK, }; struct sta_info { @@ -254,6 +251,8 @@ struct sta_info { uint64_t timestamp; } bss_transition_response; + uint64_t kick_time; + int kick_count; uint32_t below_min_snr; -- 2.30.2