wpa_supplicant: Support throughput estimation for EHT rates

Add support to consider EHT rates while calculating the estimated
throughput for scan results.

- The estimated EHT throughput uses the HE 0.8 usec GI rates from the
  relevant EHT-MCS tables from IEEE P802.11be/D2.0, 36.5.
- The minimum SNR values for EHT rates (4096-QAM) are derived by adding
  the existing minimum SNR values of 1024-QAM rates from HE tables and
  the difference between the values of minimum sensitivity levels of
  1024-QAM rates and 4096-QAM rates defined in Table 36-67 (Receiver
  minimum input level sensitivity) in IEEE P802.11be/D2.0.

Signed-off-by: Ayala Beker <ayala.beker@intel.com>
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
This commit is contained in:
Ayala Beker 2022-11-30 17:02:46 +02:00 committed by Jouni Malinen
parent 755aaeb97f
commit 9a2781f243
2 changed files with 73 additions and 13 deletions

View file

@ -2515,6 +2515,8 @@ struct ieee80211_eht_capabilities {
u8 optional[EHT_MCS_NSS_CAPAB_LEN + EHT_PPE_THRESH_CAPAB_LEN];
} STRUCT_PACKED;
#define IEEE80211_EHT_CAPAB_MIN_LEN (2 + 9)
/* IEEE P802.11be/D2.1, 9.4.2.312 - Multi-Link element */
/* Figure 9-1002f: Multi-Link Control field */

View file

@ -2373,6 +2373,8 @@ static const struct minsnr_bitrate_entry vht160_table[] = {
{ -1, 780000 } /* SNR > 37 */
};
/* EHT needs to be enabled in order to achieve MCS12 and MCS13 rates. */
#define EHT_MCS 12
static const struct minsnr_bitrate_entry he20_table[] = {
{ 0, 0 },
@ -2388,7 +2390,9 @@ static const struct minsnr_bitrate_entry he20_table[] = {
{ 31, 114700 }, /* HE20 MCS9 */
{ 34, 129000 }, /* HE20 MCS10 */
{ 36, 143400 }, /* HE20 MCS11 */
{ -1, 143400 } /* SNR > 29 */
{ 39, 154900 }, /* EHT20 MCS12 */
{ 42, 172100 }, /* EHT20 MCS13 */
{ -1, 172100 } /* SNR > 42 */
};
static const struct minsnr_bitrate_entry he40_table[] = {
@ -2405,7 +2409,9 @@ static const struct minsnr_bitrate_entry he40_table[] = {
{ 34, 229400 }, /* HE40 MCS9 */
{ 37, 258100 }, /* HE40 MCS10 */
{ 39, 286800 }, /* HE40 MCS11 */
{ -1, 286800 } /* SNR > 34 */
{ 42, 309500 }, /* EHT40 MCS12 */
{ 45, 344100 }, /* EHT40 MCS13 */
{ -1, 344100 } /* SNR > 45 */
};
static const struct minsnr_bitrate_entry he80_table[] = {
@ -2422,7 +2428,9 @@ static const struct minsnr_bitrate_entry he80_table[] = {
{ 37, 480400 }, /* HE80 MCS9 */
{ 40, 540400 }, /* HE80 MCS10 */
{ 42, 600500 }, /* HE80 MCS11 */
{ -1, 600500 } /* SNR > 37 */
{ 45, 648500 }, /* EHT80 MCS12 */
{ 48, 720600 }, /* EHT80 MCS13 */
{ -1, 720600 } /* SNR > 48 */
};
@ -2440,9 +2448,31 @@ static const struct minsnr_bitrate_entry he160_table[] = {
{ 40, 960800 }, /* HE160 MCS9 */
{ 43, 1080900 }, /* HE160 MCS10 */
{ 45, 1201000 }, /* HE160 MCS11 */
{ -1, 1201000 } /* SNR > 37 */
{ 48, 1297100 }, /* EHT160 MCS12 */
{ 51, 1441200 }, /* EHT160 MCS13 */
{ -1, 1441200 } /* SNR > 51 */
};
/* See IEEE P802.11be/D2.0, Table 36-86: EHT-MCSs for 4x996-tone RU, NSS,u = 1
*/
static const struct minsnr_bitrate_entry eht320_table[] = {
{ 0, 0 },
{ 14, 144100 }, /* EHT320 MCS0 */
{ 17, 288200 }, /* EHT320 MCS1 */
{ 21, 432400 }, /* EHT320 MCS2 */
{ 23, 576500 }, /* EHT320 MCS3 */
{ 27, 864700 }, /* EHT320 MCS4 */
{ 30, 1152900 }, /* EHT320 MCS5 */
{ 32, 1297100 }, /* EHT320 MCS6 */
{ 37, 1441200 }, /* EHT320 MCS7 */
{ 41, 1729400 }, /* EHT320 MCS8 */
{ 43, 1921500 }, /* EHT320 MCS9 */
{ 46, 2161800 }, /* EHT320 MCS10 */
{ 48, 2401900 }, /* EHT320 MCS11 */
{ 51, 2594100 }, /* EHT320 MCS12 */
{ 54, 2882400 }, /* EHT320 MCS13 */
{ -1, 2882400 } /* SNR > 54 */
};
static unsigned int interpolate_rate(int snr, int snr0, int snr1,
int rate0, int rate1)
@ -2494,17 +2524,18 @@ static unsigned int max_vht160_rate(int snr)
}
static unsigned int max_he_rate(const struct minsnr_bitrate_entry table[],
int snr)
static unsigned int max_he_eht_rate(const struct minsnr_bitrate_entry table[],
int snr, bool eht)
{
const struct minsnr_bitrate_entry *prev, *entry = table;
while (entry->minsnr != -1 && snr >= entry->minsnr)
while (entry->minsnr != -1 && snr >= entry->minsnr &&
(eht || entry - table <= EHT_MCS))
entry++;
if (entry == table)
return 0;
prev = entry - 1;
if (entry->minsnr == -1)
if (entry->minsnr == -1 || (!eht && entry - table > EHT_MCS))
return prev->bitrate;
return interpolate_rate(snr, prev->minsnr, entry->minsnr,
prev->bitrate, entry->bitrate);
@ -2642,8 +2673,11 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
if (hw_mode && hw_mode->he_capab[IEEE80211_MODE_INFRA].he_supported) {
/* Use +2 to assume HE is always faster than HT/VHT */
struct ieee80211_he_capabilities *he;
struct ieee80211_eht_capabilities *eht;
struct he_capabilities *own_he;
u8 cw;
u8 cw, boost = 2;
const u8 *eht_ie;
bool is_eht = false;
ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_HE_CAPABILITIES);
if (!ie || (ie[1] < 1 + IEEE80211_HE_CAPAB_MIN_LEN))
@ -2651,7 +2685,18 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
he = (struct ieee80211_he_capabilities *) &ie[3];
own_he = &hw_mode->he_capab[IEEE80211_MODE_INFRA];
tmp = max_he_rate(he20_table, snr) + 2;
/* Use +3 to assume EHT is always faster than HE */
if (hw_mode->eht_capab[IEEE80211_MODE_INFRA].eht_supported) {
eht_ie = get_ie_ext(ies, ies_len,
WLAN_EID_EXT_EHT_CAPABILITIES);
if (eht_ie &&
(eht_ie[1] >= 1 + IEEE80211_EHT_CAPAB_MIN_LEN)) {
is_eht = true;
boost = 3;
}
}
tmp = max_he_eht_rate(he20_table, snr, is_eht) + boost;
if (tmp > est)
est = tmp;
@ -2660,14 +2705,14 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
if (cw &
(IS_2P4GHZ(freq) ? HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G :
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) {
tmp = max_he_rate(he40_table, snr) + 2;
tmp = max_he_eht_rate(he40_table, snr, is_eht) + boost;
if (tmp > est)
est = tmp;
}
if (!IS_2P4GHZ(freq) &&
(cw & HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) {
tmp = max_he_rate(he80_table, snr) + 2;
tmp = max_he_eht_rate(he80_table, snr, is_eht) + boost;
if (tmp > est)
est = tmp;
}
@ -2675,7 +2720,20 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
if (!IS_2P4GHZ(freq) &&
(cw & (HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G))) {
tmp = max_he_rate(he160_table, snr) + 2;
tmp = max_he_eht_rate(he160_table, snr, is_eht) + boost;
if (tmp > est)
est = tmp;
}
if (!is_eht)
return est;
eht = (struct ieee80211_eht_capabilities *) &eht_ie[3];
if (is_6ghz_freq(freq) &&
(eht->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK)) {
tmp = max_he_eht_rate(eht320_table, snr, true);
if (tmp > est)
est = tmp;
}