diff options
Diffstat (limited to 'include/linux/ieee80211.h')
| -rw-r--r-- | include/linux/ieee80211.h | 287 | 
1 files changed, 266 insertions, 21 deletions
| diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index c4cf296e7eaf..4b998090898e 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1349,8 +1349,11 @@ struct ieee80211_mgmt {  /* Supported rates membership selectors */  #define BSS_MEMBERSHIP_SELECTOR_HT_PHY	127  #define BSS_MEMBERSHIP_SELECTOR_VHT_PHY	126 -#define BSS_MEMBERSHIP_SELECTOR_HE_PHY	122 +#define BSS_MEMBERSHIP_SELECTOR_GLK	125 +#define BSS_MEMBERSHIP_SELECTOR_EPS	124  #define BSS_MEMBERSHIP_SELECTOR_SAE_H2E 123 +#define BSS_MEMBERSHIP_SELECTOR_HE_PHY	122 +#define BSS_MEMBERSHIP_SELECTOR_EHT_PHY	121  /* mgmt header + 1 byte category code */  #define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) @@ -1993,12 +1996,18 @@ struct ieee80211_mu_edca_param_set {   * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams   *     supported for reception and the maximum number of spatial streams   *     supported for transmission for MCS 12 - 13. + * @rx_tx_max_nss: array of the previous fields for easier loop access   */  struct ieee80211_eht_mcs_nss_supp_20mhz_only { -	u8 rx_tx_mcs7_max_nss; -	u8 rx_tx_mcs9_max_nss; -	u8 rx_tx_mcs11_max_nss; -	u8 rx_tx_mcs13_max_nss; +	union { +		struct { +			u8 rx_tx_mcs7_max_nss; +			u8 rx_tx_mcs9_max_nss; +			u8 rx_tx_mcs11_max_nss; +			u8 rx_tx_mcs13_max_nss; +		}; +		u8 rx_tx_max_nss[4]; +	};  };  /** @@ -2018,11 +2027,17 @@ struct ieee80211_eht_mcs_nss_supp_20mhz_only {   * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams   *     supported for reception and the maximum number of spatial streams   *     supported for transmission for MCS 12 - 13. + * @rx_tx_max_nss: array of the previous fields for easier loop access   */  struct ieee80211_eht_mcs_nss_supp_bw { -	u8 rx_tx_mcs9_max_nss; -	u8 rx_tx_mcs11_max_nss; -	u8 rx_tx_mcs13_max_nss; +	union { +		struct { +			u8 rx_tx_mcs9_max_nss; +			u8 rx_tx_mcs11_max_nss; +			u8 rx_tx_mcs13_max_nss; +		}; +		u8 rx_tx_max_nss[3]; +	};  };  /** @@ -2075,7 +2090,7 @@ struct ieee80211_eht_cap_elem {   */  struct ieee80211_eht_operation {  	u8 params; -	__le32 basic_mcs_nss; +	struct ieee80211_eht_mcs_nss_supp_20mhz_only basic_mcs_nss;  	u8 optional[];  } __packed; @@ -2856,6 +2871,7 @@ ieee80211_he_spr_size(const u8 *he_spr_ie)  /* Maximum number of supported EHT LTF is split */  #define IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK	0xc0 +#define IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF		0x40  #define IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK	0x07  #define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK			0x78 @@ -4477,8 +4493,8 @@ static inline bool for_each_element_completed(const struct element *element,  #define IEEE80211_AP_INFO_TBTT_HDR_FILTERED			0x04  #define IEEE80211_AP_INFO_TBTT_HDR_COLOC			0x08  #define IEEE80211_AP_INFO_TBTT_HDR_COUNT			0xF0 -#define IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM		9 -#define IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM	13 +#define IEEE80211_TBTT_INFO_TYPE_TBTT				0 +#define IEEE80211_TBTT_INFO_TYPE_MLD				1  #define IEEE80211_RNR_TBTT_PARAMS_OCT_RECOMMENDED		0x01  #define IEEE80211_RNR_TBTT_PARAMS_SAME_SSID			0x02 @@ -4488,6 +4504,9 @@ static inline bool for_each_element_completed(const struct element *element,  #define IEEE80211_RNR_TBTT_PARAMS_PROBE_ACTIVE			0x20  #define IEEE80211_RNR_TBTT_PARAMS_COLOC_AP			0x40 +#define IEEE80211_RNR_TBTT_PARAMS_PSD_NO_LIMIT			127 +#define IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED			-128 +  struct ieee80211_neighbor_ap_info {  	u8 tbtt_info_hdr;  	u8 tbtt_info_len; @@ -4502,6 +4521,42 @@ enum ieee80211_range_params_max_total_ltf {  	IEEE80211_RANGE_PARAMS_MAX_TOTAL_LTF_UNSPECIFIED,  }; +/* + * reduced neighbor report, based on Draft P802.11be_D3.0, + * section 9.4.2.170.2. + */ +struct ieee80211_rnr_mld_params { +	u8 mld_id; +	__le16 params; +} __packed; + +#define IEEE80211_RNR_MLD_PARAMS_LINK_ID			0x000F +#define IEEE80211_RNR_MLD_PARAMS_BSS_CHANGE_COUNT		0x0FF0 +#define IEEE80211_RNR_MLD_PARAMS_UPDATES_INCLUDED		0x1000 +#define IEEE80211_RNR_MLD_PARAMS_DISABLED_LINK			0x2000 + +/* Format of the TBTT information element if it has 7, 8 or 9 bytes */ +struct ieee80211_tbtt_info_7_8_9 { +	u8 tbtt_offset; +	u8 bssid[ETH_ALEN]; + +	/* The following element is optional, structure may not grow */ +	u8 bss_params; +	s8 psd_20; +} __packed; + +/* Format of the TBTT information element if it has >= 11 bytes */ +struct ieee80211_tbtt_info_ge_11 { +	u8 tbtt_offset; +	u8 bssid[ETH_ALEN]; +	__le32 short_ssid; + +	/* The following elements are optional, structure may grow */ +	u8 bss_params; +	s8 psd_20; +	struct ieee80211_rnr_mld_params mld_params; +} __packed; +  /* multi-link device */  #define IEEE80211_MLD_MAX_NUM_LINKS	15 @@ -4529,6 +4584,14 @@ struct ieee80211_multi_link_elem {  #define IEEE80211_MED_SYNC_DELAY_SYNC_OFDM_ED_THRESH	0x0f00  #define IEEE80211_MED_SYNC_DELAY_SYNC_MAX_NUM_TXOPS	0xf000 +/* + * Described in P802.11be_D3.0 + * dot11MSDTimerDuration should default to 5484 (i.e. 171.375) + * dot11MSDOFDMEDthreshold defaults to -72 (i.e. 0) + * dot11MSDTXOPMAX defaults to 1 + */ +#define IEEE80211_MED_SYNC_DELAY_DEFAULT		0x10ac +  #define IEEE80211_EML_CAP_EMLSR_SUPP			0x0001  #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY		0x000e  #define  IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_0US		0 @@ -4611,15 +4674,12 @@ static inline u8 ieee80211_mle_common_size(const u8 *data)  	case IEEE80211_ML_CONTROL_TYPE_BASIC:  	case IEEE80211_ML_CONTROL_TYPE_PREQ:  	case IEEE80211_ML_CONTROL_TYPE_TDLS: +	case IEEE80211_ML_CONTROL_TYPE_RECONF:  		/*  		 * The length is the first octet pointed by mle->variable so no  		 * need to add anything  		 */  		break; -	case IEEE80211_ML_CONTROL_TYPE_RECONF: -		if (control & IEEE80211_MLC_RECONF_PRES_MLD_MAC_ADDR) -			common += ETH_ALEN; -		return common;  	case IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS:  		if (control & IEEE80211_MLC_PRIO_ACCESS_PRES_AP_MLD_MAC_ADDR)  			common += ETH_ALEN; @@ -4633,6 +4693,95 @@ static inline u8 ieee80211_mle_common_size(const u8 *data)  }  /** + * ieee80211_mle_get_bss_param_ch_cnt - returns the BSS parameter change count + * @mle: the basic multi link element + * + * The element is assumed to be of the correct type (BASIC) and big enough, + * this must be checked using ieee80211_mle_type_ok(). + * + * If the BSS parameter change count value can't be found (the presence bit + * for it is clear), 0 will be returned. + */ +static inline u8 +ieee80211_mle_get_bss_param_ch_cnt(const struct ieee80211_multi_link_elem *mle) +{ +	u16 control = le16_to_cpu(mle->control); +	const u8 *common = mle->variable; + +	/* common points now at the beginning of ieee80211_mle_basic_common_info */ +	common += sizeof(struct ieee80211_mle_basic_common_info); + +	if (!(control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT)) +		return 0; + +	if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) +		common += 1; + +	return *common; +} + +/** + * ieee80211_mle_get_eml_sync_delay - returns the medium sync delay + * @data: pointer to the multi link EHT IE + * + * The element is assumed to be of the correct type (BASIC) and big enough, + * this must be checked using ieee80211_mle_type_ok(). + * + * If the medium synchronization is not present, then the default value is + * returned. + */ +static inline u16 ieee80211_mle_get_eml_med_sync_delay(const u8 *data) +{ +	const struct ieee80211_multi_link_elem *mle = (const void *)data; +	u16 control = le16_to_cpu(mle->control); +	const u8 *common = mle->variable; + +	/* common points now at the beginning of ieee80211_mle_basic_common_info */ +	common += sizeof(struct ieee80211_mle_basic_common_info); + +	if (!(control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY)) +		return IEEE80211_MED_SYNC_DELAY_DEFAULT; + +	if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) +		common += 1; +	if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) +		common += 1; + +	return get_unaligned_le16(common); +} + +/** + * ieee80211_mle_get_eml_cap - returns the EML capability + * @data: pointer to the multi link EHT IE + * + * The element is assumed to be of the correct type (BASIC) and big enough, + * this must be checked using ieee80211_mle_type_ok(). + * + * If the EML capability is not present, 0 will be returned. + */ +static inline u16 ieee80211_mle_get_eml_cap(const u8 *data) +{ +	const struct ieee80211_multi_link_elem *mle = (const void *)data; +	u16 control = le16_to_cpu(mle->control); +	const u8 *common = mle->variable; + +	/* common points now at the beginning of ieee80211_mle_basic_common_info */ +	common += sizeof(struct ieee80211_mle_basic_common_info); + +	if (!(control & IEEE80211_MLC_BASIC_PRES_EML_CAPA)) +		return 0; + +	if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) +		common += 1; +	if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) +		common += 1; +	if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY) +		common += 2; + +	return get_unaligned_le16(common); +} + +/**   * ieee80211_mle_size_ok - validate multi-link element size   * @data: pointer to the element data   * @len: length of the containing element @@ -4700,6 +4849,28 @@ static inline bool ieee80211_mle_size_ok(const u8 *data, size_t len)  	return mle->variable[0] >= common;  } +/** + * ieee80211_mle_type_ok - validate multi-link element type and size + * @data: pointer to the element data + * @type: expected type of the element + * @len: length of the containing element + */ +static inline bool ieee80211_mle_type_ok(const u8 *data, u8 type, size_t len) +{ +	const struct ieee80211_multi_link_elem *mle = (const void *)data; +	u16 control; + +	if (!ieee80211_mle_size_ok(data, len)) +		return false; + +	control = le16_to_cpu(mle->control); + +	if (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE) == type) +		return true; + +	return false; +} +  enum ieee80211_mle_subelems {  	IEEE80211_MLE_SUBELEM_PER_STA_PROFILE		= 0,  	IEEE80211_MLE_SUBELEM_FRAGMENT		        = 254, @@ -4722,11 +4893,13 @@ struct ieee80211_mle_per_sta_profile {  } __packed;  /** - * ieee80211_mle_sta_prof_size_ok - validate multi-link element sta profile size + * ieee80211_mle_basic_sta_prof_size_ok - validate basic multi-link element sta + *	profile size   * @data: pointer to the sub element data   * @len: length of the containing sub element   */ -static inline bool ieee80211_mle_sta_prof_size_ok(const u8 *data, size_t len) +static inline bool ieee80211_mle_basic_sta_prof_size_ok(const u8 *data, +							size_t len)  {  	const struct ieee80211_mle_per_sta_profile *prof = (const void *)data;  	u16 control; @@ -4746,21 +4919,93 @@ static inline bool ieee80211_mle_sta_prof_size_ok(const u8 *data, size_t len)  		info_len += 8;  	if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT)  		info_len += 2; -	if (control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT) -		info_len += 1; -  	if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE && -	    control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) { +	    control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) {  		if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE)  			info_len += 2;  		else  			info_len += 1;  	} +	if (control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT) +		info_len += 1;  	return prof->sta_info_len >= info_len &&  	       fixed + prof->sta_info_len <= len;  } +/** + * ieee80211_mle_basic_sta_prof_bss_param_ch_cnt - get per-STA profile BSS + *	parameter change count + * @prof: the per-STA profile, having been checked with + *	ieee80211_mle_basic_sta_prof_size_ok() for the correct length + * + * Return: The BSS parameter change count value if present, 0 otherwise. + */ +static inline u8 +ieee80211_mle_basic_sta_prof_bss_param_ch_cnt(const struct ieee80211_mle_per_sta_profile *prof) +{ +	u16 control = le16_to_cpu(prof->control); +	const u8 *pos = prof->variable; + +	if (!(control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT)) +		return 0; + +	if (control & IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT) +		pos += 6; +	if (control & IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT) +		pos += 2; +	if (control & IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT) +		pos += 8; +	if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT) +		pos += 2; +	if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE && +	    control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) { +		if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) +			pos += 2; +		else +			pos += 1; +	} + +	return *pos; +} + +#define IEEE80211_MLE_STA_RECONF_CONTROL_LINK_ID			0x000f +#define IEEE80211_MLE_STA_RECONF_CONTROL_COMPLETE_PROFILE		0x0010 +#define IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT		0x0020 +#define IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT		0x0040 +#define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_UPDATE_TYPE		0x0780 +#define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_PARAMS_PRESENT	0x0800 + +/** + * ieee80211_mle_reconf_sta_prof_size_ok - validate reconfiguration multi-link + *	element sta profile size. + * @data: pointer to the sub element data + * @len: length of the containing sub element + */ +static inline bool ieee80211_mle_reconf_sta_prof_size_ok(const u8 *data, +							 size_t len) +{ +	const struct ieee80211_mle_per_sta_profile *prof = (const void *)data; +	u16 control; +	u8 fixed = sizeof(*prof); +	u8 info_len = 1; + +	if (len < fixed) +		return false; + +	control = le16_to_cpu(prof->control); + +	if (control & IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT) +		info_len += ETH_ALEN; +	if (control & IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT) +		info_len += 2; +	if (control & IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_PARAMS_PRESENT) +		info_len += 2; + +	return prof->sta_info_len >= info_len && +	       fixed + prof->sta_info_len - 1 <= len; +} +  #define for_each_mle_subelement(_elem, _data, _len)			\  	if (ieee80211_mle_size_ok(_data, _len))				\  		for_each_element(_elem,					\ |