aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package/kernel/mac80211/patches/321-mac80211-Parse-legacy-and-HT-rate-in-injected-frames.patch155
1 files changed, 155 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/321-mac80211-Parse-legacy-and-HT-rate-in-injected-frames.patch b/package/kernel/mac80211/patches/321-mac80211-Parse-legacy-and-HT-rate-in-injected-frames.patch
new file mode 100644
index 0000000000..c4155a1181
--- /dev/null
+++ b/package/kernel/mac80211/patches/321-mac80211-Parse-legacy-and-HT-rate-in-injected-frames.patch
@@ -0,0 +1,155 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Tue, 26 Jan 2016 17:11:13 +0100
+Subject: [PATCH] mac80211: Parse legacy and HT rate in injected frames
+
+Drivers/devices without their own rate control algorithm can get the
+information what rates they should use from either the radiotap header of
+injected frames or from the rate control algorithm. But the parsing of the
+legacy rate information from the radiotap header was removed in commit
+e6a9854b05c1 ("mac80211/drivers: rewrite the rate control API").
+
+The removal of this feature heavily reduced the usefulness of frame
+injection when wanting to simulate specific transmission behavior. Having
+rate parsing together with MCS rates and retry support allows a fine
+grained selection of the tx behavior of injected frames for these kind of
+tests.
+
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Cc: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -708,12 +708,14 @@ enum mac80211_tx_info_flags {
+ * protocol frame (e.g. EAP)
+ * @IEEE80211_TX_CTRL_PS_RESPONSE: This frame is a response to a poll
+ * frame (PS-Poll or uAPSD).
++ * @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
+ *
+ * These flags are used in tx_info->control.flags.
+ */
+ enum mac80211_tx_control_flags {
+ IEEE80211_TX_CTRL_PORT_CTRL_PROTO = BIT(0),
+ IEEE80211_TX_CTRL_PS_RESPONSE = BIT(1),
++ IEEE80211_TX_CTRL_RATE_INJECT = BIT(2),
+ };
+
+ /*
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -710,6 +710,10 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
+
+ info->control.short_preamble = txrc.short_preamble;
+
++ /* don't ask rate control when rate already injected via radiotap */
++ if (info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)
++ return TX_CONTINUE;
++
+ if (tx->sta)
+ assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
+
+@@ -1665,15 +1669,24 @@ void ieee80211_xmit(struct ieee80211_sub
+ ieee80211_tx(sdata, sta, skb, false);
+ }
+
+-static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
++static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local,
++ struct sk_buff *skb)
+ {
+ struct ieee80211_radiotap_iterator iterator;
+ struct ieee80211_radiotap_header *rthdr =
+ (struct ieee80211_radiotap_header *) skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++ struct ieee80211_supported_band *sband =
++ local->hw.wiphy->bands[info->band];
+ int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
+ NULL);
+ u16 txflags;
++ u16 rate = 0;
++ bool rate_found = false;
++ u8 rate_retries = 0;
++ u16 rate_flags = 0;
++ u8 mcs_known, mcs_flags;
++ int i;
+
+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
+ IEEE80211_TX_CTL_DONTFRAG;
+@@ -1724,6 +1737,35 @@ static bool ieee80211_parse_tx_radiotap(
+ info->flags |= IEEE80211_TX_CTL_NO_ACK;
+ break;
+
++ case IEEE80211_RADIOTAP_RATE:
++ rate = *iterator.this_arg;
++ rate_flags = 0;
++ rate_found = true;
++ break;
++
++ case IEEE80211_RADIOTAP_DATA_RETRIES:
++ rate_retries = *iterator.this_arg;
++ break;
++
++ case IEEE80211_RADIOTAP_MCS:
++ mcs_known = iterator.this_arg[0];
++ mcs_flags = iterator.this_arg[1];
++ if (!(mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_MCS))
++ break;
++
++ rate_found = true;
++ rate = iterator.this_arg[2];
++ rate_flags = IEEE80211_TX_RC_MCS;
++
++ if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_GI &&
++ mcs_flags & IEEE80211_RADIOTAP_MCS_SGI)
++ rate_flags |= IEEE80211_TX_RC_SHORT_GI;
++
++ if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_BW &&
++ mcs_flags & IEEE80211_RADIOTAP_MCS_BW_40)
++ rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
++ break;
++
+ /*
+ * Please update the file
+ * Documentation/networking/mac80211-injection.txt
+@@ -1738,6 +1780,32 @@ static bool ieee80211_parse_tx_radiotap(
+ if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
+ return false;
+
++ if (rate_found) {
++ info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT;
++
++ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
++ info->control.rates[i].idx = -1;
++ info->control.rates[i].flags = 0;
++ info->control.rates[i].count = 0;
++ }
++
++ if (rate_flags & IEEE80211_TX_RC_MCS) {
++ info->control.rates[0].idx = rate;
++ } else {
++ for (i = 0; i < sband->n_bitrates; i++) {
++ if (rate * 5 != sband->bitrates[i].bitrate)
++ continue;
++
++ info->control.rates[0].idx = i;
++ break;
++ }
++ }
++
++ info->control.rates[0].flags = rate_flags;
++ info->control.rates[0].count = min_t(u8, rate_retries + 1,
++ local->hw.max_rate_tries);
++ }
++
+ /*
+ * remove the radiotap header
+ * iterator->_max_length was sanity-checked against
+@@ -1819,7 +1887,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
+ IEEE80211_TX_CTL_INJECTED;
+
+ /* process and remove the injection radiotap header */
+- if (!ieee80211_parse_tx_radiotap(skb))
++ if (!ieee80211_parse_tx_radiotap(local, skb))
+ goto fail;
+
+ rcu_read_lock();