hc
2024-10-09 05e59e5fb0064c97a1c10921ecd549f2d4a58565
kernel/net/mac80211/mesh_hwmp.c
....@@ -1,10 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2008, 2009 open80211s Ltd.
4
+ * Copyright (C) 2019 Intel Corporation
35 * Author: Luis Carlos Cobo <luisca@cozybit.com>
4
- *
5
- * This program is free software; you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License version 2 as
7
- * published by the Free Software Foundation.
86 */
97
108 #include <linux/slab.h>
....@@ -214,7 +212,7 @@
214212 skb->priority = 7;
215213
216214 info->control.vif = &sdata->vif;
217
- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
215
+ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
218216 ieee80211_set_qos_hdr(sdata, skb);
219217 ieee80211_mps_set_frame_flags(sdata, NULL, hdr);
220218 }
....@@ -300,6 +298,7 @@
300298 {
301299 struct ieee80211_tx_info *txinfo = st->info;
302300 int failed;
301
+ struct rate_info rinfo;
303302
304303 failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
305304
....@@ -310,12 +309,15 @@
310309 if (ewma_mesh_fail_avg_read(&sta->mesh->fail_avg) >
311310 LINK_FAIL_THRESH)
312311 mesh_plink_broken(sta);
312
+
313
+ sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
314
+ ewma_mesh_tx_rate_avg_add(&sta->mesh->tx_rate_avg,
315
+ cfg80211_calculate_bitrate(&rinfo));
313316 }
314317
315
-static u32 airtime_link_metric_get(struct ieee80211_local *local,
316
- struct sta_info *sta)
318
+u32 airtime_link_metric_get(struct ieee80211_local *local,
319
+ struct sta_info *sta)
317320 {
318
- struct rate_info rinfo;
319321 /* This should be adjusted for each device */
320322 int device_constant = 1 << ARITH_SHIFT;
321323 int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
....@@ -342,8 +344,7 @@
342344 if (fail_avg > LINK_FAIL_THRESH)
343345 return MAX_METRIC;
344346
345
- sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
346
- rate = cfg80211_calculate_bitrate(&rinfo);
347
+ rate = ewma_mesh_tx_rate_avg_read(&sta->mesh->tx_rate_avg);
347348 if (WARN_ON(!rate))
348349 return MAX_METRIC;
349350
....@@ -389,6 +390,7 @@
389390 unsigned long orig_lifetime, exp_time;
390391 u32 last_hop_metric, new_metric;
391392 bool process = true;
393
+ u8 hopcount;
392394
393395 rcu_read_lock();
394396 sta = sta_info_get(sdata, mgmt->sa);
....@@ -407,6 +409,7 @@
407409 orig_sn = PREQ_IE_ORIG_SN(hwmp_ie);
408410 orig_lifetime = PREQ_IE_LIFETIME(hwmp_ie);
409411 orig_metric = PREQ_IE_METRIC(hwmp_ie);
412
+ hopcount = PREQ_IE_HOPCOUNT(hwmp_ie) + 1;
410413 break;
411414 case MPATH_PREP:
412415 /* Originator here refers to the MP that was the target in the
....@@ -418,6 +421,7 @@
418421 orig_sn = PREP_IE_TARGET_SN(hwmp_ie);
419422 orig_lifetime = PREP_IE_LIFETIME(hwmp_ie);
420423 orig_metric = PREP_IE_METRIC(hwmp_ie);
424
+ hopcount = PREP_IE_HOPCOUNT(hwmp_ie) + 1;
421425 break;
422426 default:
423427 rcu_read_unlock();
....@@ -444,7 +448,10 @@
444448 (mpath->flags & MESH_PATH_SN_VALID)) {
445449 if (SN_GT(mpath->sn, orig_sn) ||
446450 (mpath->sn == orig_sn &&
447
- new_metric >= mpath->metric)) {
451
+ (rcu_access_pointer(mpath->next_hop) !=
452
+ sta ?
453
+ mult_frac(new_metric, 10, 9) :
454
+ new_metric) >= mpath->metric)) {
448455 process = false;
449456 fresh_info = false;
450457 }
....@@ -479,12 +486,15 @@
479486 }
480487
481488 if (fresh_info) {
489
+ if (rcu_access_pointer(mpath->next_hop) != sta)
490
+ mpath->path_change_count++;
482491 mesh_path_assign_nexthop(mpath, sta);
483492 mpath->flags |= MESH_PATH_SN_VALID;
484493 mpath->metric = new_metric;
485494 mpath->sn = orig_sn;
486495 mpath->exp_time = time_after(mpath->exp_time, exp_time)
487496 ? mpath->exp_time : exp_time;
497
+ mpath->hop_count = hopcount;
488498 mesh_path_activate(mpath);
489499 spin_unlock_bh(&mpath->state_lock);
490500 ewma_mesh_fail_avg_init(&sta->mesh->fail_avg);
....@@ -509,8 +519,10 @@
509519 if (mpath) {
510520 spin_lock_bh(&mpath->state_lock);
511521 if ((mpath->flags & MESH_PATH_FIXED) ||
512
- ((mpath->flags & MESH_PATH_ACTIVE) &&
513
- (last_hop_metric > mpath->metric)))
522
+ ((mpath->flags & MESH_PATH_ACTIVE) &&
523
+ ((rcu_access_pointer(mpath->next_hop) != sta ?
524
+ mult_frac(last_hop_metric, 10, 9) :
525
+ last_hop_metric) > mpath->metric)))
514526 fresh_info = false;
515527 } else {
516528 mpath = mesh_path_add(sdata, ta);
....@@ -522,10 +534,13 @@
522534 }
523535
524536 if (fresh_info) {
537
+ if (rcu_access_pointer(mpath->next_hop) != sta)
538
+ mpath->path_change_count++;
525539 mesh_path_assign_nexthop(mpath, sta);
526540 mpath->metric = last_hop_metric;
527541 mpath->exp_time = time_after(mpath->exp_time, exp_time)
528542 ? mpath->exp_time : exp_time;
543
+ mpath->hop_count = 1;
529544 mesh_path_activate(mpath);
530545 spin_unlock_bh(&mpath->state_lock);
531546 ewma_mesh_fail_avg_init(&sta->mesh->fail_avg);
....@@ -912,7 +927,7 @@
912927
913928 baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
914929 ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
915
- len - baselen, false, &elems);
930
+ len - baselen, false, &elems, mgmt->bssid, NULL);
916931
917932 if (elems.preq) {
918933 if (elems.preq_len != 37)
....@@ -1090,11 +1105,8 @@
10901105 ttl, lifetime, 0, ifmsh->preq_id++, sdata);
10911106
10921107 spin_lock_bh(&mpath->state_lock);
1093
- if (mpath->flags & MESH_PATH_DELETED) {
1094
- spin_unlock_bh(&mpath->state_lock);
1095
- goto enddiscovery;
1096
- }
1097
- mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
1108
+ if (!(mpath->flags & MESH_PATH_DELETED))
1109
+ mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
10981110 spin_unlock_bh(&mpath->state_lock);
10991111
11001112 enddiscovery:
....@@ -1122,16 +1134,17 @@
11221134 struct mesh_path *mpath;
11231135 struct sk_buff *skb_to_free = NULL;
11241136 u8 *target_addr = hdr->addr3;
1125
- int err = 0;
11261137
11271138 /* Nulls are only sent to peers for PS and should be pre-addressed */
11281139 if (ieee80211_is_qos_nullfunc(hdr->frame_control))
11291140 return 0;
11301141
1131
- rcu_read_lock();
1132
- err = mesh_nexthop_lookup(sdata, skb);
1133
- if (!err)
1134
- goto endlookup;
1142
+ /* Allow injected packets to bypass mesh routing */
1143
+ if (info->control.flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP)
1144
+ return 0;
1145
+
1146
+ if (!mesh_nexthop_lookup(sdata, skb))
1147
+ return 0;
11351148
11361149 /* no nexthop found, start resolving */
11371150 mpath = mesh_path_lookup(sdata, target_addr);
....@@ -1139,8 +1152,7 @@
11391152 mpath = mesh_path_add(sdata, target_addr);
11401153 if (IS_ERR(mpath)) {
11411154 mesh_path_discard_frame(sdata, skb);
1142
- err = PTR_ERR(mpath);
1143
- goto endlookup;
1155
+ return PTR_ERR(mpath);
11441156 }
11451157 }
11461158
....@@ -1151,16 +1163,47 @@
11511163 if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN)
11521164 skb_to_free = skb_dequeue(&mpath->frame_queue);
11531165
1154
- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
1166
+ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
11551167 ieee80211_set_qos_hdr(sdata, skb);
11561168 skb_queue_tail(&mpath->frame_queue, skb);
1157
- err = -ENOENT;
11581169 if (skb_to_free)
11591170 mesh_path_discard_frame(sdata, skb_to_free);
11601171
1161
-endlookup:
1172
+ return -ENOENT;
1173
+}
1174
+
1175
+/**
1176
+ * mesh_nexthop_lookup_nolearn - try to set next hop without path discovery
1177
+ * @skb: 802.11 frame to be sent
1178
+ * @sdata: network subif the frame will be sent through
1179
+ *
1180
+ * Check if the meshDA (addr3) of a unicast frame is a direct neighbor.
1181
+ * And if so, set the RA (addr1) to it to transmit to this node directly,
1182
+ * avoiding PREQ/PREP path discovery.
1183
+ *
1184
+ * Returns: 0 if the next hop was found and -ENOENT otherwise.
1185
+ */
1186
+static int mesh_nexthop_lookup_nolearn(struct ieee80211_sub_if_data *sdata,
1187
+ struct sk_buff *skb)
1188
+{
1189
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1190
+ struct sta_info *sta;
1191
+
1192
+ if (is_multicast_ether_addr(hdr->addr1))
1193
+ return -ENOENT;
1194
+
1195
+ rcu_read_lock();
1196
+ sta = sta_info_get(sdata, hdr->addr3);
1197
+
1198
+ if (!sta || sta->mesh->plink_state != NL80211_PLINK_ESTAB) {
1199
+ rcu_read_unlock();
1200
+ return -ENOENT;
1201
+ }
11621202 rcu_read_unlock();
1163
- return err;
1203
+
1204
+ memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
1205
+ memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
1206
+ return 0;
11641207 }
11651208
11661209 /**
....@@ -1176,17 +1219,19 @@
11761219 int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata,
11771220 struct sk_buff *skb)
11781221 {
1222
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
11791223 struct mesh_path *mpath;
11801224 struct sta_info *next_hop;
11811225 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
11821226 u8 *target_addr = hdr->addr3;
1183
- int err = -ENOENT;
11841227
1185
- rcu_read_lock();
1228
+ if (ifmsh->mshcfg.dot11MeshNolearn &&
1229
+ !mesh_nexthop_lookup_nolearn(sdata, skb))
1230
+ return 0;
1231
+
11861232 mpath = mesh_path_lookup(sdata, target_addr);
1187
-
11881233 if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE))
1189
- goto endlookup;
1234
+ return -ENOENT;
11901235
11911236 if (time_after(jiffies,
11921237 mpath->exp_time -
....@@ -1201,12 +1246,10 @@
12011246 memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
12021247 memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
12031248 ieee80211_mps_set_frame_flags(sdata, next_hop, hdr);
1204
- err = 0;
1249
+ return 0;
12051250 }
12061251
1207
-endlookup:
1208
- rcu_read_unlock();
1209
- return err;
1252
+ return -ENOENT;
12101253 }
12111254
12121255 void mesh_path_timer(struct timer_list *t)
....@@ -1262,7 +1305,7 @@
12621305 break;
12631306 case IEEE80211_PROACTIVE_PREQ_WITH_PREP:
12641307 flags |= IEEE80211_PREQ_PROACTIVE_PREP_FLAG;
1265
- /* fall through */
1308
+ fallthrough;
12661309 case IEEE80211_PROACTIVE_PREQ_NO_PREP:
12671310 interval = ifmsh->mshcfg.dot11MeshHWMPactivePathToRootTimeout;
12681311 target_flags |= IEEE80211_PREQ_TO_FLAG |