2024-02-28 08:42:27

by Johannes Berg

[permalink] [raw]
Subject: [PATCH 0/2] wifi: mac80211: fix HT/VHT capability handling in assoc

Due to errors in the MLME rework, we didn't handle HT properly for the
bandwidth reductions, lost VHT beamforming capabilities, and included
bogus VHT capabilities on 2.4 GHz. Fix those things.

johannes



2024-02-28 08:42:47

by Johannes Berg

[permalink] [raw]
Subject: [PATCH 1/2] wifi: mac80211: don't add VHT capa on links without them

From: Johannes Berg <[email protected]>

When a link doesn't have VHT capability, before the rework
we'd have set IEEE80211_CONN_DISABLE_VHT, but now with the
linear progression of 'mode', we no longer have that. Add
an explicit check for VHT being supported, so we don't add
a zeroed VHT capabilities element where it shouldn't be.

Fixes: 310c8387c638 ("wifi: mac80211: clean up connection process")
Reviewed-by: Miriam Rachel Korenblit <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
---
net/mac80211/mlme.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 5f2e9f5e1779..fa0d679b78f4 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1319,7 +1319,8 @@ static size_t ieee80211_assoc_link_elems(struct ieee80211_sub_if_data *sdata,
offset);

if (sband->band != NL80211_BAND_6GHZ &&
- assoc_data->link[link_id].conn.mode >= IEEE80211_CONN_MODE_VHT) {
+ assoc_data->link[link_id].conn.mode >= IEEE80211_CONN_MODE_VHT &&
+ sband->vht_cap.vht_supported) {
bool mu_mimo_owner =
ieee80211_add_vht_ie(sdata, skb, sband,
&assoc_data->link[link_id].ap_vht_cap,
--
2.43.2


2024-02-28 08:52:26

by Johannes Berg

[permalink] [raw]
Subject: [PATCH 2/2] wifi: mac80211: obtain AP HT/VHT data for assoc request

From: Johannes Berg <[email protected]>

In the association request, we make some parameters depend on the
AP's HT/VHT information. This was broken by my code because it no
longer filled that information, making it all zero.

For HT that meant we wouldn't reduce our capabilities to 20 MHz if
needed, and for VHT we lost beamforming capabilities.

Fix this. It seems like it may even have been broken for all but
the assoc link before.

Fixes: 310c8387c638 ("wifi: mac80211: clean up connection process")
Reviewed-by: Miriam Rachel Korenblit <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
---
net/mac80211/mlme.c | 73 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index fa0d679b78f4..d5678a817771 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -8049,6 +8049,67 @@ ieee80211_setup_assoc_link(struct ieee80211_sub_if_data *sdata,
}
}

+static int
+ieee80211_mgd_get_ap_ht_vht_capa(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_assoc_data *assoc_data,
+ int link_id)
+{
+ struct cfg80211_bss *cbss = assoc_data->link[link_id].bss;
+ enum nl80211_band band = cbss->channel->band;
+ struct ieee80211_supported_band *sband;
+ const struct element *elem;
+ int err;
+
+ /* neither HT nor VHT elements used on 6 GHz */
+ if (band == NL80211_BAND_6GHZ)
+ return 0;
+
+ if (assoc_data->link[link_id].conn.mode < IEEE80211_CONN_MODE_HT)
+ return 0;
+
+ rcu_read_lock();
+ elem = ieee80211_bss_get_elem(cbss, WLAN_EID_HT_OPERATION);
+ if (!elem || elem->datalen < sizeof(struct ieee80211_ht_operation)) {
+ mlme_link_id_dbg(sdata, link_id, "no HT operation on BSS %pM\n",
+ cbss->bssid);
+ err = -EINVAL;
+ goto out_rcu;
+ }
+ assoc_data->link[link_id].ap_ht_param =
+ ((struct ieee80211_ht_operation *)(elem->data))->ht_param;
+ rcu_read_unlock();
+
+ if (assoc_data->link[link_id].conn.mode < IEEE80211_CONN_MODE_VHT)
+ return 0;
+
+ /* some drivers want to support VHT on 2.4 GHz even */
+ sband = sdata->local->hw.wiphy->bands[band];
+ if (!sband->vht_cap.vht_supported)
+ return 0;
+
+ rcu_read_lock();
+ elem = ieee80211_bss_get_elem(cbss, WLAN_EID_VHT_CAPABILITY);
+ /* but even then accept it not being present on the AP */
+ if (!elem && band == NL80211_BAND_2GHZ) {
+ err = 0;
+ goto out_rcu;
+ }
+ if (!elem || elem->datalen < sizeof(struct ieee80211_vht_cap)) {
+ mlme_link_id_dbg(sdata, link_id, "no VHT capa on BSS %pM\n",
+ cbss->bssid);
+ err = -EINVAL;
+ goto out_rcu;
+ }
+ memcpy(&assoc_data->link[link_id].ap_vht_cap, elem->data,
+ sizeof(struct ieee80211_vht_cap));
+ rcu_read_unlock();
+
+ return 0;
+out_rcu:
+ rcu_read_unlock();
+ return err;
+}
+
int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
struct cfg80211_assoc_request *req)
{
@@ -8193,6 +8254,14 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
req->links[i].error = err;
goto err_free;
}
+
+ err = ieee80211_mgd_get_ap_ht_vht_capa(sdata,
+ assoc_data, i);
+ if (err) {
+ err = -EINVAL;
+ req->links[i].error = err;
+ goto err_free;
+ }
}

assoc_data->wmm = true;
@@ -8228,6 +8297,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
&assoc_data->link[0].conn);

uapsd_supported = bss->uapsd_supported;
+
+ err = ieee80211_mgd_get_ap_ht_vht_capa(sdata, assoc_data, 0);
+ if (err)
+ goto err_free;
}

assoc_data->spp_amsdu = req->flags & ASSOC_REQ_SPP_AMSDU;
--
2.43.2