* @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];
+ };
};
/**
* @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];
+ };
};
/**
*/
struct ieee80211_eht_operation {
u8 params;
- __le32 basic_mcs_nss;
+ struct ieee80211_eht_mcs_nss_supp_20mhz_only basic_mcs_nss;
u8 optional[];
} __packed;
#define IEEE80211_AP_INFO_TBTT_HDR_COUNT 0xF0
#define IEEE80211_TBTT_INFO_TYPE_TBTT 0
#define IEEE80211_TBTT_INFO_TYPE_MLD 1
-#define IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM 9
-#define IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM 13
#define IEEE80211_RNR_TBTT_PARAMS_OCT_RECOMMENDED 0x01
#define IEEE80211_RNR_TBTT_PARAMS_SAME_SSID 0x02
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[6];
+
+ /* The following element is optional, structure may not grow */
+ u8 bss_params;
+ u8 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[6];
+ __le32 short_ssid;
+
+ /* The following elements are optional, structure may grow */
+ u8 bss_params;
+ u8 psd_20;
+ struct ieee80211_rnr_mld_params mld_params;
+} __packed;
+
/* multi-link device */
#define IEEE80211_MLD_MAX_NUM_LINKS 15
#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
return sizeof(*mle) + common + mle->variable[0];
}
+/**
+ * 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 0 is returned.
+ * 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)
{
common += sizeof(struct ieee80211_mle_basic_common_info);
if (!(control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY))
- return 0;
+ return IEEE80211_MED_SYNC_DELAY_DEFAULT;
if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID)
common += 1;
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) {
if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE)
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_BITMAP_SIZE) {
+ 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 += 6;
+ 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 &&
+ ((size_t)(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, \