Home | History | Annotate | Line # | Download | only in ap
      1 /*
      2  * hostapd / IEEE 802.11ax HE
      3  * Copyright (c) 2016-2017, Qualcomm Atheros, Inc.
      4  * Copyright (c) 2019 John Crispin <john (at) phrozen.org>
      5  *
      6  * This software may be distributed under the terms of the BSD license.
      7  * See README for more details.
      8  */
      9 
     10 #include "utils/includes.h"
     11 
     12 #include "utils/common.h"
     13 #include "common/ieee802_11_defs.h"
     14 #include "common/ieee802_11_common.h"
     15 #include "common/hw_features_common.h"
     16 #include "hostapd.h"
     17 #include "ap_config.h"
     18 #include "beacon.h"
     19 #include "sta_info.h"
     20 #include "ieee802_11.h"
     21 #include "dfs.h"
     22 
     23 static u8 ieee80211_he_ppet_size(u8 ppe_thres_hdr, const u8 *phy_cap_info)
     24 {
     25 	u8 sz = 0, ru;
     26 
     27 	if ((phy_cap_info[HE_PHYCAP_PPE_THRESHOLD_PRESENT_IDX] &
     28 	     HE_PHYCAP_PPE_THRESHOLD_PRESENT) == 0)
     29 		return 0;
     30 
     31 	ru = (ppe_thres_hdr >> HE_PPE_THRES_RU_INDEX_BITMASK_SHIFT) &
     32 		HE_PPE_THRES_RU_INDEX_BITMASK_MASK;
     33 	/* Count the number of 1 bits in RU Index Bitmask */
     34 	while (ru) {
     35 		if (ru & 0x1)
     36 			sz++;
     37 		ru >>= 1;
     38 	}
     39 
     40 	/* fixed header of 3 (NSTS) + 4 (RU Index Bitmask) = 7 bits */
     41 	/* 6 * (NSTS + 1) bits for bit 1 in RU Index Bitmask */
     42 	sz *= 1 + (ppe_thres_hdr & HE_PPE_THRES_NSS_MASK);
     43 	sz = (sz * 6) + 7;
     44 	/* PPE Pad to count the number of needed full octets */
     45 	sz = (sz + 7) / 8;
     46 
     47 	return sz;
     48 }
     49 
     50 
     51 static u8 ieee80211_he_mcs_set_size(const u8 *phy_cap_info)
     52 {
     53 	u8 sz = 4;
     54 
     55 	if (phy_cap_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
     56 	    HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)
     57 		sz += 4;
     58 	if (phy_cap_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
     59 	    HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
     60 		sz += 4;
     61 
     62 	return sz;
     63 }
     64 
     65 
     66 static int ieee80211_invalid_he_cap_size(const u8 *buf, size_t len)
     67 {
     68 	struct ieee80211_he_capabilities *cap;
     69 	size_t cap_len;
     70 	u8 ppe_thres_hdr;
     71 
     72 	cap = (struct ieee80211_he_capabilities *) buf;
     73 	cap_len = sizeof(*cap) - sizeof(cap->optional);
     74 	if (len < cap_len)
     75 		return 1;
     76 
     77 	cap_len += ieee80211_he_mcs_set_size(cap->he_phy_capab_info);
     78 	if (len < cap_len)
     79 		return 1;
     80 
     81 	ppe_thres_hdr = len > cap_len ? buf[cap_len] : 0xff;
     82 	cap_len += ieee80211_he_ppet_size(ppe_thres_hdr,
     83 					  cap->he_phy_capab_info);
     84 
     85 	return len < cap_len;
     86 }
     87 
     88 
     89 u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
     90 			  enum ieee80211_op_mode opmode)
     91 {
     92 	struct ieee80211_he_capabilities *cap;
     93 	struct hostapd_hw_modes *mode = hapd->iface->current_mode;
     94 	u8 he_oper_chwidth = ~HE_PHYCAP_CHANNEL_WIDTH_MASK;
     95 	u8 *pos = eid;
     96 	u8 ie_size = 0, mcs_nss_size = 4, ppet_size = 0;
     97 
     98 	if (!mode)
     99 		return eid;
    100 
    101 	ie_size = sizeof(*cap) - sizeof(cap->optional);
    102 	ppet_size = ieee80211_he_ppet_size(mode->he_capab[opmode].ppet[0],
    103 					   mode->he_capab[opmode].phy_cap);
    104 
    105 	switch (hapd->iface->conf->he_oper_chwidth) {
    106 	case CONF_OPER_CHWIDTH_80P80MHZ:
    107 		he_oper_chwidth |=
    108 			HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G;
    109 		mcs_nss_size += 4;
    110 		/* fall through */
    111 	case CONF_OPER_CHWIDTH_160MHZ:
    112 		he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
    113 		mcs_nss_size += 4;
    114 		/* fall through */
    115 	case CONF_OPER_CHWIDTH_80MHZ:
    116 	case CONF_OPER_CHWIDTH_USE_HT:
    117 		he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
    118 			HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
    119 		break;
    120 	default:
    121 		break;
    122 	}
    123 
    124 	ie_size += mcs_nss_size + ppet_size;
    125 
    126 	*pos++ = WLAN_EID_EXTENSION;
    127 	*pos++ = 1 + ie_size;
    128 	*pos++ = WLAN_EID_EXT_HE_CAPABILITIES;
    129 
    130 	cap = (struct ieee80211_he_capabilities *) pos;
    131 	os_memset(cap, 0, sizeof(*cap));
    132 
    133 	os_memcpy(cap->he_mac_capab_info, mode->he_capab[opmode].mac_cap,
    134 		  HE_MAX_MAC_CAPAB_SIZE);
    135 	os_memcpy(cap->he_phy_capab_info, mode->he_capab[opmode].phy_cap,
    136 		  HE_MAX_PHY_CAPAB_SIZE);
    137 	os_memcpy(cap->optional, mode->he_capab[opmode].mcs, mcs_nss_size);
    138 	if (ppet_size)
    139 		os_memcpy(&cap->optional[mcs_nss_size],
    140 			  mode->he_capab[opmode].ppet,  ppet_size);
    141 
    142 	if (hapd->iface->conf->he_phy_capab.he_su_beamformer)
    143 		cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
    144 			HE_PHYCAP_SU_BEAMFORMER_CAPAB;
    145 	else
    146 		cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] &=
    147 			~HE_PHYCAP_SU_BEAMFORMER_CAPAB;
    148 
    149 	if (hapd->iface->conf->he_phy_capab.he_su_beamformee)
    150 		cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX] |=
    151 			HE_PHYCAP_SU_BEAMFORMEE_CAPAB;
    152 	else
    153 		cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX] &=
    154 			~HE_PHYCAP_SU_BEAMFORMEE_CAPAB;
    155 
    156 	if (hapd->iface->conf->he_phy_capab.he_mu_beamformer)
    157 		cap->he_phy_capab_info[HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX] |=
    158 			HE_PHYCAP_MU_BEAMFORMER_CAPAB;
    159 	else
    160 		cap->he_phy_capab_info[HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX] &=
    161 			~HE_PHYCAP_MU_BEAMFORMER_CAPAB;
    162 
    163 	cap->he_phy_capab_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &=
    164 		he_oper_chwidth;
    165 
    166 	pos += ie_size;
    167 
    168 	return pos;
    169 }
    170 
    171 
    172 u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
    173 {
    174 	struct ieee80211_he_operation *oper;
    175 	u8 *pos = eid;
    176 	int oper_size = 6;
    177 	u32 params = 0;
    178 
    179 	if (!hapd->iface->current_mode)
    180 		return eid;
    181 
    182 	if (is_6ghz_op_class(hapd->iconf->op_class))
    183 		oper_size += 5;
    184 
    185 	*pos++ = WLAN_EID_EXTENSION;
    186 	*pos++ = 1 + oper_size;
    187 	*pos++ = WLAN_EID_EXT_HE_OPERATION;
    188 
    189 	oper = (struct ieee80211_he_operation *) pos;
    190 	os_memset(oper, 0, sizeof(*oper));
    191 
    192 	if (hapd->iface->conf->he_op.he_default_pe_duration)
    193 		params |= (hapd->iface->conf->he_op.he_default_pe_duration <<
    194 			   HE_OPERATION_DFLT_PE_DURATION_OFFSET);
    195 
    196 	if (hapd->iface->conf->he_op.he_twt_required)
    197 		params |= HE_OPERATION_TWT_REQUIRED;
    198 
    199 	if (hapd->iface->conf->he_op.he_rts_threshold)
    200 		params |= (hapd->iface->conf->he_op.he_rts_threshold <<
    201 			   HE_OPERATION_RTS_THRESHOLD_OFFSET);
    202 
    203 	if (hapd->iface->conf->he_op.he_er_su_disable)
    204 		params |= HE_OPERATION_ER_SU_DISABLE;
    205 
    206 	if (hapd->iface->conf->he_op.he_bss_color_disabled ||
    207 	    hapd->cca_in_progress)
    208 		params |= HE_OPERATION_BSS_COLOR_DISABLED;
    209 	if (hapd->iface->conf->he_op.he_bss_color_partial)
    210 		params |= HE_OPERATION_BSS_COLOR_PARTIAL;
    211 	params |= hapd->iface->conf->he_op.he_bss_color <<
    212 		HE_OPERATION_BSS_COLOR_OFFSET;
    213 
    214 	/* HE minimum required basic MCS and NSS for STAs */
    215 	oper->he_mcs_nss_set =
    216 		host_to_le16(hapd->iface->conf->he_op.he_basic_mcs_nss_set);
    217 
    218 	/* TODO: conditional MaxBSSID Indicator subfield */
    219 
    220 	pos += 6; /* skip the fixed part */
    221 
    222 	if (is_6ghz_op_class(hapd->iconf->op_class)) {
    223 		enum oper_chan_width oper_chwidth =
    224 			hostapd_get_oper_chwidth(hapd->iconf);
    225 		u8 seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx;
    226 		u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
    227 		u8 control;
    228 #ifdef CONFIG_IEEE80211BE
    229 		u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
    230 
    231 		if (punct_bitmap) {
    232 			punct_update_legacy_bw(punct_bitmap,
    233 					       hapd->iconf->channel,
    234 					       &oper_chwidth, &seg0, &seg1);
    235 		}
    236 #endif /* CONFIG_IEEE80211BE */
    237 
    238 		if (!seg0)
    239 			seg0 = hapd->iconf->channel;
    240 
    241 		params |= HE_OPERATION_6GHZ_OPER_INFO;
    242 
    243 		/* 6 GHz Operation Information field
    244 		 * IEEE Std 802.11ax-2021, 9.4.2.249 HE Operation element,
    245 		 * Figure 9-788k
    246 		 */
    247 		*pos++ = hapd->iconf->channel; /* Primary Channel */
    248 
    249 		/* Control:
    250 		 *	bits 0-1: Channel Width
    251 		 *	bit 2: Duplicate Beacon
    252 		 *	bits 3-5: Regulatory Info
    253 		 */
    254 		/* Channel Width */
    255 		if (seg1)
    256 			control = 3;
    257 		else
    258 			control = center_idx_to_bw_6ghz(seg0);
    259 
    260 		control |= hapd->iconf->he_6ghz_reg_pwr_type <<
    261 			HE_6GHZ_OPER_INFO_CTRL_REG_INFO_SHIFT;
    262 
    263 		*pos++ = control;
    264 
    265 		/* Channel Center Freq Seg0/Seg1 */
    266 		if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ ||
    267 		    oper_chwidth == CONF_OPER_CHWIDTH_320MHZ) {
    268 			/*
    269 			 * Seg 0 indicates the channel center frequency index of
    270 			 * the 160 MHz channel.
    271 			 */
    272 			seg1 = seg0;
    273 			if (hapd->iconf->channel < seg0)
    274 				seg0 -= 8;
    275 			else
    276 				seg0 += 8;
    277 		}
    278 
    279 		*pos++ = seg0;
    280 		*pos++ = seg1;
    281 		/* Minimum Rate */
    282 		*pos++ = 6; /* TODO: what should be set here? */
    283 	}
    284 
    285 	oper->he_oper_params = host_to_le32(params);
    286 
    287 	return pos;
    288 }
    289 
    290 
    291 u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid)
    292 {
    293 	struct ieee80211_he_mu_edca_parameter_set *edca;
    294 	u8 *pos;
    295 	size_t i;
    296 
    297 	pos = (u8 *) &hapd->iface->conf->he_mu_edca;
    298 	for (i = 0; i < sizeof(*edca); i++) {
    299 		if (pos[i])
    300 			break;
    301 	}
    302 	if (i == sizeof(*edca))
    303 		return eid; /* no MU EDCA Parameters configured */
    304 
    305 	pos = eid;
    306 	*pos++ = WLAN_EID_EXTENSION;
    307 	*pos++ = 1 + sizeof(*edca);
    308 	*pos++ = WLAN_EID_EXT_HE_MU_EDCA_PARAMS;
    309 
    310 	edca = (struct ieee80211_he_mu_edca_parameter_set *) pos;
    311 	os_memcpy(edca, &hapd->iface->conf->he_mu_edca, sizeof(*edca));
    312 
    313 	wpa_hexdump(MSG_DEBUG, "HE: MU EDCA Parameter Set element",
    314 		    pos, sizeof(*edca));
    315 
    316 	pos += sizeof(*edca);
    317 
    318 	return pos;
    319 }
    320 
    321 
    322 u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid)
    323 {
    324 	struct ieee80211_spatial_reuse *spr;
    325 	u8 *pos = eid, *spr_param;
    326 	u8 sz = 1;
    327 
    328 	if (!hapd->iface->conf->spr.sr_control)
    329 		return eid;
    330 
    331 	if (hapd->iface->conf->spr.sr_control &
    332 	    SPATIAL_REUSE_NON_SRG_OFFSET_PRESENT)
    333 		sz++;
    334 
    335 	if (hapd->iface->conf->spr.sr_control &
    336 	    SPATIAL_REUSE_SRG_INFORMATION_PRESENT)
    337 		sz += 18;
    338 
    339 	*pos++ = WLAN_EID_EXTENSION;
    340 	*pos++ = 1 + sz;
    341 	*pos++ = WLAN_EID_EXT_SPATIAL_REUSE;
    342 
    343 	spr = (struct ieee80211_spatial_reuse *) pos;
    344 	os_memset(spr, 0, sizeof(*spr));
    345 
    346 	spr->sr_ctrl = hapd->iface->conf->spr.sr_control;
    347 	pos++;
    348 	spr_param = spr->params;
    349 	if (spr->sr_ctrl & SPATIAL_REUSE_NON_SRG_OFFSET_PRESENT) {
    350 		*spr_param++ =
    351 			hapd->iface->conf->spr.non_srg_obss_pd_max_offset;
    352 		pos++;
    353 	}
    354 	if (spr->sr_ctrl & SPATIAL_REUSE_SRG_INFORMATION_PRESENT) {
    355 		*spr_param++ = hapd->iface->conf->spr.srg_obss_pd_min_offset;
    356 		*spr_param++ = hapd->iface->conf->spr.srg_obss_pd_max_offset;
    357 		os_memcpy(spr_param,
    358 			  hapd->iface->conf->spr.srg_bss_color_bitmap, 8);
    359 		spr_param += 8;
    360 		os_memcpy(spr_param,
    361 			  hapd->iface->conf->spr.srg_partial_bssid_bitmap, 8);
    362 		pos += 18;
    363 	}
    364 
    365 	return pos;
    366 }
    367 
    368 
    369 u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid)
    370 {
    371 	struct hostapd_config *conf = hapd->iface->conf;
    372 	struct hostapd_hw_modes *mode = hapd->iface->current_mode;
    373 	struct he_capabilities *he_cap;
    374 	struct ieee80211_he_6ghz_band_cap *cap;
    375 	u16 capab;
    376 	u8 *pos;
    377 
    378 	if (!mode || !is_6ghz_op_class(hapd->iconf->op_class) ||
    379 	    !is_6ghz_freq(hapd->iface->freq))
    380 		return eid;
    381 
    382 	he_cap = &mode->he_capab[IEEE80211_MODE_AP];
    383 	capab = he_cap->he_6ghz_capa & HE_6GHZ_BAND_CAP_MIN_MPDU_START;
    384 	capab |= (conf->he_6ghz_max_ampdu_len_exp <<
    385 		  HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_SHIFT) &
    386 		HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_MASK;
    387 	capab |= (conf->he_6ghz_max_mpdu <<
    388 		  HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_SHIFT) &
    389 		HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_MASK;
    390 	capab |= HE_6GHZ_BAND_CAP_SMPS_DISABLED;
    391 	if (conf->he_6ghz_rx_ant_pat)
    392 		capab |= HE_6GHZ_BAND_CAP_RX_ANTPAT_CONS;
    393 	if (conf->he_6ghz_tx_ant_pat)
    394 		capab |= HE_6GHZ_BAND_CAP_TX_ANTPAT_CONS;
    395 
    396 	pos = eid;
    397 	*pos++ = WLAN_EID_EXTENSION;
    398 	*pos++ = 1 + sizeof(*cap);
    399 	*pos++ = WLAN_EID_EXT_HE_6GHZ_BAND_CAP;
    400 
    401 	cap = (struct ieee80211_he_6ghz_band_cap *) pos;
    402 	cap->capab = host_to_le16(capab);
    403 	pos += sizeof(*cap);
    404 
    405 	return pos;
    406 }
    407 
    408 
    409 void hostapd_get_he_capab(struct hostapd_data *hapd,
    410 			  const struct ieee80211_he_capabilities *he_cap,
    411 			  struct ieee80211_he_capabilities *neg_he_cap,
    412 			  size_t he_capab_len)
    413 {
    414 	if (!he_cap)
    415 		return;
    416 
    417 	if (he_capab_len > sizeof(*neg_he_cap))
    418 		he_capab_len = sizeof(*neg_he_cap);
    419 	/* TODO: mask out unsupported features */
    420 
    421 	os_memcpy(neg_he_cap, he_cap, he_capab_len);
    422 }
    423 
    424 
    425 static int check_valid_he_mcs(struct hostapd_data *hapd, const u8 *sta_he_capab,
    426 			      enum ieee80211_op_mode opmode)
    427 {
    428 	u16 sta_rx_mcs_set, ap_tx_mcs_set;
    429 	u8 mcs_count = 0;
    430 	const u16 *ap_mcs_set, *sta_mcs_set;
    431 	int i;
    432 
    433 	if (!hapd->iface->current_mode)
    434 		return 1;
    435 	ap_mcs_set = (u16 *) hapd->iface->current_mode->he_capab[opmode].mcs;
    436 	sta_mcs_set = (u16 *) ((const struct ieee80211_he_capabilities *)
    437 			       sta_he_capab)->optional;
    438 
    439 	/*
    440 	 * Disable HE capabilities for STAs for which there is not even a single
    441 	 * allowed MCS in any supported number of streams, i.e., STA is
    442 	 * advertising 3 (not supported) as HE MCS rates for all supported
    443 	 * band/stream cases.
    444 	 */
    445 	switch (hapd->iface->conf->he_oper_chwidth) {
    446 	case CONF_OPER_CHWIDTH_80P80MHZ:
    447 		mcs_count = 3;
    448 		break;
    449 	case CONF_OPER_CHWIDTH_160MHZ:
    450 		mcs_count = 2;
    451 		break;
    452 	default:
    453 		mcs_count = 1;
    454 		break;
    455 	}
    456 
    457 	for (i = 0; i < mcs_count; i++) {
    458 		int j;
    459 
    460 		/* AP Tx MCS map vs. STA Rx MCS map */
    461 		sta_rx_mcs_set = WPA_GET_LE16((const u8 *) &sta_mcs_set[i * 2]);
    462 		ap_tx_mcs_set = WPA_GET_LE16((const u8 *)
    463 					     &ap_mcs_set[(i * 2) + 1]);
    464 
    465 		for (j = 0; j < HE_NSS_MAX_STREAMS; j++) {
    466 			if (((ap_tx_mcs_set >> (j * 2)) & 0x3) == 3)
    467 				continue;
    468 
    469 			if (((sta_rx_mcs_set >> (j * 2)) & 0x3) == 3)
    470 				continue;
    471 
    472 			return 1;
    473 		}
    474 	}
    475 
    476 	wpa_printf(MSG_DEBUG,
    477 		   "No matching HE MCS found between AP TX and STA RX");
    478 
    479 	return 0;
    480 }
    481 
    482 
    483 u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
    484 		      enum ieee80211_op_mode opmode, const u8 *he_capab,
    485 		      size_t he_capab_len)
    486 {
    487 	if (!he_capab || !(sta->flags & WLAN_STA_WMM) ||
    488 	    !hapd->iconf->ieee80211ax || hapd->conf->disable_11ax ||
    489 	    !check_valid_he_mcs(hapd, he_capab, opmode) ||
    490 	    ieee80211_invalid_he_cap_size(he_capab, he_capab_len) ||
    491 	    he_capab_len > sizeof(struct ieee80211_he_capabilities)) {
    492 		sta->flags &= ~WLAN_STA_HE;
    493 		os_free(sta->he_capab);
    494 		sta->he_capab = NULL;
    495 		return WLAN_STATUS_SUCCESS;
    496 	}
    497 
    498 	if (!sta->he_capab) {
    499 		sta->he_capab =
    500 			os_zalloc(sizeof(struct ieee80211_he_capabilities));
    501 		if (!sta->he_capab)
    502 			return WLAN_STATUS_UNSPECIFIED_FAILURE;
    503 	}
    504 
    505 	sta->flags |= WLAN_STA_HE;
    506 	os_memset(sta->he_capab, 0, sizeof(struct ieee80211_he_capabilities));
    507 	os_memcpy(sta->he_capab, he_capab, he_capab_len);
    508 	sta->he_capab_len = he_capab_len;
    509 
    510 	return WLAN_STATUS_SUCCESS;
    511 }
    512 
    513 
    514 u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta,
    515 			   const u8 *he_6ghz_capab)
    516 {
    517 	if (!he_6ghz_capab || !hapd->iconf->ieee80211ax ||
    518 	    hapd->conf->disable_11ax ||
    519 	    !is_6ghz_op_class(hapd->iconf->op_class)) {
    520 		sta->flags &= ~WLAN_STA_6GHZ;
    521 		os_free(sta->he_6ghz_capab);
    522 		sta->he_6ghz_capab = NULL;
    523 		return WLAN_STATUS_SUCCESS;
    524 	}
    525 
    526 	if (!sta->he_6ghz_capab) {
    527 		sta->he_6ghz_capab =
    528 			os_zalloc(sizeof(struct ieee80211_he_6ghz_band_cap));
    529 		if (!sta->he_6ghz_capab)
    530 			return WLAN_STATUS_UNSPECIFIED_FAILURE;
    531 	}
    532 
    533 	sta->flags |= WLAN_STA_6GHZ;
    534 	os_memcpy(sta->he_6ghz_capab, he_6ghz_capab,
    535 		  sizeof(struct ieee80211_he_6ghz_band_cap));
    536 
    537 	return WLAN_STATUS_SUCCESS;
    538 }
    539 
    540 
    541 int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
    542 				 enum ieee80211_op_mode mode)
    543 {
    544 	u8 *mac_cap;
    545 
    546 	if (!hapd->iface->current_mode ||
    547 	    !hapd->iface->current_mode->he_capab[mode].he_supported ||
    548 	    !hapd->iconf->ieee80211ax || hapd->conf->disable_11ax)
    549 		return 0;
    550 
    551 	mac_cap = hapd->iface->current_mode->he_capab[mode].mac_cap;
    552 
    553 	return !!(mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER) &&
    554 		hapd->iface->conf->he_op.he_twt_responder;
    555 }
    556 
    557 
    558 u8 * hostapd_eid_cca(struct hostapd_data *hapd, u8 *eid)
    559 {
    560 	if (!hapd->cca_in_progress)
    561 		return eid;
    562 
    563 	/* BSS Color Change Announcement element */
    564 	*eid++ = WLAN_EID_EXTENSION;
    565 	*eid++ = 3;
    566 	*eid++ = WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT;
    567 	*eid++ = hapd->cca_count; /* Color Switch Countdown */
    568 	*eid++ = hapd->cca_color; /* New BSS Color Information */
    569 
    570 	return eid;
    571 }
    572