Skip to content

Commit 8c75cdc

Browse files
nbd168jmberg-intel
authored andcommitted
wifi: mac80211: split mesh fast tx cache into local/proxied/forwarded
Depending on the origin of the packets (and their SA), 802.11 + mesh headers could be filled in differently. In order to properly deal with that, add a new field to the lookup key, indicating the type (local, proxied or forwarded). This can fix spurious packet drop issues that depend on the order in which nodes/hosts communicate with each other. Fixes: d5edb9a ("wifi: mac80211: mesh fast xmit support") Signed-off-by: Felix Fietkau <[email protected]> Link: https://msgid.link/[email protected] [use sizeof_field() for key_len] Signed-off-by: Johannes Berg <[email protected]>
1 parent feafe59 commit 8c75cdc

File tree

4 files changed

+72
-16
lines changed

4 files changed

+72
-16
lines changed

net/mac80211/mesh.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,9 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
747747
struct sk_buff *skb, u32 ctrl_flags)
748748
{
749749
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
750+
struct ieee80211_mesh_fast_tx_key key = {
751+
.type = MESH_FAST_TX_TYPE_LOCAL
752+
};
750753
struct ieee80211_mesh_fast_tx *entry;
751754
struct ieee80211s_hdr *meshhdr;
752755
u8 sa[ETH_ALEN] __aligned(2);
@@ -782,7 +785,10 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
782785
return false;
783786
}
784787

785-
entry = mesh_fast_tx_get(sdata, skb->data);
788+
ether_addr_copy(key.addr, skb->data);
789+
if (!ether_addr_equal(skb->data + ETH_ALEN, sdata->vif.addr))
790+
key.type = MESH_FAST_TX_TYPE_PROXIED;
791+
entry = mesh_fast_tx_get(sdata, &key);
786792
if (!entry)
787793
return false;
788794

net/mac80211/mesh.h

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,39 @@ struct mesh_path {
134134
#define MESH_FAST_TX_CACHE_THRESHOLD_SIZE 384
135135
#define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */
136136

137+
/**
138+
* enum ieee80211_mesh_fast_tx_type - cached mesh fast tx entry type
139+
*
140+
* @MESH_FAST_TX_TYPE_LOCAL: tx from the local vif address as SA
141+
* @MESH_FAST_TX_TYPE_PROXIED: local tx with a different SA (e.g. bridged)
142+
* @MESH_FAST_TX_TYPE_FORWARDED: forwarded from a different mesh point
143+
* @NUM_MESH_FAST_TX_TYPE: number of entry types
144+
*/
145+
enum ieee80211_mesh_fast_tx_type {
146+
MESH_FAST_TX_TYPE_LOCAL,
147+
MESH_FAST_TX_TYPE_PROXIED,
148+
MESH_FAST_TX_TYPE_FORWARDED,
149+
150+
/* must be last */
151+
NUM_MESH_FAST_TX_TYPE
152+
};
153+
154+
155+
/**
156+
* struct ieee80211_mesh_fast_tx_key - cached mesh fast tx entry key
157+
*
158+
* @addr: The Ethernet DA for this entry
159+
* @type: cache entry type
160+
*/
161+
struct ieee80211_mesh_fast_tx_key {
162+
u8 addr[ETH_ALEN] __aligned(2);
163+
u16 type;
164+
};
165+
137166
/**
138167
* struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
139168
* @rhash: rhashtable pointer
140-
* @addr_key: The Ethernet DA which is the key for this entry
169+
* @key: the lookup key for this cache entry
141170
* @fast_tx: base fast_tx data
142171
* @hdr: cached mesh and rfc1042 headers
143172
* @hdrlen: length of mesh + rfc1042
@@ -148,7 +177,7 @@ struct mesh_path {
148177
*/
149178
struct ieee80211_mesh_fast_tx {
150179
struct rhash_head rhash;
151-
u8 addr_key[ETH_ALEN] __aligned(2);
180+
struct ieee80211_mesh_fast_tx_key key;
152181

153182
struct ieee80211_fast_tx fast_tx;
154183
u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
@@ -334,7 +363,8 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
334363

335364
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
336365
struct ieee80211_mesh_fast_tx *
337-
mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
366+
mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
367+
struct ieee80211_mesh_fast_tx_key *key);
338368
bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
339369
struct sk_buff *skb, u32 ctrl_flags);
340370
void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,

net/mac80211/mesh_pathtbl.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ static const struct rhashtable_params mesh_rht_params = {
3737
static const struct rhashtable_params fast_tx_rht_params = {
3838
.nelem_hint = 10,
3939
.automatic_shrinking = true,
40-
.key_len = ETH_ALEN,
41-
.key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
40+
.key_len = sizeof_field(struct ieee80211_mesh_fast_tx, key),
41+
.key_offset = offsetof(struct ieee80211_mesh_fast_tx, key),
4242
.head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
4343
.hashfn = mesh_table_hash,
4444
};
@@ -431,20 +431,21 @@ static void mesh_fast_tx_entry_free(struct mesh_tx_cache *cache,
431431
}
432432

433433
struct ieee80211_mesh_fast_tx *
434-
mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
434+
mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
435+
struct ieee80211_mesh_fast_tx_key *key)
435436
{
436437
struct ieee80211_mesh_fast_tx *entry;
437438
struct mesh_tx_cache *cache;
438439

439440
cache = &sdata->u.mesh.tx_cache;
440-
entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
441+
entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
441442
if (!entry)
442443
return NULL;
443444

444445
if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
445446
mpath_expired(entry->mpath)) {
446447
spin_lock_bh(&cache->walk_lock);
447-
entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
448+
entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
448449
if (entry)
449450
mesh_fast_tx_entry_free(cache, entry);
450451
spin_unlock_bh(&cache->walk_lock);
@@ -489,18 +490,24 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
489490
if (!sta)
490491
return;
491492

493+
build.key.type = MESH_FAST_TX_TYPE_LOCAL;
492494
if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
493495
/* This is required to keep the mppath alive */
494496
mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
495497
if (!mppath)
496498
return;
497499
build.mppath = mppath;
500+
if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr))
501+
build.key.type = MESH_FAST_TX_TYPE_PROXIED;
498502
} else if (ieee80211_has_a4(hdr->frame_control)) {
499503
mppath = mpath;
500504
} else {
501505
return;
502506
}
503507

508+
if (!ether_addr_equal(hdr->addr4, sdata->vif.addr))
509+
build.key.type = MESH_FAST_TX_TYPE_FORWARDED;
510+
504511
/* rate limit, in case fast xmit can't be enabled */
505512
if (mppath->fast_tx_check == jiffies)
506513
return;
@@ -547,7 +554,7 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
547554
}
548555
}
549556

550-
memcpy(build.addr_key, mppath->dst, ETH_ALEN);
557+
memcpy(build.key.addr, mppath->dst, ETH_ALEN);
551558
build.timestamp = jiffies;
552559
build.fast_tx.band = info->band;
553560
build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
@@ -646,12 +653,18 @@ void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata,
646653
const u8 *addr)
647654
{
648655
struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
656+
struct ieee80211_mesh_fast_tx_key key = {};
649657
struct ieee80211_mesh_fast_tx *entry;
658+
int i;
650659

660+
ether_addr_copy(key.addr, addr);
651661
spin_lock_bh(&cache->walk_lock);
652-
entry = rhashtable_lookup_fast(&cache->rht, addr, fast_tx_rht_params);
653-
if (entry)
654-
mesh_fast_tx_entry_free(cache, entry);
662+
for (i = 0; i < NUM_MESH_FAST_TX_TYPE; i++) {
663+
key.type = i;
664+
entry = rhashtable_lookup_fast(&cache->rht, &key, fast_tx_rht_params);
665+
if (entry)
666+
mesh_fast_tx_entry_free(cache, entry);
667+
}
655668
spin_unlock_bh(&cache->walk_lock);
656669
}
657670

net/mac80211/rx.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2763,7 +2763,10 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
27632763
struct sk_buff *skb, int hdrlen)
27642764
{
27652765
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
2766-
struct ieee80211_mesh_fast_tx *entry = NULL;
2766+
struct ieee80211_mesh_fast_tx_key key = {
2767+
.type = MESH_FAST_TX_TYPE_FORWARDED
2768+
};
2769+
struct ieee80211_mesh_fast_tx *entry;
27672770
struct ieee80211s_hdr *mesh_hdr;
27682771
struct tid_ampdu_tx *tid_tx;
27692772
struct sta_info *sta;
@@ -2772,9 +2775,13 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
27722775

27732776
mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
27742777
if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
2775-
entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
2778+
ether_addr_copy(key.addr, mesh_hdr->eaddr1);
27762779
else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
2777-
entry = mesh_fast_tx_get(sdata, skb->data);
2780+
ether_addr_copy(key.addr, skb->data);
2781+
else
2782+
return false;
2783+
2784+
entry = mesh_fast_tx_get(sdata, &key);
27782785
if (!entry)
27792786
return false;
27802787

0 commit comments

Comments
 (0)