From add539d6f28cce4519abad790fd4e423078b4ab7 Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Tue, 29 Jun 2021 16:46:36 -0700 Subject: [PATCH 08/23] eht: add capabilities element in management frames. Add EHT capabilities IE in beacons, probe responses and association response frames. Signed-off-by: Aloka Dixit Signed-off-by: Pradeep Kumar Chitrapu --- hostapd/Makefile | 1 + src/ap/beacon.c | 22 ++++++ src/ap/ieee802_11.c | 10 +++ src/ap/ieee802_11.h | 4 ++ src/ap/ieee802_11_eht.c | 154 ++++++++++++++++++++++++++++++++++++++++ src/drivers/driver.h | 14 ++++ 6 files changed, 205 insertions(+) create mode 100644 src/ap/ieee802_11_eht.c --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -351,6 +351,7 @@ endif ifdef CONFIG_IEEE80211BE CFLAGS += -DCONFIG_IEEE80211BE +OBJS += ../src/ap/ieee802_11_eht.o endif ifdef CONFIG_MBO --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -639,6 +639,11 @@ static u8 * hostapd_gen_probe_resp(struc } #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_mbssid_len(hapd_probed, WLAN_FC_STYPE_PROBE_RESP, NULL, known_bss, known_bss_len, NULL); buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP); @@ -780,6 +785,11 @@ static u8 * hostapd_gen_probe_resp(struc } #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); @@ -1707,6 +1717,11 @@ int ieee802_11_build_ap_params(struct ho } #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 */ + if (hapd->iconf->ema) tail_len += 5; /* Multiple BSSID Configuration element */ tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON); @@ -1857,6 +1872,12 @@ int ieee802_11_build_ap_params(struct ho } #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); --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -5083,6 +5083,11 @@ static u16 send_assoc_resp(struct hostap 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; @@ -5197,6 +5202,11 @@ static u16 send_assoc_resp(struct hostap } #endif /* CONFIG_IEEE80211AX */ +#ifdef CONFIG_IEEE80211BE + if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) + p = hostapd_eid_eht_capab(hapd, p, IEEE80211_MODE_AP); +#endif /* CONFIG_IEEE80211BE */ + p = hostapd_eid_ext_capab(hapd, p); p = hostapd_eid_bss_max_idle_period(hapd, p); if (sta && sta->qos_map_enabled) --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -215,5 +215,8 @@ void auth_sae_process_commit(void *eloop u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len); size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type); u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type); - +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 */ --- /dev/null +++ b/src/ap/ieee802_11_eht.c @@ -0,0 +1,164 @@ +/* + * hostapd / IEEE 802.11be EHT + * + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#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, ru; + + if ((phy_cap_info[EHT_PHYCAP_PPE_THRESHOLD_PRESENT_IDX] & + EHT_PHYCAP_PPE_THRESHOLD_PRESENT) == 0) + return 0; + + ru = (ppe_thres[0] & + (EHT_PPE_THRES_RU_INDEX_MASK << EHT_PPE_THRES_RU_INDEX_SHIFT)); + while (ru) { + if (ru & 0x1) + sz++; + ru >>= 1; + } + + ru = (ppe_thres[1] & (EHT_PPE_THRES_RU_INDEX_MASK >> + (8 - EHT_PPE_THRES_RU_INDEX_SHIFT))); + while (ru) { + if (ru & 0x1) + sz++; + ru >>= 1; + } + + sz *= (1 + (ppe_thres[0] & EHT_PPE_THRES_NSS_MASK)); + 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 + EHT_MAC_CAPAB_MAX_LEN + EHT_PHY_CAPAB_MAX_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_CAPABILITY; + + cap = (struct ieee80211_eht_capabilities *) pos; + os_memset(cap, 0, sizeof(*cap)); + os_memcpy(cap->mac_cap, eht_cap->mac_cap, EHT_MAC_CAPAB_MAX_LEN); + os_memcpy(cap->phy_cap, eht_cap->phy_cap, EHT_PHY_CAPAB_MAX_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; +} --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -201,6 +201,15 @@ struct he_capabilities { u16 he_6ghz_capa; }; +/* struct eht_capabilities - IEEE 802.11be EHT capabilities */ +struct eht_capabilities { + u8 eht_supported; + u8 mac_cap[EHT_MAC_CAPAB_MAX_LEN]; + u8 phy_cap[EHT_PHY_CAPAB_MAX_LEN]; + u8 mcs[EHT_MCS_NSS_CAPAB_MAX_LEN]; + u8 ppet[EHT_PPE_THRESH_CAPAB_MAX_LEN]; +}; + #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0) #define HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN BIT(1) @@ -305,6 +314,11 @@ struct hostapd_hw_modes { * supported in 6G band. */ s8 psd_values[NL80211_REG_NUM_POWER_MODES]; + + /** + * eht_capab - EHT (IEEE 802.11be) capabilities + */ + struct eht_capabilities eht_capab[IEEE80211_MODE_NUM]; };