wlan-ap-Telecominfraproject/feeds/ipq95xx/hostapd.old/patches/q02-008-eht-add-capabilities-element-in-management-frames.patch
John Crispin b9b03a6e38 ipq95xx: add Qualcomm wifi-7 support
Signed-off-by: John Crispin <john@phrozen.org>
2023-04-10 14:25:48 +02:00

317 lines
9.6 KiB
Diff

From add539d6f28cce4519abad790fd4e423078b4ab7 Mon Sep 17 00:00:00 2001
From: Aloka Dixit <quic_alokad@quicinc.com>
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 <quic_alokad@quicinc.com>
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
---
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];
};