policy: make roam-steers client-rejectable
authorDavid Bauer <mail@david-bauer.net>
Wed, 23 Feb 2022 22:34:12 +0000 (23:34 +0100)
committerDavid Bauer <mail@david-bauer.net>
Fri, 18 Mar 2022 20:42:33 +0000 (21:42 +0100)
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 <mail@david-bauer.net>
local_node.c
policy.c
sta.c
usteer.h

index 9961f95e64abd8aa2bc5723c598903e29b42518a..92c2dcbddd31f92aeb10038e1157c63dba6275f3 100644 (file)
@@ -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;
 }
 
index 1481dd51d31e87c920c8aa09881259e3a98986f2..b99a361fae94930529711729e745359a5490f95b 100644 (file)
--- 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 9934ccfeedd8f9dc8387e95838d188192960f42d..53f203af6bc8a6fabc69a7e27e5d84e2d1acc2b1 100644 (file)
--- 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);
 }
 
index 49c3651a2fe9092bb0b46f6d6d05ce67233edb1c..6a58659221bb46a1e2809b27ead985ab81494c4e 100644 (file)
--- 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;