diff options
Diffstat (limited to 'src/ap/ieee802_11_he.c')
-rw-r--r-- | src/ap/ieee802_11_he.c | 86 |
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; +} |