]> www.infradead.org Git - users/hch/misc.git/commitdiff
wifi: iwlwifi: mld: track BIGTK per link
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Thu, 21 Aug 2025 17:47:16 +0000 (20:47 +0300)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Tue, 26 Aug 2025 15:39:44 +0000 (18:39 +0300)
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
drivers/net/wireless/intel/iwlwifi/mld/d3.c
drivers/net/wireless/intel/iwlwifi/mld/iface.h
drivers/net/wireless/intel/iwlwifi/mld/key.c
drivers/net/wireless/intel/iwlwifi/mld/key.h
drivers/net/wireless/intel/iwlwifi/mld/link.h
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
drivers/net/wireless/intel/iwlwifi/mld/rx.c

index 0ac6ceddb44fac5e6c6195a8d1b9be739f8ebc30..da621fe11d62433bbb032f5f48491d00dbcaa196 100644 (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
index 05dcb63701b13ecfc635db43dfef22e006402bab..38e10e279153c1f580d69a97b46a138084f561d0 100644 (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;
index 13462a5ad79ac875593d9468bcd620e522856276..a90477971c7203461024cda64b7fe5feb9b41e00 100644 (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);
+}
index a68ea48913be6bc36db6ce66af312b49e46b681e..63de3469270a2499b25f72aabc7b3b455faccc94 100644 (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__ */
index cad2c9426349afe61a4c5245b9d39cc7745166f7..9e4da8e4de93d18e257f3295b554503b03b5807a 100644 (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;
index b0bd01914a91f03d47a85593e5e790809a123409..f434012b03a63a68d8c230e6ca4b65705d0bb4be 100644 (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 ||
index b6dedd1ecd4d8182ada5d5bc57aa599390d575fc..53cac9d8018cd66d3ec27f004517efdcaed703d7 100644 (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;
        }