iwlwifi: mvm: Allow multicast data frames only when associated
authorIlan Peer <ilan.peer@intel.com>
Fri, 16 Aug 2019 12:55:51 +0000 (15:55 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 20 Aug 2019 14:00:39 +0000 (17:00 +0300)
The MAC context configuration always allowed multicast data frames
to pass to the driver for all MAC context types, and in the
case of station MAC context both when associated and when not
associated.

One of the outcomes of this configuration is having the FW forward
encrypted multicast frames to the driver with Rx status indicating
that the frame was not decrypted (as expected, since no keys were
configured yet) which in turn results with unnecessary error
messages.

Change this behavior to allow multicast data frames only when they
are actually expected, e.g., station MAC context is associated etc.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

index cb22d447fcb8a9d68aa566a1933202dddc1bca9d..fe776e35b9d06bf152ce12eec6a664eee2317e62 100644 (file)
@@ -554,7 +554,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
                cpu_to_le32(vif->bss_conf.use_short_slot ?
                            MAC_FLG_SHORT_SLOT : 0);
 
-       cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
+       cmd->filter_flags = 0;
 
        for (i = 0; i < IEEE80211_NUM_ACS; i++) {
                u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i);
@@ -623,6 +623,8 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
        /* We need the dtim_period to set the MAC as associated */
        if (vif->bss_conf.assoc && vif->bss_conf.dtim_period &&
            !force_assoc_off) {
+               struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+               u8 ap_sta_id = mvmvif->ap_sta_id;
                u32 dtim_offs;
 
                /*
@@ -658,6 +660,29 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
                               dtim_offs);
 
                ctxt_sta->is_assoc = cpu_to_le32(1);
+
+               /*
+                * allow multicast data frames only as long as the station is
+                * authorized, i.e., GTK keys are already installed (if needed)
+                */
+               if (ap_sta_id < IWL_MVM_STATION_COUNT) {
+                       struct ieee80211_sta *sta;
+
+                       rcu_read_lock();
+
+                       sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]);
+                       if (!IS_ERR_OR_NULL(sta)) {
+                               struct iwl_mvm_sta *mvmsta =
+                                       iwl_mvm_sta_from_mac80211(sta);
+
+                               if (mvmsta->sta_state ==
+                                   IEEE80211_STA_AUTHORIZED)
+                                       cmd.filter_flags |=
+                                               cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
+                       }
+
+                       rcu_read_unlock();
+               }
        } else {
                ctxt_sta->is_assoc = cpu_to_le32(0);
 
@@ -703,7 +728,8 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
                                       MAC_FILTER_IN_CONTROL_AND_MGMT |
                                       MAC_FILTER_IN_BEACON |
                                       MAC_FILTER_IN_PROBE_REQUEST |
-                                      MAC_FILTER_IN_CRC32);
+                                      MAC_FILTER_IN_CRC32 |
+                                      MAC_FILTER_ACCEPT_GRP);
        ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
 
        /* Allocate sniffer station */
@@ -727,7 +753,8 @@ static int iwl_mvm_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
        iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
 
        cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_BEACON |
-                                      MAC_FILTER_IN_PROBE_REQUEST);
+                                      MAC_FILTER_IN_PROBE_REQUEST |
+                                      MAC_FILTER_ACCEPT_GRP);
 
        /* cmd.ibss.beacon_time/cmd.ibss.beacon_tsf are curently ignored */
        cmd.ibss.bi = cpu_to_le32(vif->bss_conf.beacon_int);
index 1c904b5226aa42d875ba503b725b33fec85e0ffd..a7bc00d1296fec755e8415dd7f226207ff2408a2 100644 (file)
@@ -3327,10 +3327,20 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
                /* enable beacon filtering */
                WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
 
+               /*
+                * Now that the station is authorized, i.e., keys were already
+                * installed, need to indicate to the FW that
+                * multicast data frames can be forwarded to the driver
+                */
+               iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+
                iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
                                     true);
        } else if (old_state == IEEE80211_STA_AUTHORIZED &&
                   new_state == IEEE80211_STA_ASSOC) {
+               /* Multicast data frames are no longer allowed */
+               iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+
                /* disable beacon filtering */
                ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
                WARN_ON(ret &&