EHT: Add capabilities element in AP mode Management frames

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>
This commit is contained in:
Aloka Dixit 2022-04-19 11:04:08 -07:00 committed by Jouni Malinen
parent a7ea721889
commit 9b7202d665
8 changed files with 200 additions and 0 deletions

View 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

View 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

View 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);

View 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 &&

View 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 */

157
src/ap/ieee802_11_eht.c Normal file
View file

@ -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;
}

View 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

View 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