b802960103a3405ded222d9db040e0c267d0e5b1
[openwrt/staging/noltari.git] / package / kernel / mac80211 / patches / subsys / 319-wifi-mac80211-mesh-fast-xmit-support.patch
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Sun, 26 Feb 2023 13:53:08 +0100
3 Subject: [PATCH] wifi: mac80211: mesh fast xmit support
4
5 Previously, fast xmit only worked on interface types where initially a
6 sta lookup is performed, and a cached header can be attached to the sta,
7 requiring only some fields to be updated at runtime.
8
9 This technique is not directly applicable for a mesh device type due
10 to the dynamic nature of the topology and protocol. There are more
11 addresses that need to be filled, and there is an extra header with a
12 dynamic length based on the addressing mode.
13
14 Change the code to cache entries contain a copy of the mesh subframe header +
15 bridge tunnel header, as well as an embedded struct ieee80211_fast_tx, which
16 contains the information for building the 802.11 header.
17
18 Add a mesh specific early fast xmit call, which looks up a cached entry and
19 adds only the mesh subframe header, before passing it over to the generic
20 fast xmit code.
21
22 To ensure the changes in network are reflected in these cached headers,
23 flush affected cached entries on path changes, as well as other conditions
24 that currently trigger a fast xmit check in other modes (key changes etc.)
25
26 This code is loosely based on a previous implementation by:
27 Sriram R <quic_srirrama@quicinc.com>
28
29 Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
30 Signed-off-by: Felix Fietkau <nbd@nbd.name>
31 ---
32
33 --- a/net/mac80211/ieee80211_i.h
34 +++ b/net/mac80211/ieee80211_i.h
35 @@ -37,6 +37,7 @@
36 extern const struct cfg80211_ops mac80211_config_ops;
37
38 struct ieee80211_local;
39 +struct ieee80211_mesh_fast_tx;
40
41 /* Maximum number of broadcast/multicast frames to buffer when some of the
42 * associated stations are using power saving. */
43 @@ -655,6 +656,19 @@ struct mesh_table {
44 atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */
45 };
46
47 +/**
48 + * struct mesh_tx_cache - mesh fast xmit header cache
49 + *
50 + * @rht: hash table containing struct ieee80211_mesh_fast_tx, using skb DA as key
51 + * @walk_head: linked list containing all ieee80211_mesh_fast_tx objects
52 + * @walk_lock: lock protecting walk_head and rht
53 + */
54 +struct mesh_tx_cache {
55 + struct rhashtable rht;
56 + struct hlist_head walk_head;
57 + spinlock_t walk_lock;
58 +};
59 +
60 struct ieee80211_if_mesh {
61 struct timer_list housekeeping_timer;
62 struct timer_list mesh_path_timer;
63 @@ -733,6 +747,7 @@ struct ieee80211_if_mesh {
64 struct mesh_table mpp_paths; /* Store paths for MPP&MAP */
65 int mesh_paths_generation;
66 int mpp_paths_generation;
67 + struct mesh_tx_cache tx_cache;
68 };
69
70 #ifdef CPTCFG_MAC80211_MESH
71 @@ -1998,6 +2013,11 @@ int ieee80211_tx_control_port(struct wip
72 int link_id, u64 *cookie);
73 int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
74 const u8 *buf, size_t len);
75 +void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
76 + struct sta_info *sta,
77 + struct ieee80211_fast_tx *fast_tx,
78 + struct sk_buff *skb, bool ampdu,
79 + const u8 *da, const u8 *sa);
80
81 /* HT */
82 void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
83 --- a/net/mac80211/mesh.c
84 +++ b/net/mac80211/mesh.c
85 @@ -10,6 +10,7 @@
86 #include <asm/unaligned.h>
87 #include "ieee80211_i.h"
88 #include "mesh.h"
89 +#include "wme.h"
90 #include "driver-ops.h"
91
92 static int mesh_allocated;
93 @@ -698,6 +699,102 @@ ieee80211_mesh_update_bss_params(struct
94 __le32_to_cpu(he_oper->he_oper_params);
95 }
96
97 +bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
98 + struct sk_buff *skb, u32 ctrl_flags)
99 +{
100 + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
101 + struct ieee80211_mesh_fast_tx *entry;
102 + struct ieee80211s_hdr *meshhdr;
103 + u8 sa[ETH_ALEN] __aligned(2);
104 + struct tid_ampdu_tx *tid_tx;
105 + struct sta_info *sta;
106 + bool copy_sa = false;
107 + u16 ethertype;
108 + u8 tid;
109 +
110 + if (ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP)
111 + return false;
112 +
113 + if (ifmsh->mshcfg.dot11MeshNolearn)
114 + return false;
115 +
116 + /* Add support for these cases later */
117 + if (ifmsh->ps_peers_light_sleep || ifmsh->ps_peers_deep_sleep)
118 + return false;
119 +
120 + if (is_multicast_ether_addr(skb->data))
121 + return false;
122 +
123 + ethertype = (skb->data[12] << 8) | skb->data[13];
124 + if (ethertype < ETH_P_802_3_MIN)
125 + return false;
126 +
127 + if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
128 + return false;
129 +
130 + if (skb->ip_summed == CHECKSUM_PARTIAL) {
131 + skb_set_transport_header(skb, skb_checksum_start_offset(skb));
132 + if (skb_checksum_help(skb))
133 + return false;
134 + }
135 +
136 + entry = mesh_fast_tx_get(sdata, skb->data);
137 + if (!entry)
138 + return false;
139 +
140 + if (skb_headroom(skb) + 2 * ETH_ALEN < entry->hdrlen +
141 + entry->fast_tx.hdr_len)
142 + return false;
143 +
144 + sta = rcu_dereference(entry->mpath->next_hop);
145 + if (!sta)
146 + return false;
147 +
148 + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
149 + tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
150 + if (tid_tx) {
151 + if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
152 + return false;
153 + if (tid_tx->timeout)
154 + tid_tx->last_tx = jiffies;
155 + }
156 +
157 + /* If the skb is shared we need to obtain our own copy */
158 + if (skb_shared(skb)) {
159 + struct sk_buff *oskb = skb;
160 +
161 + skb = skb_clone(skb, GFP_ATOMIC);
162 + if (!skb)
163 + return false;
164 +
165 + kfree_skb(oskb);
166 + }
167 +
168 + skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
169 +
170 + meshhdr = (struct ieee80211s_hdr *)entry->hdr;
171 + if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
172 + /* preserve SA from eth header for 6-addr frames */
173 + ether_addr_copy(sa, skb->data + ETH_ALEN);
174 + copy_sa = true;
175 + }
176 +
177 + memcpy(skb_push(skb, entry->hdrlen - 2 * ETH_ALEN), entry->hdr,
178 + entry->hdrlen);
179 +
180 + meshhdr = (struct ieee80211s_hdr *)skb->data;
181 + put_unaligned_le32(atomic_inc_return(&sdata->u.mesh.mesh_seqnum),
182 + &meshhdr->seqnum);
183 + meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
184 + if (copy_sa)
185 + ether_addr_copy(meshhdr->eaddr2, sa);
186 +
187 + __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx,
188 + entry->mpath->dst, sdata->vif.addr);
189 +
190 + return true;
191 +}
192 +
193 /**
194 * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
195 * @hdr: 802.11 frame header
196 @@ -780,6 +877,8 @@ static void ieee80211_mesh_housekeeping(
197 changed = mesh_accept_plinks_update(sdata);
198 ieee80211_mbss_info_change_notify(sdata, changed);
199
200 + mesh_fast_tx_gc(sdata);
201 +
202 mod_timer(&ifmsh->housekeeping_timer,
203 round_jiffies(jiffies +
204 IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
205 --- a/net/mac80211/mesh.h
206 +++ b/net/mac80211/mesh.h
207 @@ -122,11 +122,41 @@ struct mesh_path {
208 u8 rann_snd_addr[ETH_ALEN];
209 u32 rann_metric;
210 unsigned long last_preq_to_root;
211 + unsigned long fast_tx_check;
212 bool is_root;
213 bool is_gate;
214 u32 path_change_count;
215 };
216
217 +#define MESH_FAST_TX_CACHE_MAX_SIZE 512
218 +#define MESH_FAST_TX_CACHE_THRESHOLD_SIZE 384
219 +#define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */
220 +
221 +/**
222 + * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
223 + * @rhash: rhashtable pointer
224 + * @addr_key: The Ethernet DA which is the key for this entry
225 + * @fast_tx: base fast_tx data
226 + * @hdr: cached mesh and rfc1042 headers
227 + * @hdrlen: length of mesh + rfc1042
228 + * @walk_list: list containing all the fast tx entries
229 + * @mpath: mesh path corresponding to the Mesh DA
230 + * @mppath: MPP entry corresponding to this DA
231 + * @timestamp: Last used time of this entry
232 + */
233 +struct ieee80211_mesh_fast_tx {
234 + struct rhash_head rhash;
235 + u8 addr_key[ETH_ALEN] __aligned(2);
236 +
237 + struct ieee80211_fast_tx fast_tx;
238 + u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
239 + u16 hdrlen;
240 +
241 + struct mesh_path *mpath, *mppath;
242 + struct hlist_node walk_list;
243 + unsigned long timestamp;
244 +};
245 +
246 /* Recent multicast cache */
247 /* RMC_BUCKETS must be a power of 2, maximum 256 */
248 #define RMC_BUCKETS 256
249 @@ -298,6 +328,20 @@ void mesh_path_discard_frame(struct ieee
250 void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
251
252 bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
253 +struct ieee80211_mesh_fast_tx *
254 +mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
255 +bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
256 + struct sk_buff *skb, u32 ctrl_flags);
257 +void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
258 + struct sk_buff *skb, struct mesh_path *mpath);
259 +void mesh_fast_tx_gc(struct ieee80211_sub_if_data *sdata);
260 +void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata,
261 + const u8 *addr);
262 +void mesh_fast_tx_flush_mpath(struct mesh_path *mpath);
263 +void mesh_fast_tx_flush_sta(struct ieee80211_sub_if_data *sdata,
264 + struct sta_info *sta);
265 +void mesh_path_refresh(struct ieee80211_sub_if_data *sdata,
266 + struct mesh_path *mpath, const u8 *addr);
267
268 #ifdef CPTCFG_MAC80211_MESH
269 static inline
270 --- a/net/mac80211/mesh_hwmp.c
271 +++ b/net/mac80211/mesh_hwmp.c
272 @@ -394,6 +394,7 @@ static u32 hwmp_route_info_get(struct ie
273 u32 orig_sn, orig_metric;
274 unsigned long orig_lifetime, exp_time;
275 u32 last_hop_metric, new_metric;
276 + bool flush_mpath = false;
277 bool process = true;
278 u8 hopcount;
279
280 @@ -491,8 +492,10 @@ static u32 hwmp_route_info_get(struct ie
281 }
282
283 if (fresh_info) {
284 - if (rcu_access_pointer(mpath->next_hop) != sta)
285 + if (rcu_access_pointer(mpath->next_hop) != sta) {
286 mpath->path_change_count++;
287 + flush_mpath = true;
288 + }
289 mesh_path_assign_nexthop(mpath, sta);
290 mpath->flags |= MESH_PATH_SN_VALID;
291 mpath->metric = new_metric;
292 @@ -502,6 +505,8 @@ static u32 hwmp_route_info_get(struct ie
293 mpath->hop_count = hopcount;
294 mesh_path_activate(mpath);
295 spin_unlock_bh(&mpath->state_lock);
296 + if (flush_mpath)
297 + mesh_fast_tx_flush_mpath(mpath);
298 ewma_mesh_fail_avg_init(&sta->mesh->fail_avg);
299 /* init it at a low value - 0 start is tricky */
300 ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1);
301 @@ -539,8 +544,10 @@ static u32 hwmp_route_info_get(struct ie
302 }
303
304 if (fresh_info) {
305 - if (rcu_access_pointer(mpath->next_hop) != sta)
306 + if (rcu_access_pointer(mpath->next_hop) != sta) {
307 mpath->path_change_count++;
308 + flush_mpath = true;
309 + }
310 mesh_path_assign_nexthop(mpath, sta);
311 mpath->metric = last_hop_metric;
312 mpath->exp_time = time_after(mpath->exp_time, exp_time)
313 @@ -548,6 +555,8 @@ static u32 hwmp_route_info_get(struct ie
314 mpath->hop_count = 1;
315 mesh_path_activate(mpath);
316 spin_unlock_bh(&mpath->state_lock);
317 + if (flush_mpath)
318 + mesh_fast_tx_flush_mpath(mpath);
319 ewma_mesh_fail_avg_init(&sta->mesh->fail_avg);
320 /* init it at a low value - 0 start is tricky */
321 ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1);
322 @@ -1215,6 +1224,20 @@ static int mesh_nexthop_lookup_nolearn(s
323 return 0;
324 }
325
326 +void mesh_path_refresh(struct ieee80211_sub_if_data *sdata,
327 + struct mesh_path *mpath, const u8 *addr)
328 +{
329 + if (mpath->flags & (MESH_PATH_REQ_QUEUED | MESH_PATH_FIXED |
330 + MESH_PATH_RESOLVING))
331 + return;
332 +
333 + if (time_after(jiffies,
334 + mpath->exp_time -
335 + msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
336 + (!addr || ether_addr_equal(sdata->vif.addr, addr)))
337 + mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
338 +}
339 +
340 /**
341 * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling
342 * this function is considered "using" the associated mpath, so preempt a path
343 @@ -1242,19 +1265,15 @@ int mesh_nexthop_lookup(struct ieee80211
344 if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE))
345 return -ENOENT;
346
347 - if (time_after(jiffies,
348 - mpath->exp_time -
349 - msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
350 - ether_addr_equal(sdata->vif.addr, hdr->addr4) &&
351 - !(mpath->flags & MESH_PATH_RESOLVING) &&
352 - !(mpath->flags & MESH_PATH_FIXED))
353 - mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
354 + mesh_path_refresh(sdata, mpath, hdr->addr4);
355
356 next_hop = rcu_dereference(mpath->next_hop);
357 if (next_hop) {
358 memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
359 memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
360 ieee80211_mps_set_frame_flags(sdata, next_hop, hdr);
361 + if (ieee80211_hw_check(&sdata->local->hw, SUPPORT_FAST_XMIT))
362 + mesh_fast_tx_cache(sdata, skb, mpath);
363 return 0;
364 }
365
366 --- a/net/mac80211/mesh_pathtbl.c
367 +++ b/net/mac80211/mesh_pathtbl.c
368 @@ -14,6 +14,7 @@
369 #include "wme.h"
370 #include "ieee80211_i.h"
371 #include "mesh.h"
372 +#include <linux/rhashtable.h>
373
374 static void mesh_path_free_rcu(struct mesh_table *tbl, struct mesh_path *mpath);
375
376 @@ -32,6 +33,41 @@ static const struct rhashtable_params me
377 .hashfn = mesh_table_hash,
378 };
379
380 +static const struct rhashtable_params fast_tx_rht_params = {
381 + .nelem_hint = 10,
382 + .automatic_shrinking = true,
383 + .key_len = ETH_ALEN,
384 + .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
385 + .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
386 + .hashfn = mesh_table_hash,
387 +};
388 +
389 +static void __mesh_fast_tx_entry_free(void *ptr, void *tblptr)
390 +{
391 + struct ieee80211_mesh_fast_tx *entry = ptr;
392 +
393 + kfree_rcu(entry, fast_tx.rcu_head);
394 +}
395 +
396 +static void mesh_fast_tx_deinit(struct ieee80211_sub_if_data *sdata)
397 +{
398 + struct mesh_tx_cache *cache;
399 +
400 + cache = &sdata->u.mesh.tx_cache;
401 + rhashtable_free_and_destroy(&cache->rht,
402 + __mesh_fast_tx_entry_free, NULL);
403 +}
404 +
405 +static void mesh_fast_tx_init(struct ieee80211_sub_if_data *sdata)
406 +{
407 + struct mesh_tx_cache *cache;
408 +
409 + cache = &sdata->u.mesh.tx_cache;
410 + rhashtable_init(&cache->rht, &fast_tx_rht_params);
411 + INIT_HLIST_HEAD(&cache->walk_head);
412 + spin_lock_init(&cache->walk_lock);
413 +}
414 +
415 static inline bool mpath_expired(struct mesh_path *mpath)
416 {
417 return (mpath->flags & MESH_PATH_ACTIVE) &&
418 @@ -381,6 +417,243 @@ struct mesh_path *mesh_path_new(struct i
419 return new_mpath;
420 }
421
422 +static void mesh_fast_tx_entry_free(struct mesh_tx_cache *cache,
423 + struct ieee80211_mesh_fast_tx *entry)
424 +{
425 + hlist_del_rcu(&entry->walk_list);
426 + rhashtable_remove_fast(&cache->rht, &entry->rhash, fast_tx_rht_params);
427 + kfree_rcu(entry, fast_tx.rcu_head);
428 +}
429 +
430 +struct ieee80211_mesh_fast_tx *
431 +mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
432 +{
433 + struct ieee80211_mesh_fast_tx *entry;
434 + struct mesh_tx_cache *cache;
435 +
436 + cache = &sdata->u.mesh.tx_cache;
437 + entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
438 + if (!entry)
439 + return NULL;
440 +
441 + if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
442 + mpath_expired(entry->mpath)) {
443 + spin_lock_bh(&cache->walk_lock);
444 + entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
445 + if (entry)
446 + mesh_fast_tx_entry_free(cache, entry);
447 + spin_unlock_bh(&cache->walk_lock);
448 + return NULL;
449 + }
450 +
451 + mesh_path_refresh(sdata, entry->mpath, NULL);
452 + if (entry->mppath)
453 + entry->mppath->exp_time = jiffies;
454 + entry->timestamp = jiffies;
455 +
456 + return entry;
457 +}
458 +
459 +void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
460 + struct sk_buff *skb, struct mesh_path *mpath)
461 +{
462 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
463 + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
464 + struct ieee80211_mesh_fast_tx *entry, *prev;
465 + struct ieee80211_mesh_fast_tx build = {};
466 + struct ieee80211s_hdr *meshhdr;
467 + struct mesh_tx_cache *cache;
468 + struct ieee80211_key *key;
469 + struct mesh_path *mppath;
470 + struct sta_info *sta;
471 + u8 *qc;
472 +
473 + if (sdata->noack_map ||
474 + !ieee80211_is_data_qos(hdr->frame_control))
475 + return;
476 +
477 + build.fast_tx.hdr_len = ieee80211_hdrlen(hdr->frame_control);
478 + meshhdr = (struct ieee80211s_hdr *)(skb->data + build.fast_tx.hdr_len);
479 + build.hdrlen = ieee80211_get_mesh_hdrlen(meshhdr);
480 +
481 + cache = &sdata->u.mesh.tx_cache;
482 + if (atomic_read(&cache->rht.nelems) >= MESH_FAST_TX_CACHE_MAX_SIZE)
483 + return;
484 +
485 + sta = rcu_dereference(mpath->next_hop);
486 + if (!sta)
487 + return;
488 +
489 + if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
490 + /* This is required to keep the mppath alive */
491 + mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
492 + if (!mppath)
493 + return;
494 + build.mppath = mppath;
495 + } else if (ieee80211_has_a4(hdr->frame_control)) {
496 + mppath = mpath;
497 + } else {
498 + return;
499 + }
500 +
501 + /* rate limit, in case fast xmit can't be enabled */
502 + if (mppath->fast_tx_check == jiffies)
503 + return;
504 +
505 + mppath->fast_tx_check = jiffies;
506 +
507 + /*
508 + * Same use of the sta lock as in ieee80211_check_fast_xmit, in order
509 + * to protect against concurrent sta key updates.
510 + */
511 + spin_lock_bh(&sta->lock);
512 + key = rcu_access_pointer(sta->ptk[sta->ptk_idx]);
513 + if (!key)
514 + key = rcu_access_pointer(sdata->default_unicast_key);
515 + build.fast_tx.key = key;
516 +
517 + if (key) {
518 + bool gen_iv, iv_spc;
519 +
520 + gen_iv = key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV;
521 + iv_spc = key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE;
522 +
523 + if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
524 + (key->flags & KEY_FLAG_TAINTED))
525 + goto unlock_sta;
526 +
527 + switch (key->conf.cipher) {
528 + case WLAN_CIPHER_SUITE_CCMP:
529 + case WLAN_CIPHER_SUITE_CCMP_256:
530 + if (gen_iv)
531 + build.fast_tx.pn_offs = build.fast_tx.hdr_len;
532 + if (gen_iv || iv_spc)
533 + build.fast_tx.hdr_len += IEEE80211_CCMP_HDR_LEN;
534 + break;
535 + case WLAN_CIPHER_SUITE_GCMP:
536 + case WLAN_CIPHER_SUITE_GCMP_256:
537 + if (gen_iv)
538 + build.fast_tx.pn_offs = build.fast_tx.hdr_len;
539 + if (gen_iv || iv_spc)
540 + build.fast_tx.hdr_len += IEEE80211_GCMP_HDR_LEN;
541 + break;
542 + default:
543 + goto unlock_sta;
544 + }
545 + }
546 +
547 + memcpy(build.addr_key, mppath->dst, ETH_ALEN);
548 + build.timestamp = jiffies;
549 + build.fast_tx.band = info->band;
550 + build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
551 + build.fast_tx.sa_offs = offsetof(struct ieee80211_hdr, addr4);
552 + build.mpath = mpath;
553 + memcpy(build.hdr, meshhdr, build.hdrlen);
554 + memcpy(build.hdr + build.hdrlen, rfc1042_header, sizeof(rfc1042_header));
555 + build.hdrlen += sizeof(rfc1042_header);
556 + memcpy(build.fast_tx.hdr, hdr, build.fast_tx.hdr_len);
557 +
558 + hdr = (struct ieee80211_hdr *)build.fast_tx.hdr;
559 + if (build.fast_tx.key)
560 + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
561 +
562 + qc = ieee80211_get_qos_ctl(hdr);
563 + qc[1] |= IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8;
564 +
565 + entry = kmemdup(&build, sizeof(build), GFP_ATOMIC);
566 + if (!entry)
567 + goto unlock_sta;
568 +
569 + spin_lock_bh(&cache->walk_lock);
570 + prev = rhashtable_lookup_get_insert_fast(&cache->rht,
571 + &entry->rhash,
572 + fast_tx_rht_params);
573 + if (unlikely(IS_ERR(prev))) {
574 + kfree(entry);
575 + goto unlock_cache;
576 + }
577 +
578 + /*
579 + * replace any previous entry in the hash table, in case we're
580 + * replacing it with a different type (e.g. mpath -> mpp)
581 + */
582 + if (unlikely(prev)) {
583 + rhashtable_replace_fast(&cache->rht, &prev->rhash,
584 + &entry->rhash, fast_tx_rht_params);
585 + hlist_del_rcu(&prev->walk_list);
586 + kfree_rcu(prev, fast_tx.rcu_head);
587 + }
588 +
589 + hlist_add_head(&entry->walk_list, &cache->walk_head);
590 +
591 +unlock_cache:
592 + spin_unlock_bh(&cache->walk_lock);
593 +unlock_sta:
594 + spin_unlock_bh(&sta->lock);
595 +}
596 +
597 +void mesh_fast_tx_gc(struct ieee80211_sub_if_data *sdata)
598 +{
599 + unsigned long timeout = msecs_to_jiffies(MESH_FAST_TX_CACHE_TIMEOUT);
600 + struct mesh_tx_cache *cache;
601 + struct ieee80211_mesh_fast_tx *entry;
602 + struct hlist_node *n;
603 +
604 + cache = &sdata->u.mesh.tx_cache;
605 + if (atomic_read(&cache->rht.nelems) < MESH_FAST_TX_CACHE_THRESHOLD_SIZE)
606 + return;
607 +
608 + spin_lock_bh(&cache->walk_lock);
609 + hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
610 + if (!time_is_after_jiffies(entry->timestamp + timeout))
611 + mesh_fast_tx_entry_free(cache, entry);
612 + spin_unlock_bh(&cache->walk_lock);
613 +}
614 +
615 +void mesh_fast_tx_flush_mpath(struct mesh_path *mpath)
616 +{
617 + struct ieee80211_sub_if_data *sdata = mpath->sdata;
618 + struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
619 + struct ieee80211_mesh_fast_tx *entry;
620 + struct hlist_node *n;
621 +
622 + cache = &sdata->u.mesh.tx_cache;
623 + spin_lock_bh(&cache->walk_lock);
624 + hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
625 + if (entry->mpath == mpath)
626 + mesh_fast_tx_entry_free(cache, entry);
627 + spin_unlock_bh(&cache->walk_lock);
628 +}
629 +
630 +void mesh_fast_tx_flush_sta(struct ieee80211_sub_if_data *sdata,
631 + struct sta_info *sta)
632 +{
633 + struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
634 + struct ieee80211_mesh_fast_tx *entry;
635 + struct hlist_node *n;
636 +
637 + cache = &sdata->u.mesh.tx_cache;
638 + spin_lock_bh(&cache->walk_lock);
639 + hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
640 + if (rcu_access_pointer(entry->mpath->next_hop) == sta)
641 + mesh_fast_tx_entry_free(cache, entry);
642 + spin_unlock_bh(&cache->walk_lock);
643 +}
644 +
645 +void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata,
646 + const u8 *addr)
647 +{
648 + struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
649 + struct ieee80211_mesh_fast_tx *entry;
650 +
651 + cache = &sdata->u.mesh.tx_cache;
652 + spin_lock_bh(&cache->walk_lock);
653 + entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
654 + if (entry)
655 + mesh_fast_tx_entry_free(cache, entry);
656 + spin_unlock_bh(&cache->walk_lock);
657 +}
658 +
659 /**
660 * mesh_path_add - allocate and add a new path to the mesh path table
661 * @dst: destination address of the path (ETH_ALEN length)
662 @@ -464,6 +737,8 @@ int mpp_path_add(struct ieee80211_sub_if
663
664 if (ret)
665 kfree(new_mpath);
666 + else
667 + mesh_fast_tx_flush_addr(sdata, dst);
668
669 sdata->u.mesh.mpp_paths_generation++;
670 return ret;
671 @@ -523,6 +798,10 @@ static void __mesh_path_del(struct mesh_
672 {
673 hlist_del_rcu(&mpath->walk_list);
674 rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params);
675 + if (tbl == &mpath->sdata->u.mesh.mpp_paths)
676 + mesh_fast_tx_flush_addr(mpath->sdata, mpath->dst);
677 + else
678 + mesh_fast_tx_flush_mpath(mpath);
679 mesh_path_free_rcu(tbl, mpath);
680 }
681
682 @@ -747,6 +1026,7 @@ void mesh_path_fix_nexthop(struct mesh_p
683 mpath->exp_time = 0;
684 mpath->flags = MESH_PATH_FIXED | MESH_PATH_SN_VALID;
685 mesh_path_activate(mpath);
686 + mesh_fast_tx_flush_mpath(mpath);
687 spin_unlock_bh(&mpath->state_lock);
688 ewma_mesh_fail_avg_init(&next_hop->mesh->fail_avg);
689 /* init it at a low value - 0 start is tricky */
690 @@ -758,6 +1038,7 @@ void mesh_pathtbl_init(struct ieee80211_
691 {
692 mesh_table_init(&sdata->u.mesh.mesh_paths);
693 mesh_table_init(&sdata->u.mesh.mpp_paths);
694 + mesh_fast_tx_init(sdata);
695 }
696
697 static
698 @@ -785,6 +1066,7 @@ void mesh_path_expire(struct ieee80211_s
699
700 void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata)
701 {
702 + mesh_fast_tx_deinit(sdata);
703 mesh_table_free(&sdata->u.mesh.mesh_paths);
704 mesh_table_free(&sdata->u.mesh.mpp_paths);
705 }
706 --- a/net/mac80211/rx.c
707 +++ b/net/mac80211/rx.c
708 @@ -2791,6 +2791,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
709 if (mesh_hdr->flags & MESH_FLAGS_AE) {
710 struct mesh_path *mppath;
711 char *proxied_addr;
712 + bool update = false;
713
714 if (multicast)
715 proxied_addr = mesh_hdr->eaddr1;
716 @@ -2806,11 +2807,18 @@ ieee80211_rx_mesh_data(struct ieee80211_
717 mpp_path_add(sdata, proxied_addr, eth->h_source);
718 } else {
719 spin_lock_bh(&mppath->state_lock);
720 - if (!ether_addr_equal(mppath->mpp, eth->h_source))
721 + if (!ether_addr_equal(mppath->mpp, eth->h_source)) {
722 memcpy(mppath->mpp, eth->h_source, ETH_ALEN);
723 + update = true;
724 + }
725 mppath->exp_time = jiffies;
726 spin_unlock_bh(&mppath->state_lock);
727 }
728 +
729 + /* flush fast xmit cache if the address path changed */
730 + if (update)
731 + mesh_fast_tx_flush_addr(sdata, proxied_addr);
732 +
733 rcu_read_unlock();
734 }
735
736 --- a/net/mac80211/tx.c
737 +++ b/net/mac80211/tx.c
738 @@ -3021,6 +3021,9 @@ void ieee80211_check_fast_xmit(struct st
739 if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT))
740 return;
741
742 + if (ieee80211_vif_is_mesh(&sdata->vif))
743 + mesh_fast_tx_flush_sta(sdata, sta);
744 +
745 /* Locking here protects both the pointer itself, and against concurrent
746 * invocations winning data access races to, e.g., the key pointer that
747 * is used.
748 @@ -3402,6 +3405,9 @@ static bool ieee80211_amsdu_aggregate(st
749 if (sdata->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
750 return false;
751
752 + if (ieee80211_vif_is_mesh(&sdata->vif))
753 + return false;
754 +
755 if (skb_is_gso(skb))
756 return false;
757
758 @@ -3634,10 +3640,11 @@ free:
759 return NULL;
760 }
761
762 -static void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
763 - struct sta_info *sta,
764 - struct ieee80211_fast_tx *fast_tx,
765 - struct sk_buff *skb, u8 tid, bool ampdu)
766 +void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
767 + struct sta_info *sta,
768 + struct ieee80211_fast_tx *fast_tx,
769 + struct sk_buff *skb, bool ampdu,
770 + const u8 *da, const u8 *sa)
771 {
772 struct ieee80211_local *local = sdata->local;
773 struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
774 @@ -3645,8 +3652,6 @@ static void __ieee80211_xmit_fast(struct
775 struct ieee80211_tx_data tx;
776 ieee80211_tx_result r;
777 int hw_headroom = sdata->local->hw.extra_tx_headroom;
778 - int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
779 - struct ethhdr eth;
780
781 skb = skb_share_check(skb, GFP_ATOMIC);
782 if (unlikely(!skb))
783 @@ -3661,16 +3666,15 @@ static void __ieee80211_xmit_fast(struct
784 * more room than we already have in 'extra_head'
785 */
786 if (unlikely(ieee80211_skb_resize(sdata, skb,
787 - max_t(int, extra_head + hw_headroom -
788 + max_t(int, fast_tx->hdr_len + hw_headroom -
789 skb_headroom(skb), 0),
790 ENCRYPT_NO)))
791 goto free;
792
793 - memcpy(&eth, skb->data, ETH_HLEN - 2);
794 - hdr = skb_push(skb, extra_head);
795 + hdr = skb_push(skb, fast_tx->hdr_len);
796 memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len);
797 - memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN);
798 - memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN);
799 + memcpy(skb->data + fast_tx->da_offs, da, ETH_ALEN);
800 + memcpy(skb->data + fast_tx->sa_offs, sa, ETH_ALEN);
801
802 info = IEEE80211_SKB_CB(skb);
803 memset(info, 0, sizeof(*info));
804 @@ -3689,7 +3693,7 @@ static void __ieee80211_xmit_fast(struct
805 #endif
806
807 if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
808 - tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
809 + u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
810 *ieee80211_get_qos_ctl(hdr) = tid;
811 }
812
813 @@ -3732,6 +3736,7 @@ static bool ieee80211_xmit_fast(struct i
814 struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
815 struct tid_ampdu_tx *tid_tx = NULL;
816 struct sk_buff *next;
817 + struct ethhdr eth;
818 u8 tid = IEEE80211_NUM_TIDS;
819
820 /* control port protocol needs a lot of special handling */
821 @@ -3757,14 +3762,18 @@ static bool ieee80211_xmit_fast(struct i
822 }
823 }
824
825 + memcpy(&eth, skb->data, ETH_HLEN - 2);
826 +
827 /* after this point (skb is modified) we cannot return false */
828 + skb_pull(skb, ETH_HLEN - 2);
829 skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
830 if (!skb)
831 return true;
832
833 skb_list_walk_safe(skb, skb, next) {
834 skb_mark_not_on_list(skb);
835 - __ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid, tid_tx);
836 + __ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid_tx,
837 + eth.h_dest, eth.h_source);
838 }
839
840 return true;
841 @@ -4244,8 +4253,15 @@ void __ieee80211_subif_start_xmit(struct
842 return;
843 }
844
845 + sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
846 +
847 rcu_read_lock();
848
849 + if (ieee80211_vif_is_mesh(&sdata->vif) &&
850 + ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT) &&
851 + ieee80211_mesh_xmit_fast(sdata, skb, ctrl_flags))
852 + goto out;
853 +
854 if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
855 goto out_free;
856
857 @@ -4255,8 +4271,6 @@ void __ieee80211_subif_start_xmit(struct
858 skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
859 ieee80211_aggr_check(sdata, sta, skb);
860
861 - sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
862 -
863 if (sta) {
864 struct ieee80211_fast_tx *fast_tx;
865