[PATCH 2/2] Adjust the RSSI and throughput estimate in roaming algorithm

Kaidong Wang kaidong at chromium.org
Fri Sep 22 10:51:13 PDT 2023


The max transmit power of Standard Power (SP) Access Points (AP) in the
6 GHz band is limited by effective isotropic radiated power (EIRP),
while the max transmit power of Low Power Indoor (LPI) APs in the 6 GHz
band is limited by power spectral density (PSD). Therefore the max
transmit power of LPI APs grows as the channel width increases. However,
the roaming algorithm takes signal level as a constant value regardless
of the channel width.

Adjust the RSSI, SNR and throughput estimate based on max transmit power
config in roaming algorithm.

Signed-off-by: Kaidong Wang <kaidong at chromium.org>
---
 wpa_supplicant/events.c | 49 ++++++++++++++++++++++++++++++++---------
 wpa_supplicant/scan.c   | 45 ++++++++++++++++++++++++++++++-------
 2 files changed, 76 insertions(+), 18 deletions(-)

diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index b2a75a503..c50ba75f2 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1989,11 +1989,19 @@ int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
 {
 	int min_diff, diff;
 	int to_5ghz, to_6ghz;
-	int cur_level;
+	int cur_level, sel_level;
 	unsigned int cur_est, sel_est;
 	struct wpa_signal_info si;
-	int cur_snr = 0;
+	int cur_snr = 0, sel_snr = 0;
 	int ret = 0;
+	int rssi_bump = 0, noise_bump = 0;
+
+	const u8 *cur_ies = wpa_bss_ie_ptr(current_bss);
+	const u8 *sel_ies = wpa_bss_ie_ptr(selected);
+	size_t cur_ie_len = current_bss->ie_len ? current_bss->ie_len :
+			    current_bss->beacon_ie_len;
+	size_t sel_ie_len = selected->ie_len ? selected->ie_len :
+			    selected->beacon_ie_len;
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation");
 	wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR
@@ -2014,10 +2022,6 @@ int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
 		return 1;
 	}
 
-	cur_level = current_bss->level;
-	cur_est = current_bss->est_throughput;
-	sel_est = selected->est_throughput;
-
 	/*
 	 * Try to poll the signal from the driver since this will allow to get
 	 * more accurate values. In some cases, there can be big differences
@@ -2035,8 +2039,14 @@ int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
 	 */
 	if (wpa_drv_signal_poll(wpa_s, &si) == 0 &&
 	    (si.data.avg_beacon_signal || si.data.avg_signal)) {
+		/*
+		 * Normalize avg_signal to the RSSI over 20 MHz, as the
+		 * throughput is estimated based on the RSSI over 20 MHz
+		 */
 		cur_level = si.data.avg_beacon_signal ?
-			si.data.avg_beacon_signal : si.data.avg_signal;
+			    si.data.avg_beacon_signal : (si.data.avg_signal -
+			    wpas_channel_width_rssi_bump(cur_ies, cur_ie_len,
+							 si.chanwidth));
 		cur_snr = wpas_get_snr_signal_info(si.frequency, cur_level,
 						   si.current_noise);
 
@@ -2046,7 +2056,26 @@ int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
 		wpa_dbg(wpa_s, MSG_DEBUG,
 			"Using signal poll values for the current BSS: level=%d snr=%d est_throughput=%u",
 			cur_level, cur_snr, cur_est);
+	} else {
+		/* level and snr are measured over 20 MHz channel */
+		cur_level = current_bss->level;
+		cur_snr = current_bss->snr;
+		cur_est = current_bss->est_throughput;
 	}
+	/*
+	 * Adjust the SNR of BSSes based on the channel width.
+	 */
+	cur_level += wpas_channel_width_rssi_bump(cur_ies, cur_ie_len,
+						  current_bss->max_cw);
+	cur_snr = wpas_adjust_snr_by_chanwidth(cur_ies, cur_ie_len,
+					       current_bss->max_cw, cur_snr);
+
+	sel_est = selected->est_throughput;
+	sel_level = selected->level +
+		    wpas_channel_width_rssi_bump(sel_ies, sel_ie_len,
+						 selected->max_cw);
+	sel_snr = wpas_adjust_snr_by_chanwidth(sel_ies, sel_ie_len,
+					       selected->max_cw, selected->snr);
 
 	if (sel_est > cur_est + 5000) {
 		wpa_dbg(wpa_s, MSG_DEBUG,
@@ -2059,7 +2088,7 @@ int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
 		!is_6ghz_freq(current_bss->freq);
 
 	if (cur_level < 0 &&
-	    cur_level > selected->level + to_5ghz * 2 + to_6ghz * 2 &&
+	    cur_level > sel_level + to_5ghz * 2 + to_6ghz * 2 &&
 	    sel_est < cur_est * 1.2) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - Current BSS has better "
 			"signal level");
@@ -2113,7 +2142,7 @@ int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
 		min_diff -= 2;
 	if (to_6ghz)
 		min_diff -= 2;
-	diff = selected->level - cur_level;
+	diff = sel_level - cur_level;
 	if (diff < min_diff) {
 		wpa_dbg(wpa_s, MSG_DEBUG,
 			"Skip roam - too small difference in signal level (%d < %d)",
@@ -2132,7 +2161,7 @@ int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
 		     MAC2STR(current_bss->bssid),
 		     current_bss->freq, cur_level, cur_est,
 		     MAC2STR(selected->bssid),
-		     selected->freq, selected->level, sel_est);
+		     selected->freq, sel_level, sel_est);
 	return ret;
 }
 
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index c74709a9c..9806b7823 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -2756,6 +2756,12 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 	struct hostapd_hw_modes *hw_mode;
 	unsigned int est, tmp;
 	const u8 *ie;
+	/*
+	 * No need to apply a bump to the noise here because the
+	 * minsnr_bitrate_entry tables are based on MCS tables where this has
+	 * been taken into account.
+	 */
+	int adjusted_snr;
 
 	/* Limit based on estimated SNR */
 	if (rate > 1 * 2 && snr < 1)
@@ -2817,7 +2823,10 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 		if (ie && ie[1] >= 2 &&
 		    (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
 			*max_cw = CHAN_WIDTH_40;
-			tmp = max_ht40_rate(snr, false);
+			adjusted_snr = snr +
+				wpas_channel_width_rssi_bump(ies, ies_len,
+							     CHAN_WIDTH_40);
+			tmp = max_ht40_rate(adjusted_snr, false);
 			if (tmp > est)
 				est = tmp;
 		}
@@ -2839,7 +2848,10 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 			    (ie[3] &
 			     HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
 				*max_cw = CHAN_WIDTH_40;
-				tmp = max_ht40_rate(snr, true) + 1;
+				adjusted_snr = snr +
+					wpas_channel_width_rssi_bump(ies,
+							ies_len, CHAN_WIDTH_40);
+				tmp = max_ht40_rate(adjusted_snr, true) + 1;
 				if (tmp > est)
 					est = tmp;
 			}
@@ -2866,7 +2878,10 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 
 			if (vht80) {
 				*max_cw = CHAN_WIDTH_80;
-				tmp = max_vht80_rate(snr) + 1;
+				adjusted_snr = snr +
+					wpas_channel_width_rssi_bump(ies,
+							ies_len, CHAN_WIDTH_80);
+				tmp = max_vht80_rate(adjusted_snr) + 1;
 				if (tmp > est)
 					est = tmp;
 			}
@@ -2876,7 +2891,10 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 			     (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
 			      VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) {
 				*max_cw = CHAN_WIDTH_160;
-				tmp = max_vht160_rate(snr) + 1;
+				adjusted_snr = snr +
+					wpas_channel_width_rssi_bump(ies,
+						       ies_len, CHAN_WIDTH_160);
+				tmp = max_vht160_rate(adjusted_snr) + 1;
 				if (tmp > est)
 					est = tmp;
 			}
@@ -2923,7 +2941,10 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 			    *max_cw < CHAN_WIDTH_40) {
 				*max_cw = CHAN_WIDTH_40;
 			}
-			tmp = max_he_eht_rate(he40_table, snr, is_eht) + boost;
+			adjusted_snr = snr + wpas_channel_width_rssi_bump(ies,
+							ies_len, CHAN_WIDTH_40);
+			tmp = max_he_eht_rate(he40_table, adjusted_snr,
+					      is_eht) + boost;
 			if (tmp > est)
 				est = tmp;
 		}
@@ -2934,7 +2955,10 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 			    *max_cw < CHAN_WIDTH_80) {
 				*max_cw = CHAN_WIDTH_80;
 			}
-			tmp = max_he_eht_rate(he80_table, snr, is_eht) + boost;
+			adjusted_snr = snr + wpas_channel_width_rssi_bump(ies,
+							ies_len, CHAN_WIDTH_80);
+			tmp = max_he_eht_rate(he80_table, adjusted_snr,
+					      is_eht) + boost;
 			if (tmp > est)
 				est = tmp;
 		}
@@ -2946,7 +2970,10 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 			    *max_cw < CHAN_WIDTH_160) {
 				*max_cw = CHAN_WIDTH_160;
 			}
-			tmp = max_he_eht_rate(he160_table, snr, is_eht) + boost;
+			adjusted_snr = snr + wpas_channel_width_rssi_bump(ies,
+						       ies_len, CHAN_WIDTH_160);
+			tmp = max_he_eht_rate(he160_table, adjusted_snr,
+					      is_eht) + boost;
 			if (tmp > est)
 				est = tmp;
 		}
@@ -2963,7 +2990,9 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 			    *max_cw < CHAN_WIDTH_320) {
 				*max_cw = CHAN_WIDTH_320;
 			}
-			tmp = max_he_eht_rate(eht320_table, snr, true);
+			adjusted_snr = snr + wpas_channel_width_rssi_bump(ies,
+						       ies_len, CHAN_WIDTH_320);
+			tmp = max_he_eht_rate(eht320_table, adjusted_snr, true);
 			if (tmp > est)
 				est = tmp;
 		}
-- 
2.42.0.515.g380fc7ccd1-goog




More information about the Hostap mailing list