aboutsummaryrefslogtreecommitdiff
path: root/src/ap/ieee802_11_he.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ap/ieee802_11_he.c')
-rw-r--r--src/ap/ieee802_11_he.c86
1 files changed, 67 insertions, 19 deletions
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
index 6cd6c90d..548a4482 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -29,17 +29,19 @@ static u8 ieee80211_he_ppet_size(u8 ppe_thres_hdr, const u8 *phy_cap_info)
ru = (ppe_thres_hdr >> HE_PPE_THRES_RU_INDEX_BITMASK_SHIFT) &
HE_PPE_THRES_RU_INDEX_BITMASK_MASK;
+ /* Count the number of 1 bits in RU Index Bitmask */
while (ru) {
if (ru & 0x1)
sz++;
ru >>= 1;
}
+ /* fixed header of 3 (NSTS) + 4 (RU Index Bitmask) = 7 bits */
+ /* 6 * (NSTS + 1) bits for bit 1 in RU Index Bitmask */
sz *= 1 + (ppe_thres_hdr & HE_PPE_THRES_NSS_MASK);
sz = (sz * 6) + 7;
- if (sz % 8)
- sz += 8;
- sz /= 8;
+ /* PPE Pad to count the number of needed full octets */
+ sz = (sz + 7) / 8;
return sz;
}
@@ -64,6 +66,7 @@ static int ieee80211_invalid_he_cap_size(const u8 *buf, size_t len)
{
struct ieee80211_he_capabilities *cap;
size_t cap_len;
+ u8 ppe_thres_hdr;
cap = (struct ieee80211_he_capabilities *) buf;
cap_len = sizeof(*cap) - sizeof(cap->optional);
@@ -74,9 +77,11 @@ static int ieee80211_invalid_he_cap_size(const u8 *buf, size_t len)
if (len < cap_len)
return 1;
- cap_len += ieee80211_he_ppet_size(buf[cap_len], cap->he_phy_capab_info);
+ ppe_thres_hdr = len > cap_len ? buf[cap_len] : 0xff;
+ cap_len += ieee80211_he_ppet_size(ppe_thres_hdr,
+ cap->he_phy_capab_info);
- return len != cap_len;
+ return len < cap_len;
}
@@ -97,20 +102,22 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
mode->he_capab[opmode].phy_cap);
switch (hapd->iface->conf->he_oper_chwidth) {
- case CHANWIDTH_80P80MHZ:
+ case CONF_OPER_CHWIDTH_80P80MHZ:
he_oper_chwidth |=
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G;
mcs_nss_size += 4;
/* fall through */
- case CHANWIDTH_160MHZ:
+ case CONF_OPER_CHWIDTH_160MHZ:
he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
mcs_nss_size += 4;
/* fall through */
- case CHANWIDTH_80MHZ:
- case CHANWIDTH_USE_HT:
+ case CONF_OPER_CHWIDTH_80MHZ:
+ case CONF_OPER_CHWIDTH_USE_HT:
he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
break;
+ default:
+ break;
}
ie_size += mcs_nss_size + ppet_size;
@@ -195,7 +202,8 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
if (hapd->iface->conf->he_op.he_er_su_disable)
params |= HE_OPERATION_ER_SU_DISABLE;
- if (hapd->iface->conf->he_op.he_bss_color_disabled)
+ if (hapd->iface->conf->he_op.he_bss_color_disabled ||
+ hapd->cca_in_progress)
params |= HE_OPERATION_BSS_COLOR_DISABLED;
if (hapd->iface->conf->he_op.he_bss_color_partial)
params |= HE_OPERATION_BSS_COLOR_PARTIAL;
@@ -211,8 +219,19 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
pos += 6; /* skip the fixed part */
if (is_6ghz_op_class(hapd->iconf->op_class)) {
- u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
+ enum oper_chan_width oper_chwidth =
+ hostapd_get_oper_chwidth(hapd->iconf);
+ u8 seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx;
u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
+ u8 control;
+
+#ifdef CONFIG_IEEE80211BE
+ if (hapd->iconf->punct_bitmap) {
+ punct_update_legacy_bw(hapd->iconf->punct_bitmap,
+ hapd->iconf->channel,
+ &oper_chwidth, &seg0, &seg1);
+ }
+#endif /* CONFIG_IEEE80211BE */
if (!seg0)
seg0 = hapd->iconf->channel;
@@ -220,19 +239,31 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
params |= HE_OPERATION_6GHZ_OPER_INFO;
/* 6 GHz Operation Information field
- * IEEE P802.11ax/D8.0, 9.4.2.249 HE Operation element,
+ * IEEE Std 802.11ax-2021, 9.4.2.249 HE Operation element,
* Figure 9-788k
*/
*pos++ = hapd->iconf->channel; /* Primary Channel */
- /* Control: Channel Width */
+ /* Control:
+ * bits 0-1: Channel Width
+ * bit 2: Duplicate Beacon
+ * bits 3-5: Regulatory Info
+ */
+ /* Channel Width */
if (seg1)
- *pos++ = 3;
+ control = 3;
+ else
+ control = center_idx_to_bw_6ghz(seg0);
+ if (hapd->iconf->he_6ghz_reg_pwr_type == 1)
+ control |= HE_6GHZ_STANDARD_POWER_AP <<
+ HE_6GHZ_OPER_INFO_CTRL_REG_INFO_SHIFT;
else
- *pos++ = center_idx_to_bw_6ghz(seg0);
+ control |= HE_6GHZ_INDOOR_AP <<
+ HE_6GHZ_OPER_INFO_CTRL_REG_INFO_SHIFT;
+ *pos++ = control;
/* Channel Center Freq Seg0/Seg1 */
- if (hapd->iconf->he_oper_chwidth == 2) {
+ if (oper_chwidth == 2) {
/*
* Seg 0 indicates the channel center frequency index of
* the 160 MHz channel.
@@ -411,10 +442,10 @@ static int check_valid_he_mcs(struct hostapd_data *hapd, const u8 *sta_he_capab,
* band/stream cases.
*/
switch (hapd->iface->conf->he_oper_chwidth) {
- case CHANWIDTH_80P80MHZ:
+ case CONF_OPER_CHWIDTH_80P80MHZ:
mcs_count = 3;
break;
- case CHANWIDTH_160MHZ:
+ case CONF_OPER_CHWIDTH_160MHZ:
mcs_count = 2;
break;
default:
@@ -512,7 +543,8 @@ int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
u8 *mac_cap;
if (!hapd->iface->current_mode ||
- !hapd->iface->current_mode->he_capab[mode].he_supported)
+ !hapd->iface->current_mode->he_capab[mode].he_supported ||
+ !hapd->iconf->ieee80211ax || hapd->conf->disable_11ax)
return 0;
mac_cap = hapd->iface->current_mode->he_capab[mode].mac_cap;
@@ -520,3 +552,19 @@ int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
return !!(mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER) &&
hapd->iface->conf->he_op.he_twt_responder;
}
+
+
+u8 * hostapd_eid_cca(struct hostapd_data *hapd, u8 *eid)
+{
+ if (!hapd->cca_in_progress)
+ return eid;
+
+ /* BSS Color Change Announcement element */
+ *eid++ = WLAN_EID_EXTENSION;
+ *eid++ = 3;
+ *eid++ = WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT;
+ *eid++ = hapd->cca_count; /* Color Switch Countdown */
+ *eid++ = hapd->cca_color; /* New BSS Color Information */
+
+ return eid;
+}