Check local supported features for estimating BSS throughputs accurately

Add checks for features supported by the specific hardware mode of the
local device that has the channel for which the throughput is being
estimated instead of assuming the local device supports all optional
features. This is more accurate for cases where the local capabilities
might differ based on the band. In addition, this is in preparation for
extending rate estimates to cover optional VHT and HE features.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Vamsi Krishna 2021-05-05 00:45:30 +05:30 committed by Jouni Malinen
parent 3cefdf0d4a
commit 1d2118b509
5 changed files with 30 additions and 8 deletions

View file

@ -1853,7 +1853,7 @@ wpas_get_est_throughput_from_bss_snr(const struct wpa_supplicant *wpa_s,
const u8 *ies = wpa_bss_ie_ptr(bss); const u8 *ies = wpa_bss_ie_ptr(bss);
size_t ie_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; size_t ie_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
return wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr); return wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr, bss->freq);
} }

View file

@ -2322,9 +2322,9 @@ static unsigned int max_vht80_rate(int snr)
unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
const u8 *ies, size_t ies_len, int rate, const u8 *ies, size_t ies_len, int rate,
int snr) int snr, int freq)
{ {
enum local_hw_capab capab = wpa_s->hw_capab; struct hostapd_hw_modes *hw_mode;
unsigned int est, tmp; unsigned int est, tmp;
const u8 *ie; const u8 *ie;
@ -2369,7 +2369,10 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
rate = 54 * 2; rate = 54 * 2;
est = rate * 500; est = rate * 500;
if (capab == CAPAB_HT || capab == CAPAB_HT40 || capab == CAPAB_VHT) { hw_mode = get_mode_with_freq(wpa_s->hw.modes, wpa_s->hw.num_modes,
freq);
if (hw_mode && hw_mode->ht_capab) {
ie = get_ie(ies, ies_len, WLAN_EID_HT_CAP); ie = get_ie(ies, ies_len, WLAN_EID_HT_CAP);
if (ie) { if (ie) {
tmp = max_ht20_rate(snr, false); tmp = max_ht20_rate(snr, false);
@ -2378,7 +2381,8 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
} }
} }
if (capab == CAPAB_HT40 || capab == CAPAB_VHT) { if (hw_mode &&
(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION); ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
if (ie && ie[1] >= 2 && if (ie && ie[1] >= 2 &&
(ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) { (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
@ -2388,7 +2392,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
} }
} }
if (capab == CAPAB_VHT) { if (hw_mode && hw_mode->vht_capab) {
/* Use +1 to assume VHT is always faster than HT */ /* Use +1 to assume VHT is always faster than HT */
ie = get_ie(ies, ies_len, WLAN_EID_VHT_CAP); ie = get_ie(ies, ies_len, WLAN_EID_VHT_CAP);
if (ie) { if (ie) {
@ -2436,7 +2440,7 @@ void scan_est_throughput(struct wpa_supplicant *wpa_s,
if (!ie_len) if (!ie_len)
ie_len = res->beacon_ie_len; ie_len = res->beacon_ie_len;
res->est_throughput = res->est_throughput =
wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr); wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr, res->freq);
/* TODO: channel utilization and AP load (e.g., from AP Beacon) */ /* TODO: channel utilization and AP load (e.g., from AP Beacon) */
} }

View file

@ -84,7 +84,7 @@ void scan_est_throughput(struct wpa_supplicant *wpa_s,
struct wpa_scan_res *res); struct wpa_scan_res *res);
unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
const u8 *ies, size_t ies_len, int rate, const u8 *ies, size_t ies_len, int rate,
int snr); int snr, int freq);
void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s); void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s);
int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s, int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s,
enum hostapd_hw_mode band, enum hostapd_hw_mode band,

View file

@ -8111,6 +8111,22 @@ struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
} }
struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
u16 num_modes, int freq)
{
int i, j;
for (i = 0; i < num_modes; i++) {
for (j = 0; j < modes[i].num_channels; j++) {
if (freq == modes[i].channels[j].freq)
return &modes[i];
}
}
return NULL;
}
static struct static struct
wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s, wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
const u8 *bssid) const u8 *bssid)

View file

@ -1701,6 +1701,8 @@ int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd);
struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
u16 num_modes, enum hostapd_hw_mode mode, u16 num_modes, enum hostapd_hw_mode mode,
bool is_6ghz); bool is_6ghz);
struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
u16 num_modes, int freq);
void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid, void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
unsigned int sec, int rssi_threshold); unsigned int sec, int rssi_threshold);