policy: only send preferred candidate with transition request
authorDavid Bauer <mail@david-bauer.net>
Wed, 4 May 2022 22:33:52 +0000 (00:33 +0200)
committerDavid Bauer <mail@david-bauer.net>
Thu, 5 May 2022 21:39:42 +0000 (23:39 +0200)
Only send the preferred candidate with a BSS transition request.
Otherwise, unsuitable candidates might be included in the neighbor-list
of a transition request.

Signed-off-by: David Bauer <mail@david-bauer.net>
local_node.c
policy.c
ubus.c
usteer.h

index 8fb2485a84b0b0157e0f8cf755eb0aec0ea9392a..c79fd95b68281d7255e29a38d619052324a81b40 100644 (file)
@@ -736,7 +736,7 @@ usteer_local_node_process_bss_tm_queries(struct uloop_timeout *timeout)
                if (!si)
                        continue;
 
-               usteer_ubus_bss_transition_request(si, query->dialog_token, false, false, validity_period);
+               usteer_ubus_bss_transition_request(si, query->dialog_token, false, false, validity_period, NULL);
        }
 
        /* Free pending queries we can not handle */
index 6399a7820f426efd8d0e7e00f13bb0e9c85f2ad2..7d3b14f65166dfddf1f13c46180f2f5950d1b106 100644 (file)
--- a/policy.c
+++ b/policy.c
@@ -114,7 +114,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, uint64_t max_age)
 {
-       struct sta_info *si;
+       struct sta_info *si, *candidate = NULL;
        struct sta *sta = si_ref->sta;
        uint32_t reasons;
 
@@ -143,10 +143,11 @@ find_better_candidate(struct sta_info *si_ref, struct uevent *ev, uint32_t requi
                        ev->select_reasons = reasons;
                }
 
-               return si;
+               if (candidate && si->signal > candidate->signal)
+                       candidate = si;
        }
 
-       return NULL;
+       return candidate;
 }
 
 int
@@ -297,25 +298,26 @@ usteer_roam_sm_start_scan(struct sta_info *si, struct uevent *ev)
        usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, ev);
 }
 
-static bool
+static struct sta_info *
 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;
+       struct sta_info *candidate;
 
        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)) {
+       candidate = find_better_candidate(si, ev, (1 << UEV_SELECT_REASON_SIGNAL), max_age);
+       if (candidate)
                usteer_roam_set_state(si, next_state, ev);
-               return true;
-       }
 
-       return false;
+       return candidate;
 }
 
 static bool
 usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si)
 {
+       struct sta_info *candidate;
        struct uevent ev = {
                .si_cur = si,
        };
@@ -357,7 +359,12 @@ usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si)
                break;
 
        case ROAM_TRIGGER_SCAN_DONE:
-               usteer_ubus_bss_transition_request(si, 1, false, false, 100);
+               candidate = usteer_roam_sm_found_better_node(si, &ev, ROAM_TRIGGER_SCAN_DONE);
+               /* Kick back in case no better node is found */
+               if (!candidate)
+                       usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
+
+               usteer_ubus_bss_transition_request(si, 1, false, false, 100, candidate->node);
                si->kick_time = current_time;
                usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
                break;
diff --git a/ubus.c b/ubus.c
index 19ab4b3efc7a0685d697dcef0348df65e0141cee..7b8472370fc221bfc9bf3dc27df701168139deb5 100644 (file)
--- a/ubus.c
+++ b/ubus.c
@@ -611,6 +611,16 @@ usteer_add_nr_entry(struct usteer_node *ln, struct usteer_node *node)
        return true;
 }
 
+static void
+usteer_ubus_disassoc_add_neighbor(struct sta_info *si, struct usteer_node *node)
+{
+       void *c;
+
+       c = blobmsg_open_array(&b, "neighbors");
+       usteer_add_nr_entry(si->node, node);
+       blobmsg_close_array(&b, c);
+}
+
 static void
 usteer_ubus_disassoc_add_neighbors(struct sta_info *si)
 {
@@ -646,7 +656,8 @@ int usteer_ubus_bss_transition_request(struct sta_info *si,
                                       uint8_t dialog_token,
                                       bool disassoc_imminent,
                                       bool abridged,
-                                      uint8_t validity_period)
+                                      uint8_t validity_period,
+                                      struct usteer_node *target_node)
 {
        struct usteer_local_node *ln = container_of(si->node, struct usteer_local_node, node);
 
@@ -656,7 +667,11 @@ int usteer_ubus_bss_transition_request(struct sta_info *si,
        blobmsg_add_u8(&b, "disassociation_imminent", disassoc_imminent);
        blobmsg_add_u8(&b, "abridged", abridged);
        blobmsg_add_u32(&b, "validity_period", validity_period);
-       usteer_ubus_disassoc_add_neighbors(si);
+       if (!target_node) {
+               usteer_ubus_disassoc_add_neighbors(si);
+       } else {
+               usteer_ubus_disassoc_add_neighbor(si, target_node);
+       }
        return ubus_invoke(ubus_ctx, ln->obj_id, "bss_transition_request", b.head, NULL, 0, 100);
 }
 
index ec4e2191182f56d5e78b9da96c85e2ffb71361fc..1c3c28f5c8b02144c36fc17f1bc279b86728c195 100644 (file)
--- a/usteer.h
+++ b/usteer.h
@@ -336,7 +336,8 @@ int usteer_ubus_bss_transition_request(struct sta_info *si,
                                       uint8_t dialog_token,
                                       bool disassoc_imminent,
                                       bool abridged,
-                                      uint8_t validity_period);
+                                      uint8_t validity_period,
+                                      struct usteer_node *target_node);
 
 struct sta *usteer_sta_get(const uint8_t *addr, bool create);
 struct sta_info *usteer_sta_info_get(struct sta *sta, struct usteer_node *node, bool *create);