diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 310b7660e..669f380d2 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -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 */ diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 5b866ec91..968906733 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -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; }