31ed830c2aa599528831ca1086a83386f158b9b9
[openwrt.git] / package / kernel / mac80211 / patches / 315-mac80211-avoid-duplicate-TX-path-station-lookup.patch
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
4
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.
8
9 To avoid having to look up the station in the many callers, allow
10 those to pass %NULL which keeps the existing lookup.
11
12 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
13 ---
14
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);
19  
20         local_bh_disable();
21 -       ieee80211_xmit(sdata, skb);
22 +       ieee80211_xmit(sdata, sta, skb);
23         local_bh_enable();
24         rcu_read_unlock();
25  
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
29                                      gfp_t gfp);
30  void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
31                                bool bss_notify);
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);
35  
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
41         }
42  
43         info->band = chanctx_conf->def.chan->band;
44 -       ieee80211_xmit(sdata, skb);
45 +       ieee80211_xmit(sdata, sta, skb);
46         rcu_read_unlock();
47  }
48  
49 --- a/net/mac80211/tx.c
50 +++ b/net/mac80211/tx.c
51 @@ -1111,11 +1111,13 @@ static bool ieee80211_tx_prep_agg(struct
52  
53  /*
54   * initialises @tx
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
57   */
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)
63  {
64         struct ieee80211_local *local = sdata->local;
65         struct ieee80211_hdr *hdr;
66 @@ -1138,17 +1140,22 @@ ieee80211_tx_prepare(struct ieee80211_su
67  
68         hdr = (struct ieee80211_hdr *) skb->data;
69  
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)
73 -                       return TX_DROP;
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);
78 +       if (likely(sta)) {
79 +               if (!IS_ERR(sta))
80 +                       tx->sta = sta;
81 +       } else {
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)
85 +                               return TX_DROP;
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);
90 +               }
91 +               if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
92 +                       tx->sta = sta_info_get(sdata, hdr->addr1);
93         }
94 -       if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
95 -               tx->sta = sta_info_get(sdata, hdr->addr1);
96  
97         if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
98             !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
99 @@ -1486,7 +1493,7 @@ bool ieee80211_tx_prepare_skb(struct iee
100         struct ieee80211_tx_data tx;
101         struct sk_buff *skb2;
102  
103 -       if (ieee80211_tx_prepare(sdata, &tx, skb) == TX_DROP)
104 +       if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP)
105                 return false;
106  
107         info->band = band;
108 @@ -1519,7 +1526,8 @@ EXPORT_SYMBOL(ieee80211_tx_prepare_skb);
109   * Returns false if the frame couldn't be transmitted but was queued instead.
110   */
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,
114 +                        bool txpending)
115  {
116         struct ieee80211_local *local = sdata->local;
117         struct ieee80211_tx_data tx;
118 @@ -1535,7 +1543,7 @@ static bool ieee80211_tx(struct ieee8021
119  
120         /* initialises tx */
121         led_len = skb->len;
122 -       res_prepare = ieee80211_tx_prepare(sdata, &tx, skb);
123 +       res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb);
124  
125         if (unlikely(res_prepare == TX_DROP)) {
126                 ieee80211_free_txskb(&local->hw, skb);
127 @@ -1591,7 +1599,8 @@ static int ieee80211_skb_resize(struct i
128         return 0;
129  }
130  
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)
134  {
135         struct ieee80211_local *local = sdata->local;
136         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
137 @@ -1626,7 +1635,7 @@ void ieee80211_xmit(struct ieee80211_sub
138         }
139  
140         ieee80211_set_qos_hdr(sdata, skb);
141 -       ieee80211_tx(sdata, skb, false);
142 +       ieee80211_tx(sdata, sta, skb, false);
143  }
144  
145  static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
146 @@ -1847,7 +1856,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
147                 goto fail_rcu;
148  
149         info->band = chandef->chan->band;
150 -       ieee80211_xmit(sdata, skb);
151 +       ieee80211_xmit(sdata, NULL, skb);
152         rcu_read_unlock();
153  
154         return NETDEV_TX_OK;
155 @@ -1878,7 +1887,8 @@ fail:
156   * Returns: the (possibly reallocated) skb or an ERR_PTR() code
157   */
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)
162  {
163         struct ieee80211_local *local = sdata->local;
164         struct ieee80211_tx_info *info;
165 @@ -1921,6 +1931,7 @@ static struct sk_buff *ieee80211_build_h
166                         authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
167                         wme_sta = sta->sta.wme;
168                         have_station = true;
169 +                       *sta_out = sta;
170                 } else if (sdata->wdev.use_4addr) {
171                         ret = -ENOLINK;
172                         goto free;
173 @@ -2074,6 +2085,7 @@ static struct sk_buff *ieee80211_build_h
174                         have_station = true;
175                         authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
176                         wme_sta = sta->sta.wme;
177 +                       *sta_out = sta;
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 @@ -2137,13 +2149,18 @@ static struct sk_buff *ieee80211_build_h
182          * and mesh mode checks authorization later.
183          */
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);
188 +       if (multicast) {
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);
193 +               else
194 +                       sta = sta_info_get(sdata, hdr.addr1);
195                 if (sta) {
196                         authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
197                         wme_sta = sta->sta.wme;
198                 }
199 +               *sta_out = sta ?: ERR_PTR(-ENOENT);
200         }
201  
202         /* For mesh, the use of the QoS header is mandatory */
203 @@ -2321,6 +2338,7 @@ void __ieee80211_subif_start_xmit(struct
204                                   u32 info_flags)
205  {
206         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
207 +       struct sta_info *sta = NULL;
208  
209         if (unlikely(skb->len < ETH_HLEN)) {
210                 kfree_skb(skb);
211 @@ -2329,7 +2347,7 @@ void __ieee80211_subif_start_xmit(struct
212  
213         rcu_read_lock();
214  
215 -       skb = ieee80211_build_hdr(sdata, skb, info_flags);
216 +       skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta);
217         if (IS_ERR(skb))
218                 goto out;
219  
220 @@ -2337,7 +2355,7 @@ void __ieee80211_subif_start_xmit(struct
221         dev->stats.tx_bytes += skb->len;
222         dev->trans_start = jiffies;
223  
224 -       ieee80211_xmit(sdata, skb);
225 +       ieee80211_xmit(sdata, sta, skb);
226   out:
227         rcu_read_unlock();
228  }
229 @@ -2365,10 +2383,11 @@ ieee80211_build_data_template(struct iee
230                 .local = sdata->local,
231                 .sdata = sdata,
232         };
233 +       struct sta_info *sta_ignore;
234  
235         rcu_read_lock();
236  
237 -       skb = ieee80211_build_hdr(sdata, skb, info_flags);
238 +       skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta_ignore);
239         if (IS_ERR(skb))
240                 goto out;
241  
242 @@ -2426,7 +2445,7 @@ static bool ieee80211_tx_pending_skb(str
243                         return true;
244                 }
245                 info->band = chanctx_conf->def.chan->band;
246 -               result = ieee80211_tx(sdata, skb, true);
247 +               result = ieee80211_tx(sdata, NULL, skb, true);
248         } else {
249                 struct sk_buff_head skbs;
250  
251 @@ -3164,7 +3183,7 @@ ieee80211_get_buffered_bc(struct ieee802
252  
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))
257                         break;
258                 dev_kfree_skb_any(skb);
259         }
260 @@ -3296,6 +3315,6 @@ void __ieee80211_tx_skb_tid_band(struct 
261          */
262         local_bh_disable();
263         IEEE80211_SKB_CB(skb)->band = band;
264 -       ieee80211_xmit(sdata, skb);
265 +       ieee80211_xmit(sdata, NULL, skb);
266         local_bh_enable();
267  }