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:
parent
a7ea721889
commit
9b7202d665
8 changed files with 200 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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
157
src/ap/ieee802_11_eht.c
Normal 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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue