[PATCH] ath10k: deliver mgmt frames from htt to monitor vifs only
Peter Oh
poh at codeaurora.org
Mon Nov 30 11:44:53 PST 2015
On 11/30/2015 04:56 AM, Grzegorz Bajorski wrote:
> 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.
Does this change valid for all the firmware 10.1, 10.2, 10.4, and etc.?
>
> Signed-off-by: Grzegorz Bajorski <grzegorz.bajorski at tieto.com>
> ---
> depends on:
> mac80211: allow drivers to report (non-)monitor frames
>
> drivers/net/wireless/ath/ath10k/htt_rx.c | 70
> ++++++++++++++++----------------
> drivers/net/wireless/ath/ath10k/wmi.c | 6 +++
> 2 files changed, 40 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c
> b/drivers/net/wireless/ath/ath10k/htt_rx.c
> index 396645b..898eff0 100644
> --- a/drivers/net/wireless/ath/ath10k/htt_rx.c
> +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
> @@ -1076,20 +1076,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,
> @@ -1330,6 +1335,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))
> @@ -1338,6 +1344,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);
>
> @@ -1379,6 +1388,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)
> @@ -1387,10 +1397,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;
Management frames are encrypted in MFP condition.
This change seems breaking MFP frame from working.
> +}
>
> skb_queue_walk(amsdu, msdu) {
> ath10k_htt_rx_h_csum_offload(msdu);
> @@ -1403,6 +1424,8 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
> */
> if (!is_decrypted)
> continue;
> + if (is_mgmt)
> + continue;
Ditto.
Could you provide test results in MFP case?
>
> hdr = (void *)msdu->data;
> hdr->frame_control &=
> ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
> @@ -1503,14 +1526,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.
> */
> @@ -1520,23 +1535,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;
> diff --git a/drivers/net/wireless/ath/ath10k/wmi.c
> b/drivers/net/wireless/ath/ath10k/wmi.c
> index 9021079..847f91a 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi.c
> +++ b/drivers/net/wireless/ath/ath10k/wmi.c
> @@ -2298,6 +2298,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
More information about the ath10k
mailing list