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