ath10k: deliver mgmt frames from htt to monitor vifs only
authorGrzegorz Bajorski <grzegorz.bajorski@tieto.com>
Mon, 30 Nov 2015 12:56:59 +0000 (13:56 +0100)
committerKalle Valo <kvalo@qca.qualcomm.com>
Tue, 8 Mar 2016 09:25:54 +0000 (11:25 +0200)
Until now only WMI originating mgmt frames were
reported to mac80211. Management frames on HTT
were basically dropped (except frames which looked
like management but had FCS error).

To allow sniffing all frames (including offloaded
frames) without interfering with mac80211
operation and states a new rx_flag was introduced
and is not being used to distinguish frames and
classify them for mac80211.

Signed-off-by: Grzegorz Bajorski <grzegorz.bajorski@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/wmi.c

index 40f969c72de86e596edadb911c121869e65bf8e9..84b060efa1b5f4d828a01265263e071234050f19 100644 (file)
@@ -1078,20 +1078,25 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
        hdr = (void *)msdu->data;
 
        /* Tail */
-       skb_trim(msdu, msdu->len - ath10k_htt_rx_crypto_tail_len(ar, enctype));
+       if (status->flag & RX_FLAG_IV_STRIPPED)
+               skb_trim(msdu, msdu->len -
+                        ath10k_htt_rx_crypto_tail_len(ar, enctype));
 
        /* MMIC */
-       if (!ieee80211_has_morefrags(hdr->frame_control) &&
+       if ((status->flag & RX_FLAG_MMIC_STRIPPED) &&
+           !ieee80211_has_morefrags(hdr->frame_control) &&
            enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
                skb_trim(msdu, msdu->len - 8);
 
        /* Head */
-       hdr_len = ieee80211_hdrlen(hdr->frame_control);
-       crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
+       if (status->flag & RX_FLAG_IV_STRIPPED) {
+               hdr_len = ieee80211_hdrlen(hdr->frame_control);
+               crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
 
-       memmove((void *)msdu->data + crypto_len,
-               (void *)msdu->data, hdr_len);
-       skb_pull(msdu, crypto_len);
+               memmove((void *)msdu->data + crypto_len,
+                       (void *)msdu->data, hdr_len);
+               skb_pull(msdu, crypto_len);
+       }
 }
 
 static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
@@ -1345,6 +1350,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
        bool has_tkip_err;
        bool has_peer_idx_invalid;
        bool is_decrypted;
+       bool is_mgmt;
        u32 attention;
 
        if (skb_queue_empty(amsdu))
@@ -1353,6 +1359,9 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
        first = skb_peek(amsdu);
        rxd = (void *)first->data - sizeof(*rxd);
 
+       is_mgmt = !!(rxd->attention.flags &
+                    __cpu_to_le32(RX_ATTENTION_FLAGS_MGMT_TYPE));
+
        enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
                     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
 
@@ -1394,6 +1403,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
                          RX_FLAG_MMIC_ERROR |
                          RX_FLAG_DECRYPTED |
                          RX_FLAG_IV_STRIPPED |
+                         RX_FLAG_ONLY_MONITOR |
                          RX_FLAG_MMIC_STRIPPED);
 
        if (has_fcs_err)
@@ -1402,10 +1412,21 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
        if (has_tkip_err)
                status->flag |= RX_FLAG_MMIC_ERROR;
 
-       if (is_decrypted)
-               status->flag |= RX_FLAG_DECRYPTED |
-                               RX_FLAG_IV_STRIPPED |
-                               RX_FLAG_MMIC_STRIPPED;
+       /* Firmware reports all necessary management frames via WMI already.
+        * They are not reported to monitor interfaces at all so pass the ones
+        * coming via HTT to monitor interfaces instead. This simplifies
+        * matters a lot.
+        */
+       if (is_mgmt)
+               status->flag |= RX_FLAG_ONLY_MONITOR;
+
+       if (is_decrypted) {
+               status->flag |= RX_FLAG_DECRYPTED;
+
+               if (likely(!is_mgmt))
+                       status->flag |= RX_FLAG_IV_STRIPPED |
+                                       RX_FLAG_MMIC_STRIPPED;
+}
 
        skb_queue_walk(amsdu, msdu) {
                ath10k_htt_rx_h_csum_offload(msdu);
@@ -1418,6 +1439,8 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
                 */
                if (!is_decrypted)
                        continue;
+               if (is_mgmt)
+                       continue;
 
                hdr = (void *)msdu->data;
                hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
@@ -1518,14 +1541,6 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
                                        struct sk_buff_head *amsdu,
                                        struct ieee80211_rx_status *rx_status)
 {
-       struct sk_buff *msdu;
-       struct htt_rx_desc *rxd;
-       bool is_mgmt;
-       bool has_fcs_err;
-
-       msdu = skb_peek(amsdu);
-       rxd = (void *)msdu->data - sizeof(*rxd);
-
        /* FIXME: It might be a good idea to do some fuzzy-testing to drop
         * invalid/dangerous frames.
         */
@@ -1535,23 +1550,6 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
                return false;
        }
 
-       is_mgmt = !!(rxd->attention.flags &
-                    __cpu_to_le32(RX_ATTENTION_FLAGS_MGMT_TYPE));
-       has_fcs_err = !!(rxd->attention.flags &
-                        __cpu_to_le32(RX_ATTENTION_FLAGS_FCS_ERR));
-
-       /* Management frames are handled via WMI events. The pros of such
-        * approach is that channel is explicitly provided in WMI events
-        * whereas HTT doesn't provide channel information for Rxed frames.
-        *
-        * However some firmware revisions don't report corrupted frames via
-        * WMI so don't drop them.
-        */
-       if (is_mgmt && !has_fcs_err) {
-               ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n");
-               return false;
-       }
-
        if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
                ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx cac running\n");
                return false;
index c31b4878cdc6fb1957ff677b4e498b14d3938b0e..651220e98c72841239072fd648f50890f1683972 100644 (file)
@@ -2310,6 +2310,12 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
        hdr = (struct ieee80211_hdr *)skb->data;
        fc = le16_to_cpu(hdr->frame_control);
 
+       /* Firmware is guaranteed to report all essential management frames via
+        * WMI while it can deliver some extra via HTT. Since there can be
+        * duplicates split the reporting wrt monitor/sniffing.
+        */
+       status->flag |= RX_FLAG_SKIP_MONITOR;
+
        ath10k_wmi_handle_wep_reauth(ar, skb, status);
 
        /* FW delivers WEP Shared Auth frame with Protected Bit set and
This page took 0.027957 seconds and 5 git commands to generate.