1 From: Johannes Berg <johannes.berg@intel.com>
2 Date: Fri, 20 Mar 2015 14:18:27 +0100
3 Subject: [PATCH] mac80211: avoid duplicate TX path station lookup
5 Instead of looking up the destination station twice in the TX path
6 (first to build the header, and then for control processing), save
7 it when building the header and use it later in the TX path.
9 To avoid having to look up the station in the many callers, allow
10 those to pass %NULL which keeps the existing lookup.
12 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
15 --- a/net/mac80211/cfg.c
16 +++ b/net/mac80211/cfg.c
17 @@ -3565,7 +3565,7 @@ static int ieee80211_probe_client(struct
18 nullfunc->qos_ctrl = cpu_to_le16(7);
21 - ieee80211_xmit(sdata, skb);
22 + ieee80211_xmit(sdata, sta, skb);
26 --- a/net/mac80211/ieee80211_i.h
27 +++ b/net/mac80211/ieee80211_i.h
28 @@ -1775,7 +1775,8 @@ void mac80211_ev_michael_mic_failure(str
30 void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
32 -void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
33 +void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
34 + struct sta_info *sta, struct sk_buff *skb);
36 void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
37 struct sk_buff *skb, int tid,
38 --- a/net/mac80211/sta_info.c
39 +++ b/net/mac80211/sta_info.c
40 @@ -1279,7 +1279,7 @@ static void ieee80211_send_null_response
43 info->band = chanctx_conf->def.chan->band;
44 - ieee80211_xmit(sdata, skb);
45 + ieee80211_xmit(sdata, sta, skb);
49 --- a/net/mac80211/tx.c
50 +++ b/net/mac80211/tx.c
51 @@ -1110,11 +1110,13 @@ static bool ieee80211_tx_prep_agg(struct
55 + * pass %NULL for the station if unknown, a valid pointer if known
56 + * or an ERR_PTR() if the station is known not to exist
58 static ieee80211_tx_result
59 ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
60 struct ieee80211_tx_data *tx,
61 - struct sk_buff *skb)
62 + struct sta_info *sta, struct sk_buff *skb)
64 struct ieee80211_local *local = sdata->local;
65 struct ieee80211_hdr *hdr;
66 @@ -1137,17 +1139,22 @@ ieee80211_tx_prepare(struct ieee80211_su
68 hdr = (struct ieee80211_hdr *) skb->data;
70 - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
71 - tx->sta = rcu_dereference(sdata->u.vlan.sta);
72 - if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
74 - } else if (info->flags & (IEEE80211_TX_CTL_INJECTED |
75 - IEEE80211_TX_INTFL_NL80211_FRAME_TX) ||
76 - tx->sdata->control_port_protocol == tx->skb->protocol) {
77 - tx->sta = sta_info_get_bss(sdata, hdr->addr1);
82 + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
83 + tx->sta = rcu_dereference(sdata->u.vlan.sta);
84 + if (!tx->sta && sdata->wdev.use_4addr)
86 + } else if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX |
87 + IEEE80211_TX_CTL_INJECTED) ||
88 + tx->sdata->control_port_protocol == tx->skb->protocol) {
89 + tx->sta = sta_info_get_bss(sdata, hdr->addr1);
91 + if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
92 + tx->sta = sta_info_get(sdata, hdr->addr1);
94 - if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
95 - tx->sta = sta_info_get(sdata, hdr->addr1);
97 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
98 !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
99 @@ -1485,7 +1492,7 @@ bool ieee80211_tx_prepare_skb(struct iee
100 struct ieee80211_tx_data tx;
101 struct sk_buff *skb2;
103 - if (ieee80211_tx_prepare(sdata, &tx, skb) == TX_DROP)
104 + if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP)
108 @@ -1518,7 +1525,8 @@ EXPORT_SYMBOL(ieee80211_tx_prepare_skb);
109 * Returns false if the frame couldn't be transmitted but was queued instead.
111 static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
112 - struct sk_buff *skb, bool txpending)
113 + struct sta_info *sta, struct sk_buff *skb,
116 struct ieee80211_local *local = sdata->local;
117 struct ieee80211_tx_data tx;
118 @@ -1534,7 +1542,7 @@ static bool ieee80211_tx(struct ieee8021
122 - res_prepare = ieee80211_tx_prepare(sdata, &tx, skb);
123 + res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb);
125 if (unlikely(res_prepare == TX_DROP)) {
126 ieee80211_free_txskb(&local->hw, skb);
127 @@ -1590,7 +1598,8 @@ static int ieee80211_skb_resize(struct i
131 -void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
132 +void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
133 + struct sta_info *sta, struct sk_buff *skb)
135 struct ieee80211_local *local = sdata->local;
136 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
137 @@ -1625,7 +1634,7 @@ void ieee80211_xmit(struct ieee80211_sub
140 ieee80211_set_qos_hdr(sdata, skb);
141 - ieee80211_tx(sdata, skb, false);
142 + ieee80211_tx(sdata, sta, skb, false);
145 static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
146 @@ -1846,7 +1855,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
149 info->band = chandef->chan->band;
150 - ieee80211_xmit(sdata, skb);
151 + ieee80211_xmit(sdata, NULL, skb);
155 @@ -1877,7 +1886,8 @@ fail:
156 * Returns: the (possibly reallocated) skb or an ERR_PTR() code
158 static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
159 - struct sk_buff *skb, u32 info_flags)
160 + struct sk_buff *skb, u32 info_flags,
161 + struct sta_info **sta_out)
163 struct ieee80211_local *local = sdata->local;
164 struct ieee80211_tx_info *info;
165 @@ -1920,6 +1930,7 @@ static struct sk_buff *ieee80211_build_h
166 authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
167 wme_sta = sta->sta.wme;
170 } else if (sdata->wdev.use_4addr) {
173 @@ -2073,6 +2084,7 @@ static struct sk_buff *ieee80211_build_h
175 authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
176 wme_sta = sta->sta.wme;
178 } else if (sdata->u.mgd.use_4addr &&
179 cpu_to_be16(ethertype) != sdata->control_port_protocol) {
180 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
181 @@ -2136,13 +2148,18 @@ static struct sk_buff *ieee80211_build_h
182 * and mesh mode checks authorization later.
184 multicast = is_multicast_ether_addr(hdr.addr1);
185 - if (!multicast && !have_station &&
186 - !ieee80211_vif_is_mesh(&sdata->vif)) {
187 - sta = sta_info_get(sdata, hdr.addr1);
189 + *sta_out = ERR_PTR(-ENOENT);
190 + } else if (!have_station && !ieee80211_vif_is_mesh(&sdata->vif)) {
191 + if (sdata->control_port_protocol == skb->protocol)
192 + sta = sta_info_get_bss(sdata, hdr.addr1);
194 + sta = sta_info_get(sdata, hdr.addr1);
196 authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
197 wme_sta = sta->sta.wme;
199 + *sta_out = sta ?: ERR_PTR(-ENOENT);
202 /* For mesh, the use of the QoS header is mandatory */
203 @@ -2320,6 +2337,7 @@ void __ieee80211_subif_start_xmit(struct
206 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
207 + struct sta_info *sta = NULL;
209 if (unlikely(skb->len < ETH_HLEN)) {
211 @@ -2328,7 +2346,7 @@ void __ieee80211_subif_start_xmit(struct
215 - skb = ieee80211_build_hdr(sdata, skb, info_flags);
216 + skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta);
220 @@ -2336,7 +2354,7 @@ void __ieee80211_subif_start_xmit(struct
221 dev->stats.tx_bytes += skb->len;
222 dev->trans_start = jiffies;
224 - ieee80211_xmit(sdata, skb);
225 + ieee80211_xmit(sdata, sta, skb);
229 @@ -2364,10 +2382,11 @@ ieee80211_build_data_template(struct iee
230 .local = sdata->local,
233 + struct sta_info *sta_ignore;
237 - skb = ieee80211_build_hdr(sdata, skb, info_flags);
238 + skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta_ignore);
242 @@ -2425,7 +2444,7 @@ static bool ieee80211_tx_pending_skb(str
245 info->band = chanctx_conf->def.chan->band;
246 - result = ieee80211_tx(sdata, skb, true);
247 + result = ieee80211_tx(sdata, NULL, skb, true);
249 struct sk_buff_head skbs;
251 @@ -3163,7 +3182,7 @@ ieee80211_get_buffered_bc(struct ieee802
253 if (sdata->vif.type == NL80211_IFTYPE_AP)
254 sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
255 - if (!ieee80211_tx_prepare(sdata, &tx, skb))
256 + if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb))
258 dev_kfree_skb_any(skb);
260 @@ -3295,6 +3314,6 @@ void __ieee80211_tx_skb_tid_band(struct
263 IEEE80211_SKB_CB(skb)->band = band;
264 - ieee80211_xmit(sdata, skb);
265 + ieee80211_xmit(sdata, NULL, skb);