]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WNM: Choose the best available BSS, not just the first one
authorBen Greear <greearb@candelatech.com>
Thu, 27 Jul 2023 16:02:11 +0000 (09:02 -0700)
committerJouni Malinen <j@w1.fi>
Sat, 28 Oct 2023 16:54:41 +0000 (19:54 +0300)
This should allow STA to make better choice about which BSS to roam to.

Use estimated throughput as comparison value. Can improve the estimated
throughput calculation to improve this selection criteria if wanted in
the future.

Signed-off-by: Ben Greear <greearb@candelatech.com>
wpa_supplicant/wnm_sta.c

index 5b3de30d5ecadc3e9949f4339d15277689522ce0..89b7ae0bd40db6123baf26109f88d1c6f4d653f3 100644 (file)
@@ -614,22 +614,6 @@ static void wnm_clear_acceptable(struct wpa_supplicant *wpa_s)
                wpa_s->wnm_neighbor_report_elements[i].acceptable = 0;
 }
 
-
-static struct wpa_bss * get_first_acceptable(struct wpa_supplicant *wpa_s)
-{
-       unsigned int i;
-       struct neighbor_report *nei;
-
-       for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
-               nei = &wpa_s->wnm_neighbor_report_elements[i];
-               if (nei->acceptable)
-                       return wpa_bss_get_bssid(wpa_s, nei->bssid);
-       }
-
-       return NULL;
-}
-
-
 #ifdef CONFIG_MBO
 static struct wpa_bss *
 get_mbo_transition_candidate(struct wpa_supplicant *wpa_s,
@@ -724,6 +708,29 @@ end:
 #endif /* CONFIG_MBO */
 
 
+static struct wpa_bss * find_better_target(struct wpa_bss *a,
+                                          struct wpa_bss *b)
+{
+       if (!a)
+               return b;
+       if (!b)
+               return a;
+
+       if (a->est_throughput > b->est_throughput) {
+               wpa_printf(MSG_DEBUG, "WNM: A is better: " MACSTR
+                          " est-tput: %d  B: " MACSTR " est-tput: %d",
+                          MAC2STR(a->bssid), a->est_throughput,
+                          MAC2STR(b->bssid), b->est_throughput);
+               return a;
+       }
+
+       wpa_printf(MSG_DEBUG, "WNM: B is better, A: " MACSTR
+                  " est-tput: %d  B: " MACSTR " est-tput: %d",
+                  MAC2STR(a->bssid), a->est_throughput,
+                  MAC2STR(b->bssid), b->est_throughput);
+       return b;
+}
+
 static struct wpa_bss *
 compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs,
                              enum mbo_transition_reject_reason *reason)
@@ -731,6 +738,8 @@ compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs,
        u8 i;
        struct wpa_bss *bss = wpa_s->current_bss;
        struct wpa_bss *target;
+       struct wpa_bss *best_target = NULL;
+       struct wpa_bss *bss_in_list = NULL;
 
        if (!bss)
                return NULL;
@@ -817,25 +826,44 @@ compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs,
                }
 
                nei->acceptable = 1;
+
+               best_target = find_better_target(target, best_target);
+               if (target == bss)
+                       bss_in_list = bss;
        }
 
 #ifdef CONFIG_MBO
        if (wpa_s->wnm_mbo_trans_reason_present)
                target = get_mbo_transition_candidate(wpa_s, reason);
        else
-               target = get_first_acceptable(wpa_s);
+               target = best_target;
 #else /* CONFIG_MBO */
-       target = get_first_acceptable(wpa_s);
+       target = best_target;
 #endif /* CONFIG_MBO */
 
-       if (target) {
-               wpa_printf(MSG_DEBUG,
-                          "WNM: Found an acceptable preferred transition candidate BSS "
-                          MACSTR " (RSSI %d)",
-                          MAC2STR(target->bssid), target->level);
+       if (!target)
+               return NULL;
+
+       wpa_printf(MSG_DEBUG,
+                  "WNM: Found an acceptable preferred transition candidate BSS "
+                  MACSTR " (RSSI %d, tput: %d  bss-tput: %d)",
+                  MAC2STR(target->bssid), target->level,
+                  target->est_throughput, bss->est_throughput);
+
+       if (!bss_in_list)
+               return target;
+
+       if ((!target->est_throughput && !bss_in_list->est_throughput) ||
+           (target->est_throughput > bss_in_list->est_throughput &&
+            target->est_throughput - bss_in_list->est_throughput >
+            bss_in_list->est_throughput >> 4)) {
+               /* It is more than 100/16 percent better, so switch. */
+               return target;
        }
 
-       return target;
+       wpa_printf(MSG_DEBUG,
+                  "WNM: Stay with our current BSS, not enough change in estimated throughput to switch");
+       return bss_in_list;
 }