From 77386f51acaa3a4bddf536474aada86a50838eae Mon Sep 17 00:00:00 2001 From: Kaidong Wang Date: Wed, 8 Nov 2023 03:58:06 +0000 Subject: [PATCH] Adjust the RSSI and throughput estimate in roaming algorithm The max transmit power of Standard Power (SP) Access Points (AP) on 6 GHz band and APs on 2.4 GHz and 5 GHz bands is limited by effective isotropic radiated power (EIRP), while the max transmit power of Low Power Indoor (LPI) APs on 6 GHz Band is limited by power spectral density (PSD). Therefore the max transmit power of LPI APs grows as the channel width increases, similar to the noise power which has constant PSD. Adjust the RSSI, SNR and throughput estimate based on max transmit power config and max channel width in the roaming algorithm. Signed-off-by: Kaidong Wang --- wpa_supplicant/events.c | 43 ++++++++++++++++++++++++++++++--------- wpa_supplicant/scan.c | 45 +++++++++++++++++++++++++++++++++-------- 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index ece582875..aa5c9b058 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2071,11 +2071,17 @@ 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 ret = 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 @@ -2096,10 +2102,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 @@ -2117,8 +2119,15 @@ 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); @@ -2128,8 +2137,24 @@ 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); + if (sel_est > cur_est + 5000) { wpa_dbg(wpa_s, MSG_DEBUG, "Allow reassociation - selected BSS has better estimated throughput"); @@ -2141,7 +2166,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"); @@ -2195,7 +2220,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)", @@ -2214,7 +2239,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 cc0ec7fff..bab6a23c0 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -2872,6 +2872,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) @@ -2933,7 +2939,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; } @@ -2956,7 +2965,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; } @@ -2983,7 +2995,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; } @@ -2993,7 +3008,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; } @@ -3040,7 +3058,10 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, if (*max_cw == CHAN_WIDTH_UNKNOWN || *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; } @@ -3050,7 +3071,10 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, if (*max_cw == CHAN_WIDTH_UNKNOWN || *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; } @@ -3061,7 +3085,10 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, if (*max_cw == CHAN_WIDTH_UNKNOWN || *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; } @@ -3077,7 +3104,9 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, if (*max_cw == CHAN_WIDTH_UNKNOWN || *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; }