From: Felix Fietkau Date: Fri, 5 Feb 2016 16:43:25 +0000 (+0000) Subject: mac80211: parse legacy and HT rates in monitor mode injected frames X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=351be0fdecc97152a31da55af297d2a9d8fb45bc;p=openwrt%2Fstaging%2Frobimarko.git mac80211: parse legacy and HT rates in monitor mode injected frames Signed-off-by: Felix Fietkau SVN-Revision: 48636 --- 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 +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 +Cc: Simon Wunderlich +Signed-off-by: Johannes Berg +--- + +--- 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();