hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/net/mac80211/mesh_plink.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 #include <linux/gfp.h>
108 #include <linux/kernel.h>
....@@ -146,6 +144,7 @@
146144
147145 /**
148146 * mesh_set_ht_prot_mode - set correct HT protection mode
147
+ * @sdata: the (mesh) interface to handle
149148 *
150149 * Section 9.23.3.5 of IEEE 80211-2012 describes the protection rules for HT
151150 * mesh STA in a MBSS. Three HT protection modes are supported for now, non-HT
....@@ -220,9 +219,12 @@
220219 bool include_plid = false;
221220 u16 peering_proto = 0;
222221 u8 *pos, ie_len = 4;
222
+ u8 ie_len_he_cap;
223223 int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.self_prot);
224224 int err = -ENOMEM;
225225
226
+ ie_len_he_cap = ieee80211_ie_len_he_cap(sdata,
227
+ NL80211_IFTYPE_MESH_POINT);
226228 skb = dev_alloc_skb(local->tx_headroom +
227229 hdr_len +
228230 2 + /* capability info */
....@@ -235,6 +237,10 @@
235237 2 + sizeof(struct ieee80211_ht_operation) +
236238 2 + sizeof(struct ieee80211_vht_cap) +
237239 2 + sizeof(struct ieee80211_vht_operation) +
240
+ ie_len_he_cap +
241
+ 2 + 1 + sizeof(struct ieee80211_he_operation) +
242
+ sizeof(struct ieee80211_he_6ghz_oper) +
243
+ 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) +
238244 2 + 8 + /* peering IE */
239245 sdata->u.mesh.ie_len);
240246 if (!skb)
....@@ -323,7 +329,10 @@
323329 if (mesh_add_ht_cap_ie(sdata, skb) ||
324330 mesh_add_ht_oper_ie(sdata, skb) ||
325331 mesh_add_vht_cap_ie(sdata, skb) ||
326
- mesh_add_vht_oper_ie(sdata, skb))
332
+ mesh_add_vht_oper_ie(sdata, skb) ||
333
+ mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
334
+ mesh_add_he_oper_ie(sdata, skb) ||
335
+ mesh_add_he_6ghz_cap_ie(sdata, skb))
327336 goto free;
328337 }
329338
....@@ -435,6 +444,11 @@
435444 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
436445 elems->vht_cap_elem, sta);
437446
447
+ ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap,
448
+ elems->he_cap_len,
449
+ elems->he_6ghz_capa,
450
+ sta);
451
+
438452 if (bw != sta->sta.bandwidth)
439453 changed |= IEEE80211_RC_BW_CHANGED;
440454
....@@ -513,7 +527,8 @@
513527
514528 static struct sta_info *
515529 mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr,
516
- struct ieee802_11_elems *elems)
530
+ struct ieee802_11_elems *elems,
531
+ struct ieee80211_rx_status *rx_status)
517532 {
518533 struct sta_info *sta = NULL;
519534
....@@ -521,11 +536,17 @@
521536 if (sdata->u.mesh.user_mpm ||
522537 sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) {
523538 if (mesh_peer_accepts_plinks(elems) &&
524
- mesh_plink_availables(sdata))
539
+ mesh_plink_availables(sdata)) {
540
+ int sig = 0;
541
+
542
+ if (ieee80211_hw_check(&sdata->local->hw, SIGNAL_DBM))
543
+ sig = rx_status->signal;
544
+
525545 cfg80211_notify_new_peer_candidate(sdata->dev, addr,
526546 elems->ie_start,
527547 elems->total_len,
528
- GFP_KERNEL);
548
+ sig, GFP_KERNEL);
549
+ }
529550 } else
530551 sta = __mesh_sta_info_alloc(sdata, addr);
531552
....@@ -538,13 +559,15 @@
538559 * @sdata: local meshif
539560 * @addr: peer's address
540561 * @elems: IEs from beacon or mesh peering frame.
562
+ * @rx_status: rx status for the frame for signal reporting
541563 *
542564 * Return existing or newly allocated sta_info under RCU read lock.
543565 * (re)initialize with given IEs.
544566 */
545567 static struct sta_info *
546568 mesh_sta_info_get(struct ieee80211_sub_if_data *sdata,
547
- u8 *addr, struct ieee802_11_elems *elems) __acquires(RCU)
569
+ u8 *addr, struct ieee802_11_elems *elems,
570
+ struct ieee80211_rx_status *rx_status) __acquires(RCU)
548571 {
549572 struct sta_info *sta = NULL;
550573
....@@ -555,7 +578,7 @@
555578 } else {
556579 rcu_read_unlock();
557580 /* can't run atomic */
558
- sta = mesh_sta_info_alloc(sdata, addr, elems);
581
+ sta = mesh_sta_info_alloc(sdata, addr, elems, rx_status);
559582 if (!sta) {
560583 rcu_read_lock();
561584 return NULL;
....@@ -576,19 +599,24 @@
576599 * @sdata: local meshif
577600 * @addr: peer's address
578601 * @elems: IEs from beacon or mesh peering frame
602
+ * @rx_status: rx status for the frame for signal reporting
579603 *
580604 * Initiates peering if appropriate.
581605 */
582606 void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
583607 u8 *hw_addr,
584
- struct ieee802_11_elems *elems)
608
+ struct ieee802_11_elems *elems,
609
+ struct ieee80211_rx_status *rx_status)
585610 {
586611 struct sta_info *sta;
587612 u32 changed = 0;
588613
589
- sta = mesh_sta_info_get(sdata, hw_addr, elems);
614
+ sta = mesh_sta_info_get(sdata, hw_addr, elems, rx_status);
590615 if (!sta)
591616 goto out;
617
+
618
+ sta->mesh->connected_to_gate = elems->mesh_config->meshconf_form &
619
+ IEEE80211_MESHCONF_FORM_CONNECTED_TO_GATE;
592620
593621 if (mesh_peer_accepts_plinks(elems) &&
594622 sta->mesh->plink_state == NL80211_PLINK_LISTEN &&
....@@ -672,7 +700,7 @@
672700 break;
673701 }
674702 reason = WLAN_REASON_MESH_MAX_RETRIES;
675
- /* fall through */
703
+ fallthrough;
676704 case NL80211_PLINK_CNF_RCVD:
677705 /* confirm timer */
678706 if (!reason)
....@@ -1069,7 +1097,8 @@
10691097 static void
10701098 mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
10711099 struct ieee80211_mgmt *mgmt,
1072
- struct ieee802_11_elems *elems)
1100
+ struct ieee802_11_elems *elems,
1101
+ struct ieee80211_rx_status *rx_status)
10731102 {
10741103
10751104 struct sta_info *sta;
....@@ -1134,7 +1163,7 @@
11341163 if (event == OPN_ACPT) {
11351164 rcu_read_unlock();
11361165 /* allocate sta entry if necessary and update info */
1137
- sta = mesh_sta_info_get(sdata, mgmt->sa, elems);
1166
+ sta = mesh_sta_info_get(sdata, mgmt->sa, elems, rx_status);
11381167 if (!sta) {
11391168 mpl_dbg(sdata, "Mesh plink: failed to init peer!\n");
11401169 goto unlock_rcu;
....@@ -1199,6 +1228,7 @@
11991228 if (baselen > len)
12001229 return;
12011230 }
1202
- ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems);
1203
- mesh_process_plink_frame(sdata, mgmt, &elems);
1231
+ ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems,
1232
+ mgmt->bssid, NULL);
1233
+ mesh_process_plink_frame(sdata, mgmt, &elems, rx_status);
12041234 }