wifi: iwlwifi: mld: track BIGTK per link

We track the BIGTKs installed for beacon protection purposes.
But in MLO we will have a different BIGTK per link.
Track the BIGTK per-link and not per-vif.

Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250821204455.0392769d3abb.I5d8e232d663e3ca8fc23de12dd8534cb076cabb9@changeid
This commit is contained in:
Miri Korenblit 2025-08-21 20:47:16 +03:00
parent 33d958b39a
commit 8925c7876c
7 changed files with 49 additions and 18 deletions

View File

@ -11,6 +11,7 @@
#include "mcc.h"
#include "sta.h"
#include "mlo.h"
#include "key.h"
#include "fw/api/d3.h"
#include "fw/api/offload.h"
@ -825,12 +826,8 @@ iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif,
}
/* Also keep track of the new BIGTK */
if ((key_config->keyidx == 6 || key_config->keyidx == 7) &&
vif->type == NL80211_IFTYPE_STATION) {
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
rcu_assign_pointer(mld_vif->bigtks[key_config->keyidx - 6], key_config);
}
if (key_config->keyidx == 6 || key_config->keyidx == 7)
iwl_mld_track_bigtk(mld, vif, key_config, true);
}
static void

View File

@ -125,8 +125,6 @@ struct iwl_mld_emlsr {
* @ap_sta: pointer to AP sta, for easier access to it.
* Relevant only for STA vifs.
* @authorized: indicates the AP station was set to authorized
* @bigtks: BIGTKs of the AP, for beacon protection.
* Only valid for STA. (FIXME: needs to be per link)
* @num_associated_stas: number of associated STAs. Relevant only for AP mode.
* @ap_ibss_active: whether the AP/IBSS was started
* @cca_40mhz_workaround: When we are connected in 2.4 GHz and 40 MHz, and the
@ -158,7 +156,6 @@ struct iwl_mld_vif {
struct iwl_mld_session_protect session_protect;
struct ieee80211_sta *ap_sta;
bool authorized;
struct ieee80211_key_conf __rcu *bigtks[2];
u8 num_associated_stas;
bool ap_ibss_active;
enum iwl_mld_cca_40mhz_wa_status cca_40mhz_workaround;

View File

@ -368,3 +368,29 @@ int iwl_mld_update_sta_keys(struct iwl_mld *mld,
&data);
return data.err;
}
void iwl_mld_track_bigtk(struct iwl_mld *mld,
struct ieee80211_vif *vif,
struct ieee80211_key_conf *key, bool add)
{
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
struct iwl_mld_link *link;
if (vif->type != NL80211_IFTYPE_STATION)
return;
if (WARN_ON(key->keyidx < 6 || key->keyidx > 7))
return;
if (WARN_ON(key->link_id < 0))
return;
link = iwl_mld_link_dereference_check(mld_vif, key->link_id);
if (WARN_ON(!link))
return;
if (add)
rcu_assign_pointer(link->bigtks[key->keyidx - 6], key);
else
RCU_INIT_POINTER(link->bigtks[key->keyidx - 6], NULL);
}

View File

@ -36,4 +36,8 @@ iwl_mld_cleanup_keys_iter(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
key->hw_key_idx = STA_KEY_IDX_INVALID;
}
void iwl_mld_track_bigtk(struct iwl_mld *mld,
struct ieee80211_vif *vif,
struct ieee80211_key_conf *key, bool add);
#endif /* __iwl_mld_key_h__ */

View File

@ -36,6 +36,7 @@ struct iwl_probe_resp_data {
* @he_ru_2mhz_block: 26-tone RU OFDMA transmissions should be blocked.
* @igtk: fw can only have one IGTK at a time, whereas mac80211 can have two.
* This tracks the one IGTK that currently exists in FW.
* @bigtks: BIGTKs of the AP. Only valid for STA mode.
* @bcast_sta: station used for broadcast packets. Used in AP, GO and IBSS.
* @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS.
* @mon_sta: station used for TX injection in monitor interface.
@ -59,6 +60,7 @@ struct iwl_mld_link {
struct ieee80211_chanctx_conf __rcu *chan_ctx;
bool he_ru_2mhz_block;
struct ieee80211_key_conf *igtk;
struct ieee80211_key_conf __rcu *bigtks[2];
);
/* And here fields that survive a fw restart */
struct iwl_mld_int_sta bcast_sta;

View File

@ -2065,9 +2065,8 @@ static int iwl_mld_set_key_add(struct iwl_mld *mld,
return -EOPNOTSUPP;
}
if (vif->type == NL80211_IFTYPE_STATION &&
(keyidx == 6 || keyidx == 7))
rcu_assign_pointer(mld_vif->bigtks[keyidx - 6], key);
if (keyidx == 6 || keyidx == 7)
iwl_mld_track_bigtk(mld, vif, key, true);
/* After exiting from RFKILL, hostapd configures GTK/ITGK before the
* AP is started, but those keys can't be sent to the FW before the
@ -2116,9 +2115,8 @@ static void iwl_mld_set_key_remove(struct iwl_mld *mld,
sta ? iwl_mld_sta_from_mac80211(sta) : NULL;
int keyidx = key->keyidx;
if (vif->type == NL80211_IFTYPE_STATION &&
(keyidx == 6 || keyidx == 7))
RCU_INIT_POINTER(mld_vif->bigtks[keyidx - 6], NULL);
if (keyidx == 6 || keyidx == 7)
iwl_mld_track_bigtk(mld, vif, key, false);
if (mld_sta && key->flags & IEEE80211_KEY_FLAG_PAIRWISE &&
(key->cipher == WLAN_CIPHER_SUITE_CCMP ||

View File

@ -1619,12 +1619,14 @@ static int iwl_mld_rx_mgmt_prot(struct ieee80211_sta *sta,
u32 mpdu_status,
u32 mpdu_len)
{
struct iwl_mld_link *link;
struct wireless_dev *wdev;
struct iwl_mld_sta *mld_sta;
struct iwl_mld_vif *mld_vif;
u8 keyidx;
struct ieee80211_key_conf *key;
const u8 *frame = (void *)hdr;
u8 link_id;
if ((mpdu_status & IWL_RX_MPDU_STATUS_SEC_MASK) ==
IWL_RX_MPDU_STATUS_SEC_NONE)
@ -1657,12 +1659,17 @@ static int iwl_mld_rx_mgmt_prot(struct ieee80211_sta *sta,
return 0;
}
link_id = rx_status->link_valid ? rx_status->link_id : 0;
link = rcu_dereference(mld_vif->link[link_id]);
if (WARN_ON_ONCE(!link))
return -1;
/* both keys will have the same cipher and MIC length, use
* whichever one is available
*/
key = rcu_dereference(mld_vif->bigtks[0]);
key = rcu_dereference(link->bigtks[0]);
if (!key) {
key = rcu_dereference(mld_vif->bigtks[1]);
key = rcu_dereference(link->bigtks[1]);
if (!key)
goto report;
}
@ -1680,7 +1687,7 @@ static int iwl_mld_rx_mgmt_prot(struct ieee80211_sta *sta,
if (keyidx != 6 && keyidx != 7)
return -1;
key = rcu_dereference(mld_vif->bigtks[keyidx - 6]);
key = rcu_dereference(link->bigtks[keyidx - 6]);
if (!key)
goto report;
}