1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Fri, 30 Jun 2023 13:11:51 +0200
3 Subject: [PATCH] mac80211: split mesh fast tx cache into
4 local/proxied/forwarded
6 Depending on the origin of the packets (and their SA), 802.11 + mesh headers
7 could be filled in differently. In order to properly deal with that, add a
8 new field to the lookup key, indicating the type (local, proxied or
9 forwarded). This can fix spurious packet drop issues that depend on the order
10 in which nodes/hosts communicate with each other.
12 Signed-off-by: Felix Fietkau <nbd@nbd.name>
15 --- a/net/mac80211/mesh.c
16 +++ b/net/mac80211/mesh.c
17 @@ -765,6 +765,9 @@ bool ieee80211_mesh_xmit_fast(struct iee
18 struct sk_buff *skb, u32 ctrl_flags)
20 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
21 + struct ieee80211_mesh_fast_tx_key key = {
22 + .type = MESH_FAST_TX_TYPE_LOCAL
24 struct ieee80211_mesh_fast_tx *entry;
25 struct ieee80211s_hdr *meshhdr;
26 u8 sa[ETH_ALEN] __aligned(2);
27 @@ -800,7 +803,10 @@ bool ieee80211_mesh_xmit_fast(struct iee
31 - entry = mesh_fast_tx_get(sdata, skb->data);
32 + ether_addr_copy(key.addr, skb->data);
33 + if (!ether_addr_equal(skb->data + ETH_ALEN, sdata->vif.addr))
34 + key.type = MESH_FAST_TX_TYPE_PROXIED;
35 + entry = mesh_fast_tx_get(sdata, &key);
39 --- a/net/mac80211/mesh.h
40 +++ b/net/mac80211/mesh.h
41 @@ -134,9 +134,38 @@ struct mesh_path {
42 #define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */
45 + * enum ieee80211_mesh_fast_tx_type - cached mesh fast tx entry type
47 + * @MESH_FAST_TX_TYPE_LOCAL: tx from the local vif address as SA
48 + * @MESH_FAST_TX_TYPE_PROXIED: local tx with a different SA (e.g. bridged)
49 + * @MESH_FAST_TX_TYPE_FORWARDED: forwarded from a different mesh point
50 + * @NUM_MESH_FAST_TX_TYPE: number of entry types
52 +enum ieee80211_mesh_fast_tx_type {
53 + MESH_FAST_TX_TYPE_LOCAL,
54 + MESH_FAST_TX_TYPE_PROXIED,
55 + MESH_FAST_TX_TYPE_FORWARDED,
58 + NUM_MESH_FAST_TX_TYPE
63 + * struct ieee80211_mesh_fast_tx_key - cached mesh fast tx entry key
65 + * @addr: The Ethernet DA for this entry
66 + * @type: cache entry type
68 +struct ieee80211_mesh_fast_tx_key {
69 + u8 addr[ETH_ALEN] __aligned(2);
74 * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
75 * @rhash: rhashtable pointer
76 - * @addr_key: The Ethernet DA which is the key for this entry
77 + * @key: the lookup key for this cache entry
78 * @fast_tx: base fast_tx data
79 * @hdr: cached mesh and rfc1042 headers
80 * @hdrlen: length of mesh + rfc1042
81 @@ -147,7 +176,7 @@ struct mesh_path {
83 struct ieee80211_mesh_fast_tx {
84 struct rhash_head rhash;
85 - u8 addr_key[ETH_ALEN] __aligned(2);
86 + struct ieee80211_mesh_fast_tx_key key;
88 struct ieee80211_fast_tx fast_tx;
89 u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
90 @@ -333,7 +362,8 @@ void mesh_path_tx_root_frame(struct ieee
92 bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
93 struct ieee80211_mesh_fast_tx *
94 -mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
95 +mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
96 + struct ieee80211_mesh_fast_tx_key *key);
97 bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
98 struct sk_buff *skb, u32 ctrl_flags);
99 void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
100 --- a/net/mac80211/mesh_pathtbl.c
101 +++ b/net/mac80211/mesh_pathtbl.c
102 @@ -36,8 +36,8 @@ static const struct rhashtable_params me
103 static const struct rhashtable_params fast_tx_rht_params = {
105 .automatic_shrinking = true,
106 - .key_len = ETH_ALEN,
107 - .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
108 + .key_len = sizeof(struct ieee80211_mesh_fast_tx_key),
109 + .key_offset = offsetof(struct ieee80211_mesh_fast_tx, key),
110 .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
111 .hashfn = mesh_table_hash,
113 @@ -426,20 +426,21 @@ static void mesh_fast_tx_entry_free(stru
116 struct ieee80211_mesh_fast_tx *
117 -mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
118 +mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
119 + struct ieee80211_mesh_fast_tx_key *key)
121 struct ieee80211_mesh_fast_tx *entry;
122 struct mesh_tx_cache *cache;
124 cache = &sdata->u.mesh.tx_cache;
125 - entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
126 + entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
130 if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
131 mpath_expired(entry->mpath)) {
132 spin_lock_bh(&cache->walk_lock);
133 - entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
134 + entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
136 mesh_fast_tx_entry_free(cache, entry);
137 spin_unlock_bh(&cache->walk_lock);
138 @@ -484,18 +485,24 @@ void mesh_fast_tx_cache(struct ieee80211
142 + build.key.type = MESH_FAST_TX_TYPE_LOCAL;
143 if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
144 /* This is required to keep the mppath alive */
145 mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
148 build.mppath = mppath;
149 + if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr))
150 + build.key.type = MESH_FAST_TX_TYPE_PROXIED;
151 } else if (ieee80211_has_a4(hdr->frame_control)) {
157 + if (!ether_addr_equal(hdr->addr4, sdata->vif.addr))
158 + build.key.type = MESH_FAST_TX_TYPE_FORWARDED;
160 /* rate limit, in case fast xmit can't be enabled */
161 if (mppath->fast_tx_check == jiffies)
163 @@ -542,7 +549,7 @@ void mesh_fast_tx_cache(struct ieee80211
167 - memcpy(build.addr_key, mppath->dst, ETH_ALEN);
168 + memcpy(build.key.addr, mppath->dst, ETH_ALEN);
169 build.timestamp = jiffies;
170 build.fast_tx.band = info->band;
171 build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
172 @@ -644,13 +651,19 @@ void mesh_fast_tx_flush_addr(struct ieee
175 struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
176 + struct ieee80211_mesh_fast_tx_key key = {};
177 struct ieee80211_mesh_fast_tx *entry;
180 + ether_addr_copy(key.addr, addr);
181 cache = &sdata->u.mesh.tx_cache;
182 spin_lock_bh(&cache->walk_lock);
183 - entry = rhashtable_lookup_fast(&cache->rht, addr, fast_tx_rht_params);
185 - mesh_fast_tx_entry_free(cache, entry);
186 + for (i = 0; i < NUM_MESH_FAST_TX_TYPE; i++) {
188 + entry = rhashtable_lookup_fast(&cache->rht, &key, fast_tx_rht_params);
190 + mesh_fast_tx_entry_free(cache, entry);
192 spin_unlock_bh(&cache->walk_lock);
195 --- a/net/mac80211/rx.c
196 +++ b/net/mac80211/rx.c
197 @@ -2726,7 +2726,10 @@ ieee80211_rx_mesh_fast_forward(struct ie
198 struct sk_buff *skb, int hdrlen)
200 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
201 - struct ieee80211_mesh_fast_tx *entry = NULL;
202 + struct ieee80211_mesh_fast_tx_key key = {
203 + .type = MESH_FAST_TX_TYPE_FORWARDED
205 + struct ieee80211_mesh_fast_tx *entry;
206 struct ieee80211s_hdr *mesh_hdr;
207 struct tid_ampdu_tx *tid_tx;
208 struct sta_info *sta;
209 @@ -2735,9 +2738,13 @@ ieee80211_rx_mesh_fast_forward(struct ie
211 mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
212 if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
213 - entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
214 + ether_addr_copy(key.addr, mesh_hdr->eaddr1);
215 else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
216 - entry = mesh_fast_tx_get(sdata, skb->data);
217 + ether_addr_copy(key.addr, skb->data);
221 + entry = mesh_fast_tx_get(sdata, &key);