hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/mac80211/mesh.c
....@@ -1,11 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2008, 2009 open80211s Ltd.
4
+ * Copyright (C) 2018 - 2020 Intel Corporation
35 * Authors: Luis Carlos Cobo <luisca@cozybit.com>
46 * Javier Cardona <javier@cozybit.com>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
97 */
108
119 #include <linux/slab.h>
....@@ -65,6 +63,7 @@
6563 u32 basic_rates = 0;
6664 struct cfg80211_chan_def sta_chan_def;
6765 struct ieee80211_supported_band *sband;
66
+ u32 vht_cap_info = 0;
6867
6968 /*
7069 * As support for each feature is added, check for matching
....@@ -98,7 +97,14 @@
9897 cfg80211_chandef_create(&sta_chan_def, sdata->vif.bss_conf.chandef.chan,
9998 NL80211_CHAN_NO_HT);
10099 ieee80211_chandef_ht_oper(ie->ht_operation, &sta_chan_def);
101
- ieee80211_chandef_vht_oper(ie->vht_operation, &sta_chan_def);
100
+
101
+ if (ie->vht_cap_elem)
102
+ vht_cap_info = le32_to_cpu(ie->vht_cap_elem->vht_cap_info);
103
+
104
+ ieee80211_chandef_vht_oper(&sdata->local->hw, vht_cap_info,
105
+ ie->vht_operation, ie->ht_operation,
106
+ &sta_chan_def);
107
+ ieee80211_chandef_he_6ghz_oper(sdata, ie->he_operation, &sta_chan_def);
102108
103109 if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
104110 &sta_chan_def))
....@@ -251,6 +257,10 @@
251257 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
252258 u8 *pos, neighbors;
253259 u8 meshconf_len = sizeof(struct ieee80211_meshconf_ie);
260
+ bool is_connected_to_gate = ifmsh->num_gates > 0 ||
261
+ ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol ||
262
+ ifmsh->mshcfg.dot11MeshConnectedToMeshGate;
263
+ bool is_connected_to_as = ifmsh->mshcfg.dot11MeshConnectedToAuthServer;
254264
255265 if (skb_tailroom(skb) < 2 + meshconf_len)
256266 return -ENOMEM;
....@@ -275,7 +285,9 @@
275285 /* Mesh Formation Info - number of neighbors */
276286 neighbors = atomic_read(&ifmsh->estab_plinks);
277287 neighbors = min_t(int, neighbors, IEEE80211_MAX_MESH_PEERINGS);
278
- *pos++ = neighbors << 1;
288
+ *pos++ = (is_connected_to_as << 7) |
289
+ (neighbors << 1) |
290
+ is_connected_to_gate;
279291 /* Mesh capability */
280292 *pos = 0x00;
281293 *pos |= ifmsh->mshcfg.dot11MeshForwarding ?
....@@ -412,6 +424,10 @@
412424 if (!sband)
413425 return -EINVAL;
414426
427
+ /* HT not allowed in 6 GHz */
428
+ if (sband->band == NL80211_BAND_6GHZ)
429
+ return 0;
430
+
415431 if (!sband->ht_cap.ht_supported ||
416432 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
417433 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
....@@ -449,6 +465,10 @@
449465 sband = local->hw.wiphy->bands[channel->band];
450466 ht_cap = &sband->ht_cap;
451467
468
+ /* HT not allowed in 6 GHz */
469
+ if (sband->band == NL80211_BAND_6GHZ)
470
+ return 0;
471
+
452472 if (!ht_cap->ht_supported ||
453473 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
454474 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
....@@ -475,6 +495,10 @@
475495 sband = ieee80211_get_sband(sdata);
476496 if (!sband)
477497 return -EINVAL;
498
+
499
+ /* VHT not allowed in 6 GHz */
500
+ if (sband->band == NL80211_BAND_6GHZ)
501
+ return 0;
478502
479503 if (!sband->vht_cap.vht_supported ||
480504 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
....@@ -513,6 +537,10 @@
513537 sband = local->hw.wiphy->bands[channel->band];
514538 vht_cap = &sband->vht_cap;
515539
540
+ /* VHT not allowed in 6 GHz */
541
+ if (sband->band == NL80211_BAND_6GHZ)
542
+ return 0;
543
+
516544 if (!vht_cap->vht_supported ||
517545 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
518546 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
....@@ -526,6 +554,86 @@
526554 ieee80211_ie_build_vht_oper(pos, vht_cap,
527555 &sdata->vif.bss_conf.chandef);
528556
557
+ return 0;
558
+}
559
+
560
+int mesh_add_he_cap_ie(struct ieee80211_sub_if_data *sdata,
561
+ struct sk_buff *skb, u8 ie_len)
562
+{
563
+ const struct ieee80211_sta_he_cap *he_cap;
564
+ struct ieee80211_supported_band *sband;
565
+ u8 *pos;
566
+
567
+ sband = ieee80211_get_sband(sdata);
568
+ if (!sband)
569
+ return -EINVAL;
570
+
571
+ he_cap = ieee80211_get_he_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT);
572
+
573
+ if (!he_cap ||
574
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
575
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
576
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
577
+ return 0;
578
+
579
+ if (skb_tailroom(skb) < ie_len)
580
+ return -ENOMEM;
581
+
582
+ pos = skb_put(skb, ie_len);
583
+ ieee80211_ie_build_he_cap(pos, he_cap, pos + ie_len);
584
+
585
+ return 0;
586
+}
587
+
588
+int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata,
589
+ struct sk_buff *skb)
590
+{
591
+ const struct ieee80211_sta_he_cap *he_cap;
592
+ struct ieee80211_supported_band *sband;
593
+ u32 len;
594
+ u8 *pos;
595
+
596
+ sband = ieee80211_get_sband(sdata);
597
+ if (!sband)
598
+ return -EINVAL;
599
+
600
+ he_cap = ieee80211_get_he_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT);
601
+ if (!he_cap ||
602
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
603
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
604
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
605
+ return 0;
606
+
607
+ len = 2 + 1 + sizeof(struct ieee80211_he_operation);
608
+ if (sdata->vif.bss_conf.chandef.chan->band == NL80211_BAND_6GHZ)
609
+ len += sizeof(struct ieee80211_he_6ghz_oper);
610
+
611
+ if (skb_tailroom(skb) < len)
612
+ return -ENOMEM;
613
+
614
+ pos = skb_put(skb, len);
615
+ ieee80211_ie_build_he_oper(pos, &sdata->vif.bss_conf.chandef);
616
+
617
+ return 0;
618
+}
619
+
620
+int mesh_add_he_6ghz_cap_ie(struct ieee80211_sub_if_data *sdata,
621
+ struct sk_buff *skb)
622
+{
623
+ struct ieee80211_supported_band *sband;
624
+ const struct ieee80211_sband_iftype_data *iftd;
625
+
626
+ sband = ieee80211_get_sband(sdata);
627
+ if (!sband)
628
+ return -EINVAL;
629
+
630
+ iftd = ieee80211_get_sband_iftype_data(sband,
631
+ NL80211_IFTYPE_MESH_POINT);
632
+ /* The device doesn't support HE in mesh mode or at all */
633
+ if (!iftd)
634
+ return 0;
635
+
636
+ ieee80211_ie_build_he_6ghz_cap(sdata, skb);
529637 return 0;
530638 }
531639
....@@ -564,7 +672,7 @@
564672 * @hdr: 802.11 frame header
565673 * @fc: frame control field
566674 * @meshda: destination address in the mesh
567
- * @meshsa: source address address in the mesh. Same as TA, as frame is
675
+ * @meshsa: source address in the mesh. Same as TA, as frame is
568676 * locally originated.
569677 *
570678 * Return the length of the 802.11 (does not include a mesh control header)
....@@ -674,6 +782,7 @@
674782 struct ieee80211_chanctx_conf *chanctx_conf;
675783 struct mesh_csa_settings *csa;
676784 enum nl80211_band band;
785
+ u8 ie_len_he_cap;
677786 u8 *pos;
678787 struct ieee80211_sub_if_data *sdata;
679788 int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon);
....@@ -684,6 +793,8 @@
684793 band = chanctx_conf->def.chan->band;
685794 rcu_read_unlock();
686795
796
+ ie_len_he_cap = ieee80211_ie_len_he_cap(sdata,
797
+ NL80211_IFTYPE_MESH_POINT);
687798 head_len = hdr_len +
688799 2 + /* NULL SSID */
689800 /* Channel Switch Announcement */
....@@ -703,6 +814,10 @@
703814 2 + sizeof(__le16) + /* awake window */
704815 2 + sizeof(struct ieee80211_vht_cap) +
705816 2 + sizeof(struct ieee80211_vht_operation) +
817
+ ie_len_he_cap +
818
+ 2 + 1 + sizeof(struct ieee80211_he_operation) +
819
+ sizeof(struct ieee80211_he_6ghz_oper) +
820
+ 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) +
706821 ifmsh->ie_len;
707822
708823 bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL);
....@@ -749,8 +864,8 @@
749864 *pos++ = 0x0;
750865 *pos++ = ieee80211_frequency_to_channel(
751866 csa->settings.chandef.chan->center_freq);
752
- bcn->csa_current_counter = csa->settings.count;
753
- bcn->csa_counter_offsets[0] = hdr_len + 6;
867
+ bcn->cntdwn_current_counter = csa->settings.count;
868
+ bcn->cntdwn_counter_offsets[0] = hdr_len + 6;
754869 *pos++ = csa->settings.count;
755870 *pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
756871 *pos++ = 6;
....@@ -820,6 +935,9 @@
820935 mesh_add_awake_window_ie(sdata, skb) ||
821936 mesh_add_vht_cap_ie(sdata, skb) ||
822937 mesh_add_vht_oper_ie(sdata, skb) ||
938
+ mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
939
+ mesh_add_he_oper_ie(sdata, skb) ||
940
+ mesh_add_he_6ghz_cap_ie(sdata, skb) ||
823941 mesh_add_vendor_ies(sdata, skb))
824942 goto out_free;
825943
....@@ -929,6 +1047,7 @@
9291047 /* stop the beacon */
9301048 ifmsh->mesh_id_len = 0;
9311049 sdata->vif.bss_conf.enable_beacon = false;
1050
+ sdata->beacon_rate_set = false;
9321051 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
9331052 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
9341053
....@@ -979,7 +1098,7 @@
9791098 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
9801099 struct ieee80211_supported_band *sband;
9811100 int err;
982
- u32 sta_flags;
1101
+ u32 sta_flags, vht_cap_info = 0;
9831102
9841103 sdata_assert_lock(sdata);
9851104
....@@ -991,10 +1110,10 @@
9911110 switch (sdata->vif.bss_conf.chandef.width) {
9921111 case NL80211_CHAN_WIDTH_20_NOHT:
9931112 sta_flags |= IEEE80211_STA_DISABLE_HT;
994
- /* fall through */
1113
+ fallthrough;
9951114 case NL80211_CHAN_WIDTH_20:
9961115 sta_flags |= IEEE80211_STA_DISABLE_40MHZ;
997
- /* fall through */
1116
+ fallthrough;
9981117 case NL80211_CHAN_WIDTH_40:
9991118 sta_flags |= IEEE80211_STA_DISABLE_VHT;
10001119 break;
....@@ -1002,8 +1121,13 @@
10021121 break;
10031122 }
10041123
1124
+ if (elems->vht_cap_elem)
1125
+ vht_cap_info =
1126
+ le32_to_cpu(elems->vht_cap_elem->vht_cap_info);
1127
+
10051128 memset(&params, 0, sizeof(params));
10061129 err = ieee80211_parse_ch_switch_ie(sdata, elems, sband->band,
1130
+ vht_cap_info,
10071131 sta_flags, sdata->vif.addr,
10081132 &csa_ie);
10091133 if (err < 0)
....@@ -1101,7 +1225,8 @@
11011225 if (baselen > len)
11021226 return;
11031227
1104
- ieee802_11_parse_elems(pos, len - baselen, false, &elems);
1228
+ ieee802_11_parse_elems(pos, len - baselen, false, &elems, mgmt->bssid,
1229
+ NULL);
11051230
11061231 if (!elems.mesh_id)
11071232 return;
....@@ -1165,7 +1290,7 @@
11651290 return;
11661291
11671292 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
1168
- false, &elems);
1293
+ false, &elems, mgmt->bssid, NULL);
11691294
11701295 /* ignore non-mesh or secure / unsecure mismatch */
11711296 if ((!elems.mesh_id || !elems.mesh_config) ||
....@@ -1189,16 +1314,17 @@
11891314 if (!sdata->u.mesh.user_mpm ||
11901315 sdata->u.mesh.mshcfg.rssi_threshold == 0 ||
11911316 sdata->u.mesh.mshcfg.rssi_threshold < rx_status->signal)
1192
- mesh_neighbour_update(sdata, mgmt->sa, &elems);
1317
+ mesh_neighbour_update(sdata, mgmt->sa, &elems,
1318
+ rx_status);
1319
+
1320
+ if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT &&
1321
+ !sdata->vif.csa_active)
1322
+ ieee80211_mesh_process_chnswitch(sdata, &elems, true);
11931323 }
11941324
11951325 if (ifmsh->sync_ops)
11961326 ifmsh->sync_ops->rx_bcn_presp(sdata,
11971327 stype, mgmt, &elems, rx_status);
1198
-
1199
- if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT &&
1200
- !sdata->vif.csa_active)
1201
- ieee80211_mesh_process_chnswitch(sdata, &elems, true);
12021328 }
12031329
12041330 int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
....@@ -1303,7 +1429,11 @@
13031429 pos = mgmt->u.action.u.chan_switch.variable;
13041430 baselen = offsetof(struct ieee80211_mgmt,
13051431 u.action.u.chan_switch.variable);
1306
- ieee802_11_parse_elems(pos, len - baselen, true, &elems);
1432
+ ieee802_11_parse_elems(pos, len - baselen, true, &elems,
1433
+ mgmt->bssid, NULL);
1434
+
1435
+ if (!mesh_matches_local(sdata, &elems))
1436
+ return;
13071437
13081438 ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
13091439 if (!--ifmsh->chsw_ttl)