[PATCH v3 3/3] WNM: Use standard BSS selection and enable abridged bit handling

Benjamin Berg benjamin at sipsolutions.net
Thu Sep 19 03:19:17 PDT 2024


From: Benjamin Berg <benjamin.berg at intel.com>

Most of the logic to reject BSSs during transition has been moved into
wnm_is_bss_excluded. In addition to this, since commit 67bf89f55442
("WNM: Choose the best available BSS, not just the first one") we will
simply choose the BSS with the best throughput.

Overall, this matches the behaviour that the supplicant will use anyway
in wpa_supplicant_select_bss. The only bigger difference is that using
this will check all known BSSs instead of only the ones in the candidate
list. This means that with this change the abridged bit is handled
according to spec.

There are some subtle changes to the logic. Once is, that candidates
with a very low signal level are not explicitly dropped anymore.
However, that code pre-dates the logic to prefer the best BSS and should
not be relevant anymore.

Another small adjustment is to change the custom logic to avoid roaming
when it is not needed to use wpa_supplicant_need_to_roam_within_ess.

Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>

---

v3: Apply normal roaming rules, to fix the issue found by Ben Greear
Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>
---
 wpa_supplicant/events.c           |   2 +-
 wpa_supplicant/wnm_sta.c          | 137 +++++-------------------------
 wpa_supplicant/wpa_supplicant_i.h |   5 ++
 3 files changed, 26 insertions(+), 118 deletions(-)

diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 668068167f..8e43db3e41 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1733,7 +1733,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
 }
 
 
-static struct wpa_bss *
+struct wpa_bss *
 wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
 			  struct wpa_ssid *group,
 			  struct wpa_ssid **selected_ssid,
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index dcef8053ee..0ee47c2b4b 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -687,117 +687,6 @@ end:
 }
 
 
-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,
-			      enum mbo_transition_reject_reason *reason)
-{
-	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;
-
-	wpa_printf(MSG_DEBUG, "WNM: Current BSS " MACSTR " RSSI %d",
-		   MAC2STR(wpa_s->bssid), bss->level);
-
-	for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
-		struct neighbor_report *nei;
-
-		nei = &wpa_s->wnm_neighbor_report_elements[i];
-
-		target = wpa_bss_get_bssid(wpa_s, nei->bssid);
-		if (!target) {
-			wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
-				   " (pref %d) not found in scan results",
-				   MAC2STR(nei->bssid),
-				   nei->preference_present ? nei->preference :
-				   -1);
-			continue;
-		}
-
-		/*
-		 * TODO: Could consider allowing transition to another ESS if
-		 * PMF was enabled for the association.
-		 */
-		if (!wpa_scan_res_match(wpa_s, 0, target, wpa_s->current_ssid,
-					1, 0)) {
-			wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
-				   " (pref %d) does not match the current network profile",
-				   MAC2STR(nei->bssid),
-				   nei->preference_present ? nei->preference :
-				   -1);
-			continue;
-		}
-
-		if (target->level < bss->level && target->level < -80) {
-			wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
-				   " (pref %d) does not have sufficient signal level (%d)",
-				   MAC2STR(nei->bssid),
-				   nei->preference_present ? nei->preference :
-				   -1,
-				   target->level);
-			continue;
-		}
-
-		best_target = find_better_target(target, best_target);
-		if (target == bss)
-			bss_in_list = bss;
-	}
-
-	target = best_target;
-
-	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;
-	}
-
-	wpa_printf(MSG_DEBUG,
-		   "WNM: Stay with our current BSS, not enough change in estimated throughput to switch");
-	return bss_in_list;
-}
-
-
 static int wpa_bss_ies_eq(struct wpa_bss *a, struct wpa_bss *b, u8 eid)
 {
 	const u8 *ie_a, *ie_b;
@@ -1115,11 +1004,12 @@ static void wnm_bss_tm_connect(struct wpa_supplicant *wpa_s,
 
 int wnm_scan_process(struct wpa_supplicant *wpa_s, bool pre_scan_check)
 {
-	struct wpa_bss *bss;
+	struct wpa_bss *bss, *current_bss = wpa_s->current_bss;
 	struct wpa_ssid *ssid = wpa_s->current_ssid;
 	enum bss_trans_mgmt_status_code status = WNM_BSS_TM_REJECT_UNSPECIFIED;
 	enum mbo_transition_reject_reason reason =
 		MBO_TRANSITION_REJECT_REASON_UNSPECIFIED;
+	struct wpa_ssid *selected_ssid = NULL;
 
 	if (!wpa_s->wnm_dialog_token)
 		return 0;
@@ -1143,7 +1033,7 @@ int wnm_scan_process(struct wpa_supplicant *wpa_s, bool pre_scan_check)
 	fetch_drv_mbo_candidate_info(wpa_s, &reason);
 
 	/* Compare the Neighbor Report and scan results */
-	bss = compare_scan_neighbor_results(wpa_s, &reason);
+	bss = wpa_supplicant_select_bss(wpa_s, ssid, &selected_ssid, 1);
 #ifdef CONFIG_MBO
 	if (!bss && wpa_s->wnm_mbo_trans_reason_present &&
 	    wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
@@ -1169,7 +1059,7 @@ int wnm_scan_process(struct wpa_supplicant *wpa_s, bool pre_scan_check)
 				nei->drv_mbo_reject = 0;
 		}
 
-		bss = compare_scan_neighbor_results(wpa_s, &reason);
+		bss = wpa_supplicant_select_bss(wpa_s, ssid, &selected_ssid, 1);
 	}
 #endif /* CONFIG_MBO */
 
@@ -1194,20 +1084,33 @@ int wnm_scan_process(struct wpa_supplicant *wpa_s, bool pre_scan_check)
 			return 0;
 
 #ifndef CONFIG_NO_ROAMING
-		if (wpa_s->current_bss && bss != wpa_s->current_bss &&
+		if (current_bss && bss != current_bss &&
 		    wpa_supplicant_need_to_roam_within_ess(wpa_s, bss,
-							   wpa_s->current_bss,
-							   false))
+							   current_bss, false))
 			return 0;
 #endif /* CONFIG_NO_ROAMING */
 	}
 
+	/* Apply normal roaming rules if we can stay with the current BSS */
+	if (current_bss && bss != current_bss &&
+	    wpa_scan_res_match(wpa_s, 0, current_bss, wpa_s->current_ssid,
+			       1, 0) &&
+	    !wpa_supplicant_need_to_roam_within_ess(wpa_s, current_bss, bss,
+						    true))
+		bss = current_bss;
+
 	if (!bss) {
 		wpa_printf(MSG_DEBUG, "WNM: No BSS transition candidate match found");
 		status = WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES;
 		goto send_bss_resp_fail;
 	}
 
+	wpa_printf(MSG_DEBUG,
+		   "WNM: Found an acceptable preferred transition candidate BSS "
+		   MACSTR " (RSSI %d, tput: %d  bss-tput: %d)",
+		   MAC2STR(bss->bssid), bss->level, bss->est_throughput,
+		   current_bss ? current_bss->est_throughput : -1);
+
 	/* Associate to the network */
 	wnm_bss_tm_connect(wpa_s, bss, ssid, 1);
 	return 1;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 7c51cdb20e..0bd4fcdedd 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1965,6 +1965,11 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
 				     struct wpa_ssid *group,
 				     int only_first_ssid, int debug_print);
 
+struct wpa_bss * wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
+					   struct wpa_ssid *group,
+					   struct wpa_ssid **selected_ssid,
+					   int only_first_ssid);
+
 int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
 						enum wpa_driver_if_type if_type,
 						unsigned int *num,
-- 
2.46.0




More information about the Hostap mailing list