* @nan.mgmt_sta: internal station used for NAN management frames, e.g., SDFs
* and NAFs.
* @nan.mcast_data_sta: internal station used for multicast NAN Data frames.
+ * @nan.tx_igtk: TX IGTK key for NAN, tracked separately since NAN does not
+ * use the vif links.
*/
struct iwl_mld_vif {
/* Add here fields that need clean up on restart */
struct iwl_mld_int_sta bcast_sta;
struct iwl_mld_int_sta mgmt_sta;
struct iwl_mld_int_sta mcast_data_sta;
+ struct ieee80211_key_conf *tx_igtk;
} nan;
struct iwl_mld_emlsr emlsr;
lockdep_assert_wiphy(mld->wiphy);
+ if (vif->type == NL80211_IFTYPE_NAN_DATA && !sta) {
+ /* Older firmware versions do not support transmission of
+ * multicast data frames.
+ */
+ if (!iwl_mld_nan_use_nan_stations(mld))
+ return 0;
+
+ if (WARN_ON(mld_vif->nan.mcast_data_sta.sta_id ==
+ IWL_INVALID_STA))
+ return 0;
+
+ return BIT(mld_vif->nan.mcast_data_sta.sta_id);
+ }
+
+ if (vif->type == NL80211_IFTYPE_NAN && !sta) {
+ /* Older firmware versions do not support installation of
+ * IGTK/BIGTK keys.
+ */
+ if (!iwl_mld_nan_use_nan_stations(mld))
+ return 0;
+
+ if (WARN_ON(mld_vif->nan.bcast_sta.sta_id == IWL_INVALID_STA ||
+ mld_vif->nan.mgmt_sta.sta_id == IWL_INVALID_STA))
+ return 0;
+
+ if (key->keyidx >= 4 && key->keyidx <= 5)
+ return BIT(mld_vif->nan.mgmt_sta.sta_id);
+
+ if (key->keyidx >= 6 && key->keyidx <= 7)
+ return BIT(mld_vif->nan.bcast_sta.sta_id);
+
+ return 0;
+ }
+
/* AP group keys are per link and should be on the mcast/bcast STA */
if (vif->type == NL80211_IFTYPE_AP &&
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
return &mld_sta->deflink.rx_igtk;
}
- return &mld_vif->deflink.tx_igtk;
+ return &mld_vif->nan.tx_igtk;
case NL80211_IFTYPE_AP:
mld_link = iwl_mld_link_dereference_check(mld_vif, link_id);
if (WARN_ON(!mld_link))
lockdep_assert_wiphy(mld->wiphy);
- if (!sta_mask)
+ if (!sta_mask) {
+ /* for NAN (GTK) indicate SW-only, it's not used at all */
+ if (vif->type == NL80211_IFTYPE_NAN_DATA && !sta &&
+ !iwl_mld_nan_use_nan_stations(mld))
+ return 1;
+
+ /* otherwise that's not valid */
+ IWL_WARN(mld, "empty STA mask for key %d\n", key->keyidx);
return -EINVAL;
+ }
igtk_ptr = iwl_mld_get_igtk_ptr(vif, sta, key);
if (igtk_ptr) {
}
ret = iwl_mld_add_key_to_fw(mld, sta_mask, key_flags, key);
- if (ret)
+ if (ret) {
+ IWL_WARN(mld, "failed to add key to FW (%d)\n", ret);
return ret;
+ }
if (igtk_ptr) {
WARN_ON(*igtk_ptr);
* On the other hand, FW will never check this flag during RX since
* an AP/GO doesn't receive protected broadcast management frames.
* So, we can set it unconditionally.
+ *
+ * For NAN stations associated with a NAN Device, the MFP bit must be
+ * set to 1, as otherwise the FW will assert when a key associated with
+ * these stations would be added.
*/
- if (internal_sta->sta_type == STATION_TYPE_BCAST_MGMT)
+ if (internal_sta->sta_type == STATION_TYPE_BCAST_MGMT ||
+ internal_sta->sta_type == STATION_TYPE_NAN_BCAST ||
+ internal_sta->sta_type == STATION_TYPE_NAN_MGMT)
cmd.mfp = cpu_to_le32(1);
if (addr) {