mirror of
https://github.com/torvalds/linux.git
synced 2026-05-13 08:39:31 +02:00
wifi: mac80211: add HT and VHT basic set verification
So far we did not verify the HT and VHT basic MCS set. However, in P802.11REVme/D7.0 (6.5.4.2.4) says that the MLME-JOIN.request shall return an error if the VHT and HT basic set requirements are not met. Given broken APs, apply VHT basic MCS/NSS set checks only in strict mode. Signed-off-by: Benjamin Berg <benjamin.berg@intel.com> Reviewed-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20250205110958.e2d8d4095f6b.I66bcf6c2de3b9d3325e4ffd9f573f4cd26ce5685@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
7364a4688b
commit
574faa0e93
|
|
@ -345,6 +345,115 @@ ieee80211_determine_ap_chan(struct ieee80211_sub_if_data *sdata,
|
|||
return IEEE80211_CONN_MODE_EHT;
|
||||
}
|
||||
|
||||
static bool
|
||||
ieee80211_verify_sta_ht_mcs_support(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_supported_band *sband,
|
||||
const struct ieee80211_ht_operation *ht_op)
|
||||
{
|
||||
struct ieee80211_sta_ht_cap sta_ht_cap;
|
||||
int i;
|
||||
|
||||
if (sband->band == NL80211_BAND_6GHZ)
|
||||
return true;
|
||||
|
||||
if (!ht_op)
|
||||
return false;
|
||||
|
||||
memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap));
|
||||
ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);
|
||||
|
||||
/*
|
||||
* P802.11REVme/D7.0 - 6.5.4.2.4
|
||||
* ...
|
||||
* If the MLME of an HT STA receives an MLME-JOIN.request primitive
|
||||
* with the SelectedBSS parameter containing a Basic HT-MCS Set field
|
||||
* in the HT Operation parameter that contains any unsupported MCSs,
|
||||
* the MLME response in the resulting MLME-JOIN.confirm primitive shall
|
||||
* contain a ResultCode parameter that is not set to the value SUCCESS.
|
||||
* ...
|
||||
*/
|
||||
|
||||
/* Simply check that all basic rates are in the STA RX mask */
|
||||
for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
|
||||
if ((ht_op->basic_set[i] & sta_ht_cap.mcs.rx_mask[i]) !=
|
||||
ht_op->basic_set[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ieee80211_verify_sta_vht_mcs_support(struct ieee80211_sub_if_data *sdata,
|
||||
int link_id,
|
||||
struct ieee80211_supported_band *sband,
|
||||
const struct ieee80211_vht_operation *vht_op)
|
||||
{
|
||||
struct ieee80211_sta_vht_cap sta_vht_cap;
|
||||
u16 ap_min_req_set, sta_rx_mcs_map, sta_tx_mcs_map;
|
||||
int nss;
|
||||
|
||||
if (sband->band != NL80211_BAND_5GHZ)
|
||||
return true;
|
||||
|
||||
if (!vht_op)
|
||||
return false;
|
||||
|
||||
memcpy(&sta_vht_cap, &sband->vht_cap, sizeof(sta_vht_cap));
|
||||
ieee80211_apply_vhtcap_overrides(sdata, &sta_vht_cap);
|
||||
|
||||
ap_min_req_set = le16_to_cpu(vht_op->basic_mcs_set);
|
||||
sta_rx_mcs_map = le16_to_cpu(sta_vht_cap.vht_mcs.rx_mcs_map);
|
||||
sta_tx_mcs_map = le16_to_cpu(sta_vht_cap.vht_mcs.tx_mcs_map);
|
||||
|
||||
/*
|
||||
* Many APs are incorrectly advertising an all-zero value here,
|
||||
* which really means MCS 0-7 are required for 1-8 streams, but
|
||||
* they don't really mean it that way.
|
||||
* Some other APs are incorrectly advertising 3 spatial streams
|
||||
* with MCS 0-7 are required, but don't really mean it that way
|
||||
* and we'll connect only with HT, rather than even HE.
|
||||
* As a result, unfortunately the VHT basic MCS/NSS set cannot
|
||||
* be used at all, so check it only in strict mode.
|
||||
*/
|
||||
if (!ieee80211_hw_check(&sdata->local->hw, STRICT))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* P802.11REVme/D7.0 - 6.5.4.2.4
|
||||
* ...
|
||||
* If the MLME of a VHT STA receives an MLME-JOIN.request primitive
|
||||
* with a SelectedBSS parameter containing a Basic VHT-MCS And NSS Set
|
||||
* field in the VHT Operation parameter that contains any unsupported
|
||||
* <VHT-MCS, NSS> tuple, the MLME response in the resulting
|
||||
* MLME-JOIN.confirm primitive shall contain a ResultCode parameter
|
||||
* that is not set to the value SUCCESS.
|
||||
* ...
|
||||
*/
|
||||
for (nss = 8; nss > 0; nss--) {
|
||||
u8 ap_op_val = (ap_min_req_set >> (2 * (nss - 1))) & 3;
|
||||
u8 sta_rx_val;
|
||||
u8 sta_tx_val;
|
||||
|
||||
if (ap_op_val == IEEE80211_HE_MCS_NOT_SUPPORTED)
|
||||
continue;
|
||||
|
||||
sta_rx_val = (sta_rx_mcs_map >> (2 * (nss - 1))) & 3;
|
||||
sta_tx_val = (sta_tx_mcs_map >> (2 * (nss - 1))) & 3;
|
||||
|
||||
if (sta_rx_val == IEEE80211_HE_MCS_NOT_SUPPORTED ||
|
||||
sta_tx_val == IEEE80211_HE_MCS_NOT_SUPPORTED ||
|
||||
sta_rx_val < ap_op_val || sta_tx_val < ap_op_val) {
|
||||
link_id_info(sdata, link_id,
|
||||
"Missing mandatory rates for %d Nss, rx %d, tx %d oper %d, disable VHT\n",
|
||||
nss, sta_rx_val, sta_tx_val, ap_op_val);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ieee80211_verify_peer_he_mcs_support(struct ieee80211_sub_if_data *sdata,
|
||||
int link_id,
|
||||
|
|
@ -1042,6 +1151,26 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
|
|||
link_id_info(sdata, link_id,
|
||||
"regulatory prevented using AP config, downgraded\n");
|
||||
|
||||
if (conn->mode >= IEEE80211_CONN_MODE_HT &&
|
||||
!ieee80211_verify_sta_ht_mcs_support(sdata, sband,
|
||||
elems->ht_operation)) {
|
||||
conn->mode = IEEE80211_CONN_MODE_LEGACY;
|
||||
conn->bw_limit = IEEE80211_CONN_BW_LIMIT_20;
|
||||
link_id_info(sdata, link_id,
|
||||
"required MCSes not supported, disabling HT\n");
|
||||
}
|
||||
|
||||
if (conn->mode >= IEEE80211_CONN_MODE_VHT &&
|
||||
!ieee80211_verify_sta_vht_mcs_support(sdata, link_id, sband,
|
||||
elems->vht_operation)) {
|
||||
conn->mode = IEEE80211_CONN_MODE_HT;
|
||||
conn->bw_limit = min_t(enum ieee80211_conn_bw_limit,
|
||||
conn->bw_limit,
|
||||
IEEE80211_CONN_BW_LIMIT_40);
|
||||
link_id_info(sdata, link_id,
|
||||
"required MCSes not supported, disabling VHT\n");
|
||||
}
|
||||
|
||||
if (conn->mode >= IEEE80211_CONN_MODE_HE &&
|
||||
(!ieee80211_verify_peer_he_mcs_support(sdata, link_id,
|
||||
(void *)elems->he_cap,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user