]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP: Fix HE capability advertisement
authorAditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
Mon, 29 Sep 2025 09:45:35 +0000 (15:15 +0530)
committerJouni Malinen <j@w1.fi>
Mon, 29 Sep 2025 10:54:59 +0000 (13:54 +0300)
The current implementation incorrectly derives the 'Supported Channel
Width Set' in the HE PHY Capabilities Information field based on the
operating bandwidth. This, in turn, affects the advertisement of the
'Supported HE-MCS and NSS Set' field. Such behavior is flawed, as
capability advertisement should reflect the full hardware capabilities,
not the current operating configuration. Runtime parameters already have
designated fields in the HE Operation element for their representation.

Hence, fix this now by using the HE PHY Capabilities and Supported
HE-MCS and NSS Set values as advertised by the driver.

Signed-off-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
src/ap/ieee802_11_he.c

index f4adeada98c53c954b8c9c988dd68c6edf3d2929..e072fb831acac9bf83f434532decbfc600417d36 100644 (file)
@@ -91,49 +91,20 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
 {
        struct ieee80211_he_capabilities *cap;
        struct hostapd_hw_modes *mode = hapd->iface->current_mode;
-       u8 he_oper_chwidth = 0;
+       const struct he_capabilities *he_capab;
        u8 *pos = eid;
-       u8 ie_size = 0, mcs_nss_size = 4, ppet_size = 0;
+       u8 ie_size = 0, mcs_nss_size, ppet_size;
 
        if (!mode)
                return eid;
 
-       ie_size = sizeof(*cap) - sizeof(cap->optional);
-       ppet_size = ieee80211_he_ppet_size(mode->he_capab[opmode].ppet[0],
-                                          mode->he_capab[opmode].phy_cap);
-
-       if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
-               switch (hapd->iface->conf->he_oper_chwidth) {
-               case CONF_OPER_CHWIDTH_80P80MHZ:
-                       he_oper_chwidth |=
-                               HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G;
-                       mcs_nss_size += 4;
-                       /* fall through */
-               case CONF_OPER_CHWIDTH_160MHZ:
-                       he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
-                       mcs_nss_size += 4;
-                       /* fall through */
-               case CONF_OPER_CHWIDTH_80MHZ:
-               case CONF_OPER_CHWIDTH_USE_HT:
-                       he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
-                       break;
-               default:
-                       break;
-               }
-       } else  {
-               switch (hapd->iface->conf->he_oper_chwidth) {
-               case CONF_OPER_CHWIDTH_80P80MHZ:
-               case CONF_OPER_CHWIDTH_160MHZ:
-               case CONF_OPER_CHWIDTH_80MHZ:
-               case CONF_OPER_CHWIDTH_USE_HT:
-                       he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
-                       break;
-               default:
-                       break;
-               }
-       }
+       he_capab = &mode->he_capab[opmode];
+
+       mcs_nss_size = ieee80211_he_mcs_set_size(he_capab->phy_cap);
+       ppet_size = ieee80211_he_ppet_size(he_capab->ppet[0],
+                                          he_capab->phy_cap);
 
-       ie_size += mcs_nss_size + ppet_size;
+       ie_size = IEEE80211_HE_CAPAB_MIN_LEN + mcs_nss_size + ppet_size;
 
        *pos++ = WLAN_EID_EXTENSION;
        *pos++ = 1 + ie_size;
@@ -142,14 +113,15 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
        cap = (struct ieee80211_he_capabilities *) pos;
        os_memset(cap, 0, sizeof(*cap));
 
-       os_memcpy(cap->he_mac_capab_info, mode->he_capab[opmode].mac_cap,
+       os_memcpy(cap->he_mac_capab_info, he_capab->mac_cap,
                  HE_MAX_MAC_CAPAB_SIZE);
-       os_memcpy(cap->he_phy_capab_info, mode->he_capab[opmode].phy_cap,
+       os_memcpy(cap->he_phy_capab_info, he_capab->phy_cap,
                  HE_MAX_PHY_CAPAB_SIZE);
-       os_memcpy(cap->optional, mode->he_capab[opmode].mcs, mcs_nss_size);
+       os_memcpy(cap->optional, he_capab->mcs, mcs_nss_size);
+
        if (ppet_size)
-               os_memcpy(&cap->optional[mcs_nss_size],
-                         mode->he_capab[opmode].ppet,  ppet_size);
+               os_memcpy(&cap->optional[mcs_nss_size], he_capab->ppet,
+                         ppet_size);
 
        if (hapd->iface->conf->he_phy_capab.he_su_beamformer)
                cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
@@ -172,9 +144,6 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
                cap->he_phy_capab_info[HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX] &=
                        ~HE_PHYCAP_MU_BEAMFORMER_CAPAB;
 
-       cap->he_phy_capab_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &=
-               he_oper_chwidth;
-
        pos += ie_size;
 
        return pos;