image.mk: fix emitting profiles for targets that have no subtargets
[openwrt/staging/mkresin.git] / package / kernel / mac80211 / patches / 321-mac80211-Parse-legacy-and-HT-rate-in-injected-frames.patch
1 From: Sven Eckelmann <sven@narfation.org>
2 Date: Tue, 26 Jan 2016 17:11:13 +0100
3 Subject: [PATCH] mac80211: Parse legacy and HT rate in injected frames
4
5 Drivers/devices without their own rate control algorithm can get the
6 information what rates they should use from either the radiotap header of
7 injected frames or from the rate control algorithm. But the parsing of the
8 legacy rate information from the radiotap header was removed in commit
9 e6a9854b05c1 ("mac80211/drivers: rewrite the rate control API").
10
11 The removal of this feature heavily reduced the usefulness of frame
12 injection when wanting to simulate specific transmission behavior. Having
13 rate parsing together with MCS rates and retry support allows a fine
14 grained selection of the tx behavior of injected frames for these kind of
15 tests.
16
17 Signed-off-by: Sven Eckelmann <sven@narfation.org>
18 Cc: Simon Wunderlich <sw@simonwunderlich.de>
19 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
20 ---
21
22 --- a/include/net/mac80211.h
23 +++ b/include/net/mac80211.h
24 @@ -708,12 +708,14 @@ enum mac80211_tx_info_flags {
25 * protocol frame (e.g. EAP)
26 * @IEEE80211_TX_CTRL_PS_RESPONSE: This frame is a response to a poll
27 * frame (PS-Poll or uAPSD).
28 + * @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
29 *
30 * These flags are used in tx_info->control.flags.
31 */
32 enum mac80211_tx_control_flags {
33 IEEE80211_TX_CTRL_PORT_CTRL_PROTO = BIT(0),
34 IEEE80211_TX_CTRL_PS_RESPONSE = BIT(1),
35 + IEEE80211_TX_CTRL_RATE_INJECT = BIT(2),
36 };
37
38 /*
39 --- a/net/mac80211/tx.c
40 +++ b/net/mac80211/tx.c
41 @@ -710,6 +710,10 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
42
43 info->control.short_preamble = txrc.short_preamble;
44
45 + /* don't ask rate control when rate already injected via radiotap */
46 + if (info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)
47 + return TX_CONTINUE;
48 +
49 if (tx->sta)
50 assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
51
52 @@ -1665,15 +1669,24 @@ void ieee80211_xmit(struct ieee80211_sub
53 ieee80211_tx(sdata, sta, skb, false);
54 }
55
56 -static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
57 +static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local,
58 + struct sk_buff *skb)
59 {
60 struct ieee80211_radiotap_iterator iterator;
61 struct ieee80211_radiotap_header *rthdr =
62 (struct ieee80211_radiotap_header *) skb->data;
63 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
64 + struct ieee80211_supported_band *sband =
65 + local->hw.wiphy->bands[info->band];
66 int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
67 NULL);
68 u16 txflags;
69 + u16 rate = 0;
70 + bool rate_found = false;
71 + u8 rate_retries = 0;
72 + u16 rate_flags = 0;
73 + u8 mcs_known, mcs_flags;
74 + int i;
75
76 info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
77 IEEE80211_TX_CTL_DONTFRAG;
78 @@ -1724,6 +1737,35 @@ static bool ieee80211_parse_tx_radiotap(
79 info->flags |= IEEE80211_TX_CTL_NO_ACK;
80 break;
81
82 + case IEEE80211_RADIOTAP_RATE:
83 + rate = *iterator.this_arg;
84 + rate_flags = 0;
85 + rate_found = true;
86 + break;
87 +
88 + case IEEE80211_RADIOTAP_DATA_RETRIES:
89 + rate_retries = *iterator.this_arg;
90 + break;
91 +
92 + case IEEE80211_RADIOTAP_MCS:
93 + mcs_known = iterator.this_arg[0];
94 + mcs_flags = iterator.this_arg[1];
95 + if (!(mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_MCS))
96 + break;
97 +
98 + rate_found = true;
99 + rate = iterator.this_arg[2];
100 + rate_flags = IEEE80211_TX_RC_MCS;
101 +
102 + if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_GI &&
103 + mcs_flags & IEEE80211_RADIOTAP_MCS_SGI)
104 + rate_flags |= IEEE80211_TX_RC_SHORT_GI;
105 +
106 + if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_BW &&
107 + mcs_flags & IEEE80211_RADIOTAP_MCS_BW_40)
108 + rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
109 + break;
110 +
111 /*
112 * Please update the file
113 * Documentation/networking/mac80211-injection.txt
114 @@ -1738,6 +1780,32 @@ static bool ieee80211_parse_tx_radiotap(
115 if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
116 return false;
117
118 + if (rate_found) {
119 + info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT;
120 +
121 + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
122 + info->control.rates[i].idx = -1;
123 + info->control.rates[i].flags = 0;
124 + info->control.rates[i].count = 0;
125 + }
126 +
127 + if (rate_flags & IEEE80211_TX_RC_MCS) {
128 + info->control.rates[0].idx = rate;
129 + } else {
130 + for (i = 0; i < sband->n_bitrates; i++) {
131 + if (rate * 5 != sband->bitrates[i].bitrate)
132 + continue;
133 +
134 + info->control.rates[0].idx = i;
135 + break;
136 + }
137 + }
138 +
139 + info->control.rates[0].flags = rate_flags;
140 + info->control.rates[0].count = min_t(u8, rate_retries + 1,
141 + local->hw.max_rate_tries);
142 + }
143 +
144 /*
145 * remove the radiotap header
146 * iterator->_max_length was sanity-checked against
147 @@ -1819,7 +1887,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
148 IEEE80211_TX_CTL_INJECTED;
149
150 /* process and remove the injection radiotap header */
151 - if (!ieee80211_parse_tx_radiotap(skb))
152 + if (!ieee80211_parse_tx_radiotap(local, skb))
153 goto fail;
154
155 rcu_read_lock();