blob: 4853cef723171e82906dabb649a08ce4bf7d2412 [file] [log] [blame]
developer327aa322023-07-10 13:49:56 +08001From: Felix Fietkau <nbd@nbd.name>
2Date: Fri, 30 Jun 2023 13:11:51 +0200
3Subject: [PATCH] mac80211: split mesh fast tx cache into
4 local/proxied/forwarded
5
6Depending on the origin of the packets (and their SA), 802.11 + mesh headers
7could be filled in differently. In order to properly deal with that, add a
8new field to the lookup key, indicating the type (local, proxied or
9forwarded). This can fix spurious packet drop issues that depend on the order
10in which nodes/hosts communicate with each other.
11
12Signed-off-by: Felix Fietkau <nbd@nbd.name>
13---
14
15--- a/net/mac80211/mesh.c
16+++ b/net/mac80211/mesh.c
developerbd9fa1e2023-10-16 11:04:00 +080017@@ -765,6 +765,9 @@ bool ieee80211_mesh_xmit_fast(struct iee
developer327aa322023-07-10 13:49:56 +080018 struct sk_buff *skb, u32 ctrl_flags)
19 {
20 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
21+ struct ieee80211_mesh_fast_tx_key key = {
22+ .type = MESH_FAST_TX_TYPE_LOCAL
23+ };
24 struct ieee80211_mesh_fast_tx *entry;
25 struct ieee80211s_hdr *meshhdr;
26 u8 sa[ETH_ALEN] __aligned(2);
developerbd9fa1e2023-10-16 11:04:00 +080027@@ -800,7 +803,10 @@ bool ieee80211_mesh_xmit_fast(struct iee
developer327aa322023-07-10 13:49:56 +080028 return false;
29 }
30
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);
36 if (!entry)
37 return false;
38
39--- a/net/mac80211/mesh.h
40+++ b/net/mac80211/mesh.h
developerbd9fa1e2023-10-16 11:04:00 +080041@@ -134,9 +134,33 @@ struct mesh_path {
developer327aa322023-07-10 13:49:56 +080042 #define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */
43
44 /**
45+ * enum ieee80211_mesh_fast_tx_type - cached mesh fast tx entry type
46+ *
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+ */
51+enum ieee80211_mesh_fast_tx_type {
52+ MESH_FAST_TX_TYPE_LOCAL,
53+ MESH_FAST_TX_TYPE_PROXIED,
54+ MESH_FAST_TX_TYPE_FORWARDED,
55+};
56+
57+/**
58+ * struct ieee80211_mesh_fast_tx_key - cached mesh fast tx entry key
59+ *
60+ * @addr: The Ethernet DA for this entry
61+ * @type: cache entry type
62+ */
63+struct ieee80211_mesh_fast_tx_key {
64+ u8 addr[ETH_ALEN] __aligned(2);
65+ enum ieee80211_mesh_fast_tx_type type;
66+};
67+
68+/**
69 * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
70 * @rhash: rhashtable pointer
71- * @addr_key: The Ethernet DA which is the key for this entry
72+ * @key: the lookup key for this cache entry
73 * @fast_tx: base fast_tx data
74 * @hdr: cached mesh and rfc1042 headers
75 * @hdrlen: length of mesh + rfc1042
developerbd9fa1e2023-10-16 11:04:00 +080076@@ -147,7 +171,7 @@ struct mesh_path {
developer327aa322023-07-10 13:49:56 +080077 */
78 struct ieee80211_mesh_fast_tx {
79 struct rhash_head rhash;
80- u8 addr_key[ETH_ALEN] __aligned(2);
81+ struct ieee80211_mesh_fast_tx_key key;
82
83 struct ieee80211_fast_tx fast_tx;
84 u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
developera46f6132024-03-26 14:09:54 +080085@@ -333,7 +357,8 @@ void mesh_path_tx_root_frame(struct ieee
developer327aa322023-07-10 13:49:56 +080086
87 bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
88 struct ieee80211_mesh_fast_tx *
89-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
90+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
91+ struct ieee80211_mesh_fast_tx_key *key);
92 bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
93 struct sk_buff *skb, u32 ctrl_flags);
94 void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
95--- a/net/mac80211/mesh_pathtbl.c
96+++ b/net/mac80211/mesh_pathtbl.c
97@@ -36,8 +36,8 @@ static const struct rhashtable_params me
98 static const struct rhashtable_params fast_tx_rht_params = {
99 .nelem_hint = 10,
100 .automatic_shrinking = true,
101- .key_len = ETH_ALEN,
102- .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
103+ .key_len = sizeof(struct ieee80211_mesh_fast_tx_key),
104+ .key_offset = offsetof(struct ieee80211_mesh_fast_tx, key),
105 .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
106 .hashfn = mesh_table_hash,
107 };
108@@ -426,20 +426,21 @@ static void mesh_fast_tx_entry_free(stru
109 }
110
111 struct ieee80211_mesh_fast_tx *
112-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
113+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
114+ struct ieee80211_mesh_fast_tx_key *key)
115 {
116 struct ieee80211_mesh_fast_tx *entry;
117 struct mesh_tx_cache *cache;
118
119 cache = &sdata->u.mesh.tx_cache;
120- entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
121+ entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
122 if (!entry)
123 return NULL;
124
125 if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
126 mpath_expired(entry->mpath)) {
127 spin_lock_bh(&cache->walk_lock);
128- entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
129+ entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
130 if (entry)
131 mesh_fast_tx_entry_free(cache, entry);
132 spin_unlock_bh(&cache->walk_lock);
133@@ -484,18 +485,24 @@ void mesh_fast_tx_cache(struct ieee80211
134 if (!sta)
135 return;
136
137+ build.key.type = MESH_FAST_TX_TYPE_LOCAL;
138 if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
139 /* This is required to keep the mppath alive */
140 mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
141 if (!mppath)
142 return;
143 build.mppath = mppath;
144+ if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr))
145+ build.key.type = MESH_FAST_TX_TYPE_PROXIED;
146 } else if (ieee80211_has_a4(hdr->frame_control)) {
147 mppath = mpath;
148 } else {
149 return;
150 }
151
152+ if (!ether_addr_equal(hdr->addr4, sdata->vif.addr))
153+ build.key.type = MESH_FAST_TX_TYPE_FORWARDED;
154+
155 /* rate limit, in case fast xmit can't be enabled */
156 if (mppath->fast_tx_check == jiffies)
157 return;
158@@ -542,7 +549,7 @@ void mesh_fast_tx_cache(struct ieee80211
159 }
160 }
161
162- memcpy(build.addr_key, mppath->dst, ETH_ALEN);
163+ memcpy(build.key.addr, mppath->dst, ETH_ALEN);
164 build.timestamp = jiffies;
165 build.fast_tx.band = info->band;
166 build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
167@@ -644,13 +651,19 @@ void mesh_fast_tx_flush_addr(struct ieee
168 const u8 *addr)
169 {
170 struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
171+ struct ieee80211_mesh_fast_tx_key key = {};
172 struct ieee80211_mesh_fast_tx *entry;
173+ int i;
174
175+ ether_addr_copy(key.addr, addr);
176 cache = &sdata->u.mesh.tx_cache;
177 spin_lock_bh(&cache->walk_lock);
developera46f6132024-03-26 14:09:54 +0800178- entry = rhashtable_lookup_fast(&cache->rht, addr, fast_tx_rht_params);
developer327aa322023-07-10 13:49:56 +0800179- if (entry)
180- mesh_fast_tx_entry_free(cache, entry);
181+ for (i = MESH_FAST_TX_TYPE_LOCAL; i < MESH_FAST_TX_TYPE_FORWARDED; i++) {
182+ key.type = i;
developera46f6132024-03-26 14:09:54 +0800183+ entry = rhashtable_lookup_fast(&cache->rht, &key, fast_tx_rht_params);
developer327aa322023-07-10 13:49:56 +0800184+ if (entry)
185+ mesh_fast_tx_entry_free(cache, entry);
186+ }
187 spin_unlock_bh(&cache->walk_lock);
188 }
189
190--- a/net/mac80211/rx.c
191+++ b/net/mac80211/rx.c
developera46f6132024-03-26 14:09:54 +0800192@@ -2726,7 +2726,10 @@ ieee80211_rx_mesh_fast_forward(struct ie
developer327aa322023-07-10 13:49:56 +0800193 struct sk_buff *skb, int hdrlen)
194 {
195 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
196- struct ieee80211_mesh_fast_tx *entry = NULL;
197+ struct ieee80211_mesh_fast_tx_key key = {
198+ .type = MESH_FAST_TX_TYPE_FORWARDED
199+ };
200+ struct ieee80211_mesh_fast_tx *entry;
201 struct ieee80211s_hdr *mesh_hdr;
202 struct tid_ampdu_tx *tid_tx;
203 struct sta_info *sta;
developera46f6132024-03-26 14:09:54 +0800204@@ -2735,9 +2738,13 @@ ieee80211_rx_mesh_fast_forward(struct ie
developer327aa322023-07-10 13:49:56 +0800205
206 mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
207 if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
208- entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
209+ ether_addr_copy(key.addr, mesh_hdr->eaddr1);
210 else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
211- entry = mesh_fast_tx_get(sdata, skb->data);
212+ ether_addr_copy(key.addr, skb->data);
213+ else
214+ return false;
215+
216+ entry = mesh_fast_tx_get(sdata, &key);
217 if (!entry)
218 return false;
219