]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EHT: Add capabilities element in AP mode Management frames
authorAloka Dixit <quic_alokad@quicinc.com>
Tue, 19 Apr 2022 18:04:08 +0000 (11:04 -0700)
committerJouni Malinen <j@w1.fi>
Fri, 29 Apr 2022 14:28:40 +0000 (17:28 +0300)
Add EHT Capabilities element in Beacon, Probe Response, and
(Re)Association Response frames.

Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
hostapd/Android.mk
hostapd/Makefile
src/ap/beacon.c
src/ap/ieee802_11.c
src/ap/ieee802_11.h
src/ap/ieee802_11_eht.c [new file with mode: 0644]
wpa_supplicant/Android.mk
wpa_supplicant/Makefile

index f36957594bfa0411259adb1e76dd62de42ae0a7e..885dae7f6db08b28890bdf67f2f859f4a74514d4 100644 (file)
@@ -297,6 +297,7 @@ endif
 ifdef CONFIG_IEEE80211BE
 CONFIG_IEEE80211AX=y
 L_CFLAGS += -DCONFIG_IEEE80211BE
+OBJS += src/ap/ieee802_11_eht.c
 endif
 
 ifdef CONFIG_IEEE80211AX
index 25d6530d370a25bfd443affcdbdc753161091d8e..9967e270cfc24808fff7042b8d8bacbf25e1b6ae 100644 (file)
@@ -342,6 +342,7 @@ endif
 ifdef CONFIG_IEEE80211BE
 CONFIG_IEEE80211AX=y
 CFLAGS += -DCONFIG_IEEE80211BE
+OBJS += ../src/ap/ieee802_11_eht.o
 endif
 
 ifdef CONFIG_IEEE80211AX
index 3ff03f845200f0df2e3f3887a55e0f060cefdf8a..270b28b713e5c3459e447ece0f9565d555f1b134 100644 (file)
@@ -509,6 +509,11 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
        }
 #endif /* CONFIG_IEEE80211AX */
 
+#ifdef CONFIG_IEEE80211BE
+       if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be)
+               buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP);
+#endif /* CONFIG_IEEE80211BE */
+
        buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
        buflen += hostapd_mbo_ie_len(hapd);
        buflen += hostapd_eid_owe_trans_len(hapd);
@@ -635,6 +640,11 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
        }
 #endif /* CONFIG_IEEE80211AX */
 
+#ifdef CONFIG_IEEE80211BE
+       if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be)
+               pos = hostapd_eid_eht_capab(hapd, pos, IEEE80211_MODE_AP);
+#endif /* CONFIG_IEEE80211BE */
+
 #ifdef CONFIG_IEEE80211AC
        if (hapd->conf->vendor_vht)
                pos = hostapd_eid_vendor_vht(hapd, pos);
@@ -1538,6 +1548,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
        }
 #endif /* CONFIG_IEEE80211AX */
 
+#ifdef CONFIG_IEEE80211BE
+       if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be)
+               tail_len += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP);
+#endif /* CONFIG_IEEE80211BE */
+
        tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
        tail_len += hostapd_mbo_ie_len(hapd);
        tail_len += hostapd_eid_owe_trans_len(hapd);
@@ -1685,6 +1700,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
        }
 #endif /* CONFIG_IEEE80211AX */
 
+#ifdef CONFIG_IEEE80211BE
+       if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be)
+               tailpos = hostapd_eid_eht_capab(hapd, tailpos,
+                                               IEEE80211_MODE_AP);
+#endif /* CONFIG_IEEE80211BE */
+
 #ifdef CONFIG_IEEE80211AC
        if (hapd->conf->vendor_vht)
                tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
index e25b6804c89506f89e968fa2b7a802a6628bc537..c7ee3e126f3c08d29c2a26a35f5b59968c56c025 100644 (file)
@@ -5044,6 +5044,11 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
        if (sta && sta->dpp_pfs)
                buflen += 5 + sta->dpp_pfs->curve->prime_len;
 #endif /* CONFIG_DPP2 */
+#ifdef CONFIG_IEEE80211BE
+       if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be)
+               buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP);
+#endif /* CONFIG_IEEE80211BE */
+
        buf = os_zalloc(buflen);
        if (!buf) {
                res = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -5190,6 +5195,11 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
 rsnxe_done:
 #endif /* CONFIG_TESTING_OPTIONS */
 
+#ifdef CONFIG_IEEE80211BE
+       if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be)
+               p = hostapd_eid_eht_capab(hapd, p, IEEE80211_MODE_AP);
+#endif /* CONFIG_IEEE80211BE */
+
 #ifdef CONFIG_OWE
        if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
            sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS &&
index ec0fc4396a7d2adc59e223ea00b68e93b5d47dee..b8fcfae0dc1c3c1ac6354590e8c5c44dc4b240a1 100644 (file)
@@ -201,5 +201,9 @@ size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type);
 u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type);
 int ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
                               int res, struct radius_sta *info);
+size_t hostapd_eid_eht_capab_len(struct hostapd_data *hapd,
+                                enum ieee80211_op_mode opmode);
+u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid,
+                          enum ieee80211_op_mode opmode);
 
 #endif /* IEEE802_11_H */
diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c
new file mode 100644 (file)
index 0000000..f4807d0
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * hostapd / IEEE 802.11be EHT
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#include "utils/common.h"
+#include "hostapd.h"
+#include "ieee802_11.h"
+
+
+static u8 ieee80211_eht_ppet_size(const u8 *ppe_thres, const u8 *phy_cap_info)
+{
+       u8 sz = 0, nss, num_nss = 0;
+       u32 ru;
+
+       if ((phy_cap_info[EHT_PHYCAP_PPE_THRESHOLD_PRESENT_IDX] &
+            EHT_PHYCAP_PPE_THRESHOLD_PRESENT) == 0)
+               return 0;
+
+       ru = (u32) ppe_thres[0];
+       ru = (ru & EHT_PPE_THRES_RU_INDEX_MASK) >> EHT_PPE_THRES_RU_INDEX_SHIFT;
+       while (ru) {
+               if (ru & 0x1)
+                       sz++;
+               ru >>= 1;
+       }
+
+       nss = (ppe_thres[0] & EHT_PPE_THRES_NSS_MASK) >>
+               EHT_PPE_THRES_NSS_SHIFT;
+       while (nss) {
+               if (nss & 0x1)
+                       num_nss++;
+               nss >>= 1;
+       }
+
+       sz = sz * (1 + num_nss);
+       sz = (sz * 6) + 9;
+       if (sz % 8)
+               sz += 8;
+       sz /= 8;
+
+       return sz;
+}
+
+
+static u8 ieee80211_eht_mcs_set_size(const u8 *he_phy_cap,
+                                    const u8 *eht_phy_cap)
+{
+       u8 sz = EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS;
+
+       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)
+               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 (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;
+}
+
+
+size_t hostapd_eid_eht_capab_len(struct hostapd_data *hapd,
+                                enum ieee80211_op_mode opmode)
+{
+       struct hostapd_hw_modes *mode;
+       struct eht_capabilities *eht_cap;
+       size_t len = 3 + 2 + EHT_PHY_CAPAB_LEN;
+
+       mode = hapd->iface->current_mode;
+       if (!mode)
+               return 0;
+
+       eht_cap = &mode->eht_capab[opmode];
+       if (!eht_cap->eht_supported)
+               return 0;
+
+       len += ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap,
+                                         eht_cap->phy_cap);
+       len += ieee80211_eht_ppet_size(eht_cap->ppet, eht_cap->phy_cap);
+
+       return len;
+}
+
+
+u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid,
+                          enum ieee80211_op_mode opmode)
+{
+       struct hostapd_hw_modes *mode;
+       struct eht_capabilities *eht_cap;
+       struct ieee80211_eht_capabilities *cap;
+       size_t mcs_nss_len, ppe_thresh_len;
+       u8 *pos = eid, *length_pos;
+
+       mode = hapd->iface->current_mode;
+       if (!mode)
+               return eid;
+
+       eht_cap = &mode->eht_capab[opmode];
+       if (!eht_cap->eht_supported)
+               return eid;
+
+       *pos++ = WLAN_EID_EXTENSION;
+       length_pos = pos++;
+       *pos++ = WLAN_EID_EXT_EHT_CAPABILITIES;
+
+       cap = (struct ieee80211_eht_capabilities *) pos;
+       os_memset(cap, 0, sizeof(*cap));
+       cap->mac_cap = host_to_le16(eht_cap->mac_cap);
+       os_memcpy(cap->phy_cap, eht_cap->phy_cap, EHT_PHY_CAPAB_LEN);
+
+       if (!is_6ghz_op_class(hapd->iconf->op_class))
+               cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &=
+                       ~EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK;
+       if (!hapd->iface->conf->eht_phy_capab.su_beamformer)
+               cap->phy_cap[EHT_PHYCAP_SU_BEAMFORMER_IDX] &=
+                       ~EHT_PHYCAP_SU_BEAMFORMER;
+
+       if (!hapd->iface->conf->eht_phy_capab.su_beamformee)
+               cap->phy_cap[EHT_PHYCAP_SU_BEAMFORMEE_IDX] &=
+                       ~EHT_PHYCAP_SU_BEAMFORMEE;
+
+       if (!hapd->iface->conf->eht_phy_capab.mu_beamformer)
+               cap->phy_cap[EHT_PHYCAP_MU_BEAMFORMER_IDX] &=
+                       ~EHT_PHYCAP_MU_BEAMFORMER_MASK;
+
+       pos = cap->optional;
+
+       mcs_nss_len = ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap,
+                                                eht_cap->phy_cap);
+       if (mcs_nss_len) {
+               os_memcpy(pos, eht_cap->mcs, mcs_nss_len);
+               pos += mcs_nss_len;
+       }
+
+       ppe_thresh_len = ieee80211_eht_ppet_size(eht_cap->ppet,
+                                                eht_cap->phy_cap);
+       if (ppe_thresh_len) {
+               os_memcpy(pos, eht_cap->ppet, ppe_thresh_len);
+               pos += ppe_thresh_len;
+       }
+
+       *length_pos = pos - (eid + 2);
+       return pos;
+}
index bddeaf52648ed4ff535fcacb59dc96185b1650c5..5d68ffa1d5e44cdae159cf76e8ee71994622a146 100644 (file)
@@ -911,6 +911,9 @@ endif
 ifdef CONFIG_IEEE80211AX
 OBJS += src/ap/ieee802_11_he.c
 endif
+ifdef CONFIG_IEEE80211BE
+OBJS += src/ap/ieee802_11_eht.c
+endif
 ifdef CONFIG_WNM_AP
 L_CFLAGS += -DCONFIG_WNM_AP
 OBJS += src/ap/wnm_ap.c
index 575d22340812e29e2ddc4e33493a016edbf52eaf..ead9205ff1ac188a014954c83a948ac301cf2ccd 100644 (file)
@@ -946,6 +946,9 @@ endif
 ifdef CONFIG_IEEE80211AX
 OBJS += ../src/ap/ieee802_11_he.o
 endif
+ifdef CONFIG_IEEE80211BE
+OBJS += ../src/ap/ieee802_11_eht.o
+endif
 ifdef CONFIG_WNM_AP
 CFLAGS += -DCONFIG_WNM_AP
 OBJS += ../src/ap/wnm_ap.o