}
-static u8 ieee80211_eht_mcs_set_size(const u8 *he_phy_cap,
+static u8 ieee80211_eht_mcs_set_size(enum hostapd_hw_mode mode, u8 opclass,
+ const u8 *he_phy_cap,
const u8 *eht_phy_cap)
{
u8 sz = EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS;
+ bool band24, band5, band6;
+
+ band24 = mode == HOSTAPD_MODE_IEEE80211B ||
+ mode == HOSTAPD_MODE_IEEE80211G ||
+ mode == NUM_HOSTAPD_MODES;
+ band5 = mode == HOSTAPD_MODE_IEEE80211A ||
+ mode == NUM_HOSTAPD_MODES;
+ band6 = is_6ghz_op_class(opclass);
+
+ if (band24 &&
+ (he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+ HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G) == 0)
+ return EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY;
- if ((he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
- (HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
- HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
- HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
- HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) == 0)
+ if (band5 &&
+ (he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+ (HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
+ HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
+ HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) == 0)
return EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY;
- if (he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
- (HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
- HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G))
- sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS;
+ if (band5 &&
+ (he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+ (HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
+ HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)))
+ sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS;
- if (eht_phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
- EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK)
+ if (band6 &&
+ (eht_phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
+ EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK))
sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS;
return sz;
if (!eht_cap->eht_supported)
return 0;
- len += ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap,
+ len += ieee80211_eht_mcs_set_size(mode->mode, hapd->iconf->op_class,
+ mode->he_capab[opmode].phy_cap,
eht_cap->phy_cap);
len += ieee80211_eht_ppet_size(WPA_GET_LE16(&eht_cap->ppet[0]),
eht_cap->phy_cap);
pos = cap->optional;
- mcs_nss_len = ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap,
+ mcs_nss_len = ieee80211_eht_mcs_set_size(mode->mode,
+ hapd->iconf->op_class,
+ mode->he_capab[opmode].phy_cap,
eht_cap->phy_cap);
if (mcs_nss_len) {
os_memcpy(pos, eht_cap->mcs, mcs_nss_len);
capab = (const struct ieee80211_eht_capabilities *) sta_eht_capab;
sta_mcs = capab->optional;
- if (ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap,
+ if (ieee80211_eht_mcs_set_size(mode->mode, hapd->iconf->op_class,
+ mode->he_capab[opmode].phy_cap,
mode->eht_capab[opmode].phy_cap) ==
EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY)
return check_valid_eht_mcs_nss(
}
-static bool ieee80211_invalid_eht_cap_size(const u8 *he_cap, const u8 *eht_cap,
+static bool ieee80211_invalid_eht_cap_size(enum hostapd_hw_mode mode,
+ u8 opclass,
+ const u8 *he_cap, const u8 *eht_cap,
size_t len)
{
const struct ieee80211_he_capabilities *he_capab;
if (len < cap_len)
return true;
- cap_len += ieee80211_eht_mcs_set_size(he_phy_cap, cap->phy_cap);
+ cap_len += ieee80211_eht_mcs_set_size(mode, opclass, he_phy_cap,
+ cap->phy_cap);
if (len < cap_len)
return true;
const u8 *he_capab, size_t he_capab_len,
const u8 *eht_capab, size_t eht_capab_len)
{
+ struct hostapd_hw_modes *c_mode = hapd->iface->current_mode;
+ enum hostapd_hw_mode mode = c_mode ? c_mode->mode : NUM_HOSTAPD_MODES;
+
if (!hapd->iconf->ieee80211be || hapd->conf->disable_11be ||
!he_capab || he_capab_len < IEEE80211_HE_CAPAB_MIN_LEN ||
!eht_capab ||
- ieee80211_invalid_eht_cap_size(he_capab, eht_capab,
+ ieee80211_invalid_eht_cap_size(mode, hapd->iconf->op_class,
+ he_capab, eht_capab,
eht_capab_len) ||
!check_valid_eht_mcs(hapd, eht_capab, opmode)) {
sta->flags &= ~WLAN_STA_EHT;