iwlwifi: mvm: include configured sniffer AID in radiotap
authorJohannes Berg <johannes.berg@intel.com>
Tue, 20 Nov 2018 16:58:46 +0000 (17:58 +0100)
committerLuca Coelho <luciano.coelho@intel.com>
Tue, 29 Jan 2019 14:10:32 +0000 (16:10 +0200)
In order to make more sense out of the captured radiotap data e.g.
when the configured AID changes, add the currently configured AID
to the radiotap data as a vendor extension field.

This is made race-free by updating the included value from inside
the RX path (using a notification wait) for the command response
from the firmware, which thus means it's serialized with frame RX.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c

index 91b4636..e136475 100644 (file)
@@ -1682,11 +1682,33 @@ iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
        return ret ?: count;
 }
 
+struct iwl_mvm_sniffer_apply {
+       struct iwl_mvm *mvm;
+       u16 aid;
+};
+
+static bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data,
+                                 struct iwl_rx_packet *pkt, void *data)
+{
+       struct iwl_mvm_sniffer_apply *apply = data;
+
+       apply->mvm->cur_aid = cpu_to_le16(apply->aid);
+
+       return true;
+}
+
 static ssize_t
 iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf,
-                       size_t count, loff_t *ppos)
+                                 size_t count, loff_t *ppos)
 {
+       struct iwl_notification_wait wait;
        struct iwl_he_monitor_cmd he_mon_cmd = {};
+       struct iwl_mvm_sniffer_apply apply = {
+               .mvm = mvm,
+       };
+       u16 wait_cmds[] = {
+               iwl_cmd_id(HE_AIR_SNIFFER_CONFIG_CMD, DATA_PATH_GROUP, 0),
+       };
        u32 aid;
        int ret;
 
@@ -1702,10 +1724,30 @@ iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf,
 
        he_mon_cmd.aid = cpu_to_le16(aid);
 
+       apply.aid = aid;
+
        mutex_lock(&mvm->mutex);
+
+       /*
+        * Use the notification waiter to get our function triggered
+        * in sequence with other RX. This ensures that frames we get
+        * on the RX queue _before_ the new configuration is applied
+        * still have mvm->cur_aid pointing to the old AID, and that
+        * frames on the RX queue _after_ the firmware processed the
+        * new configuration (and sent the response, synchronously)
+        * get mvm->cur_aid correctly set to the new AID.
+        */
+       iwl_init_notification_wait(&mvm->notif_wait, &wait,
+                                  wait_cmds, ARRAY_SIZE(wait_cmds),
+                                  iwl_mvm_sniffer_apply, &apply);
+
        ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(HE_AIR_SNIFFER_CONFIG_CMD,
                                                   DATA_PATH_GROUP, 0), 0,
                                   sizeof(he_mon_cmd), &he_mon_cmd);
+
+       /* no need to really wait, we already did anyway */
+       iwl_remove_notification(&mvm->notif_wait, &wait);
+
        mutex_unlock(&mvm->mutex);
 
        return ret ?: count;
index d4b05ca..531d2de 100644 (file)
@@ -1167,6 +1167,8 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
 
        iwl_mvm_stop_device(mvm);
 
+       mvm->cur_aid = 0;
+
        mvm->scan_status = 0;
        mvm->ps_disabled = false;
        mvm->calibrating = false;
index 5c9adf7..ac526b4 100644 (file)
@@ -1164,6 +1164,10 @@ struct iwl_mvm {
 
        /* does a monitor vif exist (only one can exist hence bool) */
        bool monitor_on;
+
+       /* sniffer data to include in radiotap */
+       __le16 cur_aid;
+
 #ifdef CONFIG_ACPI
        struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
        struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
index 9fde322..79860f6 100644 (file)
@@ -192,11 +192,40 @@ static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr,
        }
 }
 
+static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
+                                           struct sk_buff *skb)
+{
+       struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
+       struct ieee80211_vendor_radiotap *radiotap;
+       int size = sizeof(*radiotap) + sizeof(__le16);
+
+       if (!mvm->cur_aid)
+               return;
+
+       radiotap = skb_put(skb, size);
+       radiotap->align = 1;
+       /* Intel OUI */
+       radiotap->oui[0] = 0xf6;
+       radiotap->oui[1] = 0x54;
+       radiotap->oui[2] = 0x25;
+       /* radiotap sniffer config sub-namespace */
+       radiotap->subns = 1;
+       radiotap->present = 0x1;
+       radiotap->len = size - sizeof(*radiotap);
+       radiotap->pad = 0;
+
+       /* fill the data now */
+       memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid));
+
+       rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA;
+}
+
 /* iwl_mvm_pass_packet_to_mac80211 - passes the packet for mac80211 */
 static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
                                            struct napi_struct *napi,
                                            struct sk_buff *skb, int queue,
-                                           struct ieee80211_sta *sta)
+                                           struct ieee80211_sta *sta,
+                                           bool csi)
 {
        struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
 
@@ -465,7 +494,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
                while ((skb = __skb_dequeue(skb_list))) {
                        iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,
                                                        reorder_buf->queue,
-                                                       sta);
+                                                       sta, false);
                        reorder_buf->num_stored--;
                }
        }
@@ -1304,6 +1333,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
                .d4 = desc->phy_data4,
                .info_type = IWL_RX_PHY_INFO_TYPE_NONE,
        };
+       bool csi = false;
 
        if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
                return;
@@ -1599,7 +1629,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
 
        iwl_mvm_create_skb(skb, hdr, len, crypt_len, rxb);
        if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc))
-               iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta);
+               iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue,
+                                               sta, csi);
 out:
        rcu_read_unlock();
 }
@@ -1732,7 +1763,7 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
                rx_status->rate_idx = rate;
        }
 
-       iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta);
+       iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta, false);
 out:
        rcu_read_unlock();
 }