^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2008, 2009 open80211s Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2018 - 2020 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Authors: Luis Carlos Cobo <luisca@cozybit.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Javier Cardona <javier@cozybit.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "ieee80211_i.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "mesh.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "driver-ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) static int mesh_allocated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static struct kmem_cache *rm_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) return (mgmt->u.action.u.mesh_action.action_code ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) WLAN_MESH_ACTION_HWMP_PATH_SELECTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) void ieee80211s_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) mesh_allocated = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) void ieee80211s_stop(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (!mesh_allocated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) kmem_cache_destroy(rm_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static void ieee80211_mesh_housekeeping_timer(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct ieee80211_sub_if_data *sdata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) from_timer(sdata, t, u.mesh.housekeeping_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ieee80211_queue_work(&local->hw, &sdata->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * mesh_matches_local - check if the config of a mesh point matches ours
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * @sdata: local mesh subif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * @ie: information elements of a management frame from the mesh peer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * This function checks if the mesh configuration of a mesh point matches the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * local mesh configuration, i.e. if both nodes belong to the same mesh network.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct ieee802_11_elems *ie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u32 basic_rates = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct cfg80211_chan_def sta_chan_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u32 vht_cap_info = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * As support for each feature is added, check for matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * - On mesh config capabilities
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * - Power Save Support En
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * - Sync support enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * - Sync support active
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * - Sync support required from peer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * - MDA enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * - Power management control on fc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!(ifmsh->mesh_id_len == ie->mesh_id_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) (ifmsh->mesh_pm_id == ie->mesh_config->meshconf_pmetric) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) ieee80211_sta_get_rates(sdata, ie, sband->band,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) &basic_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (sdata->vif.bss_conf.basic_rates != basic_rates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) cfg80211_chandef_create(&sta_chan_def, sdata->vif.bss_conf.chandef.chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) NL80211_CHAN_NO_HT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ieee80211_chandef_ht_oper(ie->ht_operation, &sta_chan_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (ie->vht_cap_elem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) vht_cap_info = le32_to_cpu(ie->vht_cap_elem->vht_cap_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ieee80211_chandef_vht_oper(&sdata->local->hw, vht_cap_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ie->vht_operation, ie->ht_operation,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) &sta_chan_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ieee80211_chandef_he_6ghz_oper(sdata, ie->he_operation, &sta_chan_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) &sta_chan_def))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * @ie: information elements of a management frame from the mesh peer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return (ie->mesh_config->meshconf_cap &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * mesh_accept_plinks_update - update accepting_plink in local mesh beacons
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * @sdata: mesh interface in which mesh beacons are going to be updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * Returns: beacon changed flag if the beacon content changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) bool free_plinks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) u32 changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * the mesh interface might be able to establish plinks with peers that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * are already on the table but are not on PLINK_ESTAB state. However,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * in general the mesh interface is not accepting peer link requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * from new peers, and that must be reflected in the beacon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) free_plinks = mesh_plink_availables(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (free_plinks != sdata->u.mesh.accepting_plinks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) sdata->u.mesh.accepting_plinks = free_plinks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) changed = BSS_CHANGED_BEACON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * mesh_sta_cleanup - clean up any mesh sta state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * @sta: mesh sta to clean up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) void mesh_sta_cleanup(struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) u32 changed = mesh_plink_deactivate(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ieee80211_mbss_info_change_notify(sdata, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (!sdata->u.mesh.rmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) for (i = 0; i < RMC_BUCKETS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) INIT_HLIST_HEAD(&sdata->u.mesh.rmc->bucket[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct mesh_rmc *rmc = sdata->u.mesh.rmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct rmc_entry *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct hlist_node *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (!sdata->u.mesh.rmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) for (i = 0; i < RMC_BUCKETS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) hlist_for_each_entry_safe(p, n, &rmc->bucket[i], list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) hlist_del(&p->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) kmem_cache_free(rm_cache, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) kfree(rmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) sdata->u.mesh.rmc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * mesh_rmc_check - Check frame in recent multicast cache and add if absent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * @sdata: interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * @sa: source address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * @mesh_hdr: mesh_header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * Returns: 0 if the frame is not in the cache, nonzero otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * Checks using the source address and the mesh sequence number if we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * received this frame lately. If the frame is not in the cache, it is added to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) int mesh_rmc_check(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) const u8 *sa, struct ieee80211s_hdr *mesh_hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct mesh_rmc *rmc = sdata->u.mesh.rmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) u32 seqnum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int entries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) u8 idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct rmc_entry *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct hlist_node *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (!rmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* Don't care about endianness since only match matters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) hlist_for_each_entry_safe(p, n, &rmc->bucket[idx], list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ++entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (time_after(jiffies, p->exp_time) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) entries == RMC_QUEUE_MAX_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) hlist_del(&p->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) kmem_cache_free(rm_cache, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) --entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) } else if ((seqnum == p->seqnum) && ether_addr_equal(sa, p->sa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) p = kmem_cache_alloc(rm_cache, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) p->seqnum = seqnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) p->exp_time = jiffies + RMC_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) memcpy(p->sa, sa, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) hlist_add_head(&p->list, &rmc->bucket[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) u8 *pos, neighbors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) u8 meshconf_len = sizeof(struct ieee80211_meshconf_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) bool is_connected_to_gate = ifmsh->num_gates > 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ifmsh->mshcfg.dot11MeshConnectedToMeshGate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) bool is_connected_to_as = ifmsh->mshcfg.dot11MeshConnectedToAuthServer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (skb_tailroom(skb) < 2 + meshconf_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) pos = skb_put(skb, 2 + meshconf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) *pos++ = WLAN_EID_MESH_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) *pos++ = meshconf_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* save a pointer for quick updates in pre-tbtt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ifmsh->meshconf_offset = pos - skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* Active path selection protocol ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) *pos++ = ifmsh->mesh_pp_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* Active path selection metric ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) *pos++ = ifmsh->mesh_pm_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* Congestion control mode identifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) *pos++ = ifmsh->mesh_cc_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* Synchronization protocol identifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) *pos++ = ifmsh->mesh_sp_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* Authentication Protocol identifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) *pos++ = ifmsh->mesh_auth_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* Mesh Formation Info - number of neighbors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) neighbors = atomic_read(&ifmsh->estab_plinks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) neighbors = min_t(int, neighbors, IEEE80211_MAX_MESH_PEERINGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) *pos++ = (is_connected_to_as << 7) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) (neighbors << 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) is_connected_to_gate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Mesh capability */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) *pos = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) *pos |= ifmsh->mshcfg.dot11MeshForwarding ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) IEEE80211_MESHCONF_CAPAB_FORWARDING : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) *pos |= ifmsh->accepting_plinks ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) *pos |= ifmsh->ps_peers_deep_sleep ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (skb_tailroom(skb) < 2 + ifmsh->mesh_id_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) pos = skb_put(skb, 2 + ifmsh->mesh_id_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) *pos++ = WLAN_EID_MESH_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) *pos++ = ifmsh->mesh_id_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (ifmsh->mesh_id_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) memcpy(pos, ifmsh->mesh_id, ifmsh->mesh_id_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int mesh_add_awake_window_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* see IEEE802.11-2012 13.14.6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (ifmsh->ps_peers_light_sleep == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ifmsh->ps_peers_deep_sleep == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ifmsh->nonpeer_pm == NL80211_MESH_POWER_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (skb_tailroom(skb) < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) pos = skb_put(skb, 2 + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) *pos++ = WLAN_EID_MESH_AWAKE_WINDOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) *pos++ = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) put_unaligned_le16(ifmsh->mshcfg.dot11MeshAwakeWindowDuration, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) u8 offset, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) const u8 *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (!ifmsh->ie || !ifmsh->ie_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* fast-forward to vendor IEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) offset = ieee80211_ie_split_vendor(ifmsh->ie, ifmsh->ie_len, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (offset < ifmsh->ie_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) len = ifmsh->ie_len - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) data = ifmsh->ie + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (skb_tailroom(skb) < len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) skb_put_data(skb, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) int mesh_add_rsn_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) u8 len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) const u8 *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (!ifmsh->ie || !ifmsh->ie_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) /* find RSN IE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) data = cfg80211_find_ie(WLAN_EID_RSN, ifmsh->ie, ifmsh->ie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) len = data[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (skb_tailroom(skb) < len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) skb_put_data(skb, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static int mesh_add_ds_params_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct ieee80211_chanctx_conf *chanctx_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (skb_tailroom(skb) < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (WARN_ON(!chanctx_conf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) chan = chanctx_conf->def.chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) pos = skb_put(skb, 2 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) *pos++ = WLAN_EID_DS_PARAMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) *pos++ = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) *pos++ = ieee80211_frequency_to_channel(chan->center_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* HT not allowed in 6 GHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (sband->band == NL80211_BAND_6GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (!sband->ht_cap.ht_supported ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, sband->ht_cap.cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct ieee80211_chanctx_conf *chanctx_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) struct ieee80211_channel *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct ieee80211_sta_ht_cap *ht_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (WARN_ON(!chanctx_conf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) channel = chanctx_conf->def.chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) sband = local->hw.wiphy->bands[channel->band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) ht_cap = &sband->ht_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* HT not allowed in 6 GHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (sband->band == NL80211_BAND_6GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (!ht_cap->ht_supported ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_operation))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) ieee80211_ie_build_ht_oper(pos, ht_cap, &sdata->vif.bss_conf.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) sdata->vif.bss_conf.ht_operation_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int mesh_add_vht_cap_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) /* VHT not allowed in 6 GHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (sband->band == NL80211_BAND_6GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (!sband->vht_cap.vht_supported ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_vht_cap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, sband->vht_cap.cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) int mesh_add_vht_oper_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct ieee80211_chanctx_conf *chanctx_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) struct ieee80211_channel *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) struct ieee80211_sta_vht_cap *vht_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (WARN_ON(!chanctx_conf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) channel = chanctx_conf->def.chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) sband = local->hw.wiphy->bands[channel->band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) vht_cap = &sband->vht_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* VHT not allowed in 6 GHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (sband->band == NL80211_BAND_6GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (!vht_cap->vht_supported ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_vht_operation))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_operation));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) ieee80211_ie_build_vht_oper(pos, vht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) &sdata->vif.bss_conf.chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) int mesh_add_he_cap_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct sk_buff *skb, u8 ie_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) const struct ieee80211_sta_he_cap *he_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) he_cap = ieee80211_get_he_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (!he_cap ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (skb_tailroom(skb) < ie_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) pos = skb_put(skb, ie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) ieee80211_ie_build_he_cap(pos, he_cap, pos + ie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) const struct ieee80211_sta_he_cap *he_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) he_cap = ieee80211_get_he_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (!he_cap ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) len = 2 + 1 + sizeof(struct ieee80211_he_operation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (sdata->vif.bss_conf.chandef.chan->band == NL80211_BAND_6GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) len += sizeof(struct ieee80211_he_6ghz_oper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (skb_tailroom(skb) < len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) pos = skb_put(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) ieee80211_ie_build_he_oper(pos, &sdata->vif.bss_conf.chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) int mesh_add_he_6ghz_cap_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) const struct ieee80211_sband_iftype_data *iftd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) iftd = ieee80211_get_sband_iftype_data(sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) NL80211_IFTYPE_MESH_POINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /* The device doesn't support HE in mesh mode or at all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (!iftd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) ieee80211_ie_build_he_6ghz_cap(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static void ieee80211_mesh_path_timer(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct ieee80211_sub_if_data *sdata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) from_timer(sdata, t, u.mesh.mesh_path_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) ieee80211_queue_work(&sdata->local->hw, &sdata->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static void ieee80211_mesh_path_root_timer(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct ieee80211_sub_if_data *sdata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) from_timer(sdata, t, u.mesh.mesh_path_root_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) ieee80211_queue_work(&sdata->local->hw, &sdata->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (ifmsh->mshcfg.dot11MeshHWMPRootMode > IEEE80211_ROOTMODE_ROOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /* stop running timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) del_timer_sync(&ifmsh->mesh_path_root_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * @hdr: 802.11 frame header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * @fc: frame control field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * @meshda: destination address in the mesh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * @meshsa: source address in the mesh. Same as TA, as frame is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * locally originated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * Return the length of the 802.11 (does not include a mesh control header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) const u8 *meshda, const u8 *meshsa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (is_multicast_ether_addr(meshda)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /* DA TA SA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) memcpy(hdr->addr1, meshda, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) memcpy(hdr->addr2, meshsa, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) memcpy(hdr->addr3, meshsa, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* RA TA DA SA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) eth_zero_addr(hdr->addr1); /* RA is resolved later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) memcpy(hdr->addr2, meshsa, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) memcpy(hdr->addr3, meshda, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) memcpy(hdr->addr4, meshsa, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * ieee80211_new_mesh_header - create a new mesh header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * @sdata: mesh interface to be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) * @meshhdr: uninitialized mesh header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * @addr4or5: 1st address in the ae header, which may correspond to address 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * (if addr6 is NULL) or address 5 (if addr6 is present). It may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * be NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * @addr6: 2nd address in the ae header, which corresponds to addr6 of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) * mesh frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * Return the header length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) unsigned int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct ieee80211s_hdr *meshhdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) const char *addr4or5, const char *addr6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (WARN_ON(!addr4or5 && addr6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) memset(meshhdr, 0, sizeof(*meshhdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /* FIXME: racy -- TX on multiple queues can be concurrent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) sdata->u.mesh.mesh_seqnum++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (addr4or5 && !addr6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) meshhdr->flags |= MESH_FLAGS_AE_A4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return 2 * ETH_ALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) } else if (addr4or5 && addr6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) meshhdr->flags |= MESH_FLAGS_AE_A5_A6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) memcpy(meshhdr->eaddr2, addr6, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return 3 * ETH_ALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return ETH_ALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) u32 changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (ifmsh->mshcfg.plink_timeout > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) ieee80211_sta_expire(sdata, ifmsh->mshcfg.plink_timeout * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) mesh_path_expire(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) changed = mesh_accept_plinks_update(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) ieee80211_mbss_info_change_notify(sdata, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) mod_timer(&ifmsh->housekeeping_timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) round_jiffies(jiffies +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) u32 interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) mesh_path_tx_root_frame(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (ifmsh->mshcfg.dot11MeshHWMPRootMode == IEEE80211_PROACTIVE_RANN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) interval = ifmsh->mshcfg.dot11MeshHWMProotInterval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) mod_timer(&ifmsh->mesh_path_root_timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) round_jiffies(TU_TO_EXP_TIME(interval)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) struct beacon_data *bcn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) int head_len, tail_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) struct ieee80211_mgmt *mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct ieee80211_chanctx_conf *chanctx_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct mesh_csa_settings *csa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) u8 ie_len_he_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct ieee80211_sub_if_data *sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) band = chanctx_conf->def.chan->band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) ie_len_he_cap = ieee80211_ie_len_he_cap(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) NL80211_IFTYPE_MESH_POINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) head_len = hdr_len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 2 + /* NULL SSID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) /* Channel Switch Announcement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 2 + sizeof(struct ieee80211_channel_sw_ie) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /* Mesh Channel Switch Parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 2 + sizeof(struct ieee80211_mesh_chansw_params_ie) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) /* Channel Switch Wrapper + Wide Bandwidth CSA IE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 2 + 2 + sizeof(struct ieee80211_wide_bw_chansw_ie) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 2 + sizeof(struct ieee80211_sec_chan_offs_ie) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 2 + 8 + /* supported rates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 2 + 3; /* DS params */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) tail_len = 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 2 + sizeof(struct ieee80211_ht_cap) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 2 + sizeof(struct ieee80211_ht_operation) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 2 + ifmsh->mesh_id_len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 2 + sizeof(struct ieee80211_meshconf_ie) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 2 + sizeof(__le16) + /* awake window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 2 + sizeof(struct ieee80211_vht_cap) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 2 + sizeof(struct ieee80211_vht_operation) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) ie_len_he_cap +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 2 + 1 + sizeof(struct ieee80211_he_operation) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) sizeof(struct ieee80211_he_6ghz_oper) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) ifmsh->ie_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) /* need an skb for IE builders to operate on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) skb = dev_alloc_skb(max(head_len, tail_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (!bcn || !skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * pointers go into the block we allocated,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * memory is | beacon_data | head | tail |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) bcn->head = ((u8 *) bcn) + sizeof(*bcn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) /* fill in the head */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) mgmt = skb_put_zero(skb, hdr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) IEEE80211_STYPE_BEACON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) eth_broadcast_addr(mgmt->da);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ieee80211_mps_set_frame_flags(sdata, NULL, (void *) mgmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) mgmt->u.beacon.beacon_int =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) cpu_to_le16(sdata->vif.bss_conf.beacon_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) mgmt->u.beacon.capab_info |= cpu_to_le16(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) sdata->u.mesh.security ? WLAN_CAPABILITY_PRIVACY : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) pos = skb_put(skb, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) *pos++ = WLAN_EID_SSID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) *pos++ = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) csa = rcu_dereference(ifmsh->csa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (csa) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) enum nl80211_channel_type ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) struct cfg80211_chan_def *chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) int ie_len = 2 + sizeof(struct ieee80211_channel_sw_ie) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 2 + sizeof(struct ieee80211_mesh_chansw_params_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) pos = skb_put_zero(skb, ie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) *pos++ = WLAN_EID_CHANNEL_SWITCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) *pos++ = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) *pos++ = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) *pos++ = ieee80211_frequency_to_channel(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) csa->settings.chandef.chan->center_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) bcn->cntdwn_current_counter = csa->settings.count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) bcn->cntdwn_counter_offsets[0] = hdr_len + 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) *pos++ = csa->settings.count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) *pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) *pos++ = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) *pos++ = ifmsh->mshcfg.dot11MeshTTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) *pos++ = ifmsh->chsw_ttl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) *pos++ |= csa->settings.block_tx ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) pos += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) put_unaligned_le16(ifmsh->pre_value, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) pos += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) switch (csa->settings.chandef.width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) case NL80211_CHAN_WIDTH_40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) ie_len = 2 + sizeof(struct ieee80211_sec_chan_offs_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) pos = skb_put_zero(skb, ie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) *pos++ = 1; /* len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ct = cfg80211_get_chandef_type(&csa->settings.chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (ct == NL80211_CHAN_HT40PLUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) case NL80211_CHAN_WIDTH_80:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) case NL80211_CHAN_WIDTH_80P80:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) case NL80211_CHAN_WIDTH_160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* Channel Switch Wrapper + Wide Bandwidth CSA IE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) ie_len = 2 + 2 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) sizeof(struct ieee80211_wide_bw_chansw_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) pos = skb_put_zero(skb, ie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) *pos++ = WLAN_EID_CHANNEL_SWITCH_WRAPPER; /* EID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) *pos++ = 5; /* len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) /* put sub IE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) chandef = &csa->settings.chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) ieee80211_ie_build_wide_bw_cs(pos, chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) mesh_add_ds_params_ie(sdata, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) bcn->head_len = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) memcpy(bcn->head, skb->data, bcn->head_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) /* now the tail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) skb_trim(skb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) bcn->tail = bcn->head + bcn->head_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if (ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) mesh_add_rsn_ie(sdata, skb) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) mesh_add_ht_cap_ie(sdata, skb) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) mesh_add_ht_oper_ie(sdata, skb) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) mesh_add_meshid_ie(sdata, skb) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) mesh_add_meshconf_ie(sdata, skb) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) mesh_add_awake_window_ie(sdata, skb) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) mesh_add_vht_cap_ie(sdata, skb) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) mesh_add_vht_oper_ie(sdata, skb) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) mesh_add_he_oper_ie(sdata, skb) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) mesh_add_he_6ghz_cap_ie(sdata, skb) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) mesh_add_vendor_ies(sdata, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) bcn->tail_len = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) memcpy(bcn->tail, skb->data, bcn->tail_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) bcn->meshconf = (struct ieee80211_meshconf_ie *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) (bcn->tail + ifmsh->meshconf_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) rcu_assign_pointer(ifmsh->beacon, bcn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) kfree(bcn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) ieee80211_mesh_rebuild_beacon(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) struct beacon_data *old_bcn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) old_bcn = rcu_dereference_protected(sdata->u.mesh.beacon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) lockdep_is_held(&sdata->wdev.mtx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) ret = ieee80211_mesh_build_beacon(&sdata->u.mesh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) /* just reuse old beacon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (old_bcn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) kfree_rcu(old_bcn, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) u32 changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) unsigned long bits = changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) u32 bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (!bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* if we race with running work, worst case this work becomes a noop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) set_bit(bit, &ifmsh->mbss_changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) ieee80211_queue_work(&sdata->local->hw, &sdata->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) u32 changed = BSS_CHANGED_BEACON |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) BSS_CHANGED_BEACON_ENABLED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) BSS_CHANGED_HT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) BSS_CHANGED_BASIC_RATES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) BSS_CHANGED_BEACON_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) BSS_CHANGED_MCAST_RATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) local->fif_other_bss++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /* mesh ifaces must set allmulti to forward mcast traffic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) atomic_inc(&local->iff_allmultis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) ieee80211_configure_filter(local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) ifmsh->mesh_cc_id = 0; /* Disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) /* register sync ops from extensible synchronization framework */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) ifmsh->sync_offset_clockdrift_max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) ieee80211_mesh_root_setup(ifmsh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) ieee80211_queue_work(&local->hw, &sdata->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) sdata->vif.bss_conf.ht_operation_mode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) ifmsh->mshcfg.ht_opmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) sdata->vif.bss_conf.enable_beacon = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) changed |= ieee80211_mps_local_status_update(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (ieee80211_mesh_build_beacon(ifmsh)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) ieee80211_stop_mesh(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) ieee80211_recalc_dtim(local, sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) ieee80211_bss_info_change_notify(sdata, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) netif_carrier_on(sdata->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) struct beacon_data *bcn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) netif_carrier_off(sdata->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) /* flush STAs and mpaths on this iface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) sta_info_flush(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) ieee80211_free_keys(sdata, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) mesh_path_flush_by_iface(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) /* stop the beacon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) ifmsh->mesh_id_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) sdata->vif.bss_conf.enable_beacon = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) sdata->beacon_rate_set = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) /* remove beacon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) bcn = rcu_dereference_protected(ifmsh->beacon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) lockdep_is_held(&sdata->wdev.mtx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) RCU_INIT_POINTER(ifmsh->beacon, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) kfree_rcu(bcn, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /* free all potentially still buffered group-addressed frames */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) local->total_ps_buffered -= skb_queue_len(&ifmsh->ps.bc_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) skb_queue_purge(&ifmsh->ps.bc_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) del_timer_sync(&sdata->u.mesh.housekeeping_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) del_timer_sync(&sdata->u.mesh.mesh_path_root_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) del_timer_sync(&sdata->u.mesh.mesh_path_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) /* clear any mesh work (for next join) we may have accrued */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) ifmsh->wrkq_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) ifmsh->mbss_changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) local->fif_other_bss--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) atomic_dec(&local->iff_allmultis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) ieee80211_configure_filter(local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) static void ieee80211_mesh_csa_mark_radar(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) /* if the current channel is a DFS channel, mark the channel as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) * unavailable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) &sdata->vif.bss_conf.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) NL80211_IFTYPE_MESH_POINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (err > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) cfg80211_radar_event(sdata->local->hw.wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) &sdata->vif.bss_conf.chandef, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) struct ieee802_11_elems *elems, bool beacon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) struct cfg80211_csa_settings params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) struct ieee80211_csa_ie csa_ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) u32 sta_flags, vht_cap_info = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) sdata_assert_lock(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) sta_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) switch (sdata->vif.bss_conf.chandef.width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) case NL80211_CHAN_WIDTH_20_NOHT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) sta_flags |= IEEE80211_STA_DISABLE_HT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) case NL80211_CHAN_WIDTH_20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) sta_flags |= IEEE80211_STA_DISABLE_40MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) case NL80211_CHAN_WIDTH_40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) sta_flags |= IEEE80211_STA_DISABLE_VHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (elems->vht_cap_elem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) vht_cap_info =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) le32_to_cpu(elems->vht_cap_elem->vht_cap_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) memset(¶ms, 0, sizeof(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) err = ieee80211_parse_ch_switch_ie(sdata, elems, sband->band,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) vht_cap_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) sta_flags, sdata->vif.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) &csa_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) /* Mark the channel unavailable if the reason for the switch is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) * regulatory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (csa_ie.reason_code == WLAN_REASON_MESH_CHAN_REGULATORY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) ieee80211_mesh_csa_mark_radar(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) params.chandef = csa_ie.chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) params.count = csa_ie.count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) IEEE80211_CHAN_DISABLED) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) !cfg80211_reg_can_beacon(sdata->local->hw.wiphy, ¶ms.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) NL80211_IFTYPE_MESH_POINT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) sdata_info(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) "mesh STA %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) sdata->vif.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) params.chandef.chan->center_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) params.chandef.width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) params.chandef.center_freq1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) params.chandef.center_freq2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) ¶ms.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) NL80211_IFTYPE_MESH_POINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (err > 0 && !ifmsh->userspace_handles_dfs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) sdata_info(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) "mesh STA %pM switches to channel requiring DFS (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) sdata->vif.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) params.chandef.chan->center_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) params.chandef.width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) params.chandef.center_freq1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) params.chandef.center_freq2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) params.radar_required = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (cfg80211_chandef_identical(¶ms.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) &sdata->vif.bss_conf.chandef)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) mcsa_dbg(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) "received csa with an identical chandef, ignoring\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) mcsa_dbg(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) "received channel switch announcement to go to channel %d MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) params.chandef.chan->center_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (beacon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) ifmsh->chsw_ttl = csa_ie.ttl - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (ifmsh->pre_value >= csa_ie.pre_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) ifmsh->pre_value = csa_ie.pre_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (ifmsh->chsw_ttl >= ifmsh->mshcfg.dot11MeshTTL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_REPEATER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) ¶ms) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) struct ieee80211_mgmt *mgmt, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) struct sk_buff *presp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) struct beacon_data *bcn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) struct ieee80211_mgmt *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) struct ieee802_11_elems elems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) size_t baselen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) pos = mgmt->u.probe_req.variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) baselen = (u8 *) pos - (u8 *) mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (baselen > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) ieee802_11_parse_elems(pos, len - baselen, false, &elems, mgmt->bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (!elems.mesh_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) /* 802.11-2012 10.1.4.3.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if ((!ether_addr_equal(mgmt->da, sdata->vif.addr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) !is_broadcast_ether_addr(mgmt->da)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) elems.ssid_len != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (elems.mesh_id_len != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) (elems.mesh_id_len != ifmsh->mesh_id_len ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) memcmp(elems.mesh_id, ifmsh->mesh_id, ifmsh->mesh_id_len)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) bcn = rcu_dereference(ifmsh->beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (!bcn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) presp = dev_alloc_skb(local->tx_headroom +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) bcn->head_len + bcn->tail_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (!presp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) skb_reserve(presp, local->tx_headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) skb_put_data(presp, bcn->head, bcn->head_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) skb_put_data(presp, bcn->tail, bcn->tail_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) hdr = (struct ieee80211_mgmt *) presp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) IEEE80211_STYPE_PROBE_RESP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) memcpy(hdr->da, mgmt->sa, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) IEEE80211_SKB_CB(presp)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) ieee80211_tx_skb(sdata, presp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) u16 stype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) struct ieee80211_mgmt *mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) struct ieee80211_rx_status *rx_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) struct ieee802_11_elems elems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) struct ieee80211_channel *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) size_t baselen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) int freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) enum nl80211_band band = rx_status->band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) /* ignore ProbeResp to foreign address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (stype == IEEE80211_STYPE_PROBE_RESP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) !ether_addr_equal(mgmt->da, sdata->vif.addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) if (baselen > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) false, &elems, mgmt->bssid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) /* ignore non-mesh or secure / unsecure mismatch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if ((!elems.mesh_id || !elems.mesh_config) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) (elems.rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) (!elems.rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) if (elems.ds_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) freq = rx_status->freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) channel = ieee80211_get_channel(local->hw.wiphy, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (mesh_matches_local(sdata, &elems)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) mpl_dbg(sdata, "rssi_threshold=%d,rx_status->signal=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) sdata->u.mesh.mshcfg.rssi_threshold, rx_status->signal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) if (!sdata->u.mesh.user_mpm ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) sdata->u.mesh.mshcfg.rssi_threshold == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) sdata->u.mesh.mshcfg.rssi_threshold < rx_status->signal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) mesh_neighbour_update(sdata, mgmt->sa, &elems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) rx_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) !sdata->vif.csa_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) ieee80211_mesh_process_chnswitch(sdata, &elems, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if (ifmsh->sync_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) ifmsh->sync_ops->rx_bcn_presp(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) stype, mgmt, &elems, rx_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) struct mesh_csa_settings *tmp_csa_settings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) /* Reset the TTL value and Initiator flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) ifmsh->chsw_ttl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) /* Remove the CSA and MCSP elements from the beacon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) tmp_csa_settings = rcu_dereference_protected(ifmsh->csa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) lockdep_is_held(&sdata->wdev.mtx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) RCU_INIT_POINTER(ifmsh->csa, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (tmp_csa_settings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) kfree_rcu(tmp_csa_settings, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) ret = ieee80211_mesh_rebuild_beacon(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) changed |= BSS_CHANGED_BEACON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) mcsa_dbg(sdata, "complete switching to center freq %d MHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) sdata->vif.bss_conf.chandef.chan->center_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) struct cfg80211_csa_settings *csa_settings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) struct mesh_csa_settings *tmp_csa_settings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) lockdep_assert_held(&sdata->wdev.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) tmp_csa_settings = kmalloc(sizeof(*tmp_csa_settings),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (!tmp_csa_settings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) memcpy(&tmp_csa_settings->settings, csa_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) sizeof(struct cfg80211_csa_settings));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) rcu_assign_pointer(ifmsh->csa, tmp_csa_settings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) ret = ieee80211_mesh_rebuild_beacon(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) tmp_csa_settings = rcu_dereference(ifmsh->csa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) RCU_INIT_POINTER(ifmsh->csa, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) kfree_rcu(tmp_csa_settings, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) return BSS_CHANGED_BEACON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) struct ieee80211_mgmt *mgmt, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) struct ieee802_11_elems *elems)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) struct ieee80211_mgmt *mgmt_fwd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) skb = dev_alloc_skb(local->tx_headroom + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) skb_reserve(skb, local->tx_headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) mgmt_fwd = skb_put(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) elems->mesh_chansw_params_ie->mesh_ttl--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) elems->mesh_chansw_params_ie->mesh_flags &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) memcpy(mgmt_fwd, mgmt, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) eth_broadcast_addr(mgmt_fwd->da);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) memcpy(mgmt_fwd->sa, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) memcpy(mgmt_fwd->bssid, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) ieee80211_tx_skb(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) struct ieee80211_mgmt *mgmt, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) struct ieee802_11_elems elems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) u16 pre_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) bool fwd_csa = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) size_t baselen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (mgmt->u.action.u.measurement.action_code !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) WLAN_ACTION_SPCT_CHL_SWITCH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) pos = mgmt->u.action.u.chan_switch.variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) baselen = offsetof(struct ieee80211_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) u.action.u.chan_switch.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) ieee802_11_parse_elems(pos, len - baselen, true, &elems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) mgmt->bssid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (!mesh_matches_local(sdata, &elems))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) if (!--ifmsh->chsw_ttl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) fwd_csa = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (ifmsh->pre_value >= pre_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) ifmsh->pre_value = pre_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) if (!sdata->vif.csa_active &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) !ieee80211_mesh_process_chnswitch(sdata, &elems, false)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) mcsa_dbg(sdata, "Failed to process CSA action frame");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) /* forward or re-broadcast the CSA frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) if (fwd_csa) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) if (mesh_fwd_csa_frame(sdata, mgmt, len, &elems) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) mcsa_dbg(sdata, "Failed to forward the CSA frame");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) struct ieee80211_mgmt *mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) struct ieee80211_rx_status *rx_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) switch (mgmt->u.action.category) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) case WLAN_CATEGORY_SELF_PROTECTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) switch (mgmt->u.action.u.self_prot.action_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) case WLAN_SP_MESH_PEERING_OPEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) case WLAN_SP_MESH_PEERING_CLOSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) case WLAN_SP_MESH_PEERING_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) mesh_rx_plink_frame(sdata, mgmt, len, rx_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) case WLAN_CATEGORY_MESH_ACTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (mesh_action_is_path_sel(mgmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) mesh_rx_path_sel_frame(sdata, mgmt, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) case WLAN_CATEGORY_SPECTRUM_MGMT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) mesh_rx_csa_frame(sdata, mgmt, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) struct ieee80211_rx_status *rx_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) struct ieee80211_mgmt *mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) u16 stype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) sdata_lock(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) /* mesh already went down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) if (!sdata->u.mesh.mesh_id_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) rx_status = IEEE80211_SKB_RXCB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) mgmt = (struct ieee80211_mgmt *) skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) switch (stype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) case IEEE80211_STYPE_PROBE_RESP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) case IEEE80211_STYPE_BEACON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) rx_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) case IEEE80211_STYPE_PROBE_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) ieee80211_mesh_rx_probe_req(sdata, mgmt, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) case IEEE80211_STYPE_ACTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) sdata_unlock(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) static void mesh_bss_info_changed(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) u32 bit, changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) for_each_set_bit(bit, &ifmsh->mbss_changed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) sizeof(changed) * BITS_PER_BYTE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) clear_bit(bit, &ifmsh->mbss_changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) changed |= BIT(bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) if (sdata->vif.bss_conf.enable_beacon &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) (changed & (BSS_CHANGED_BEACON |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) BSS_CHANGED_HT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) BSS_CHANGED_BASIC_RATES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) BSS_CHANGED_BEACON_INT)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) if (ieee80211_mesh_rebuild_beacon(sdata))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) ieee80211_bss_info_change_notify(sdata, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) sdata_lock(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) /* mesh already went down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) if (!sdata->u.mesh.mesh_id_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (ifmsh->preq_queue_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) time_after(jiffies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) mesh_path_start_discovery(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) ieee80211_mesh_housekeeping(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) ieee80211_mesh_rootpath(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) mesh_sync_adjust_tsf(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if (test_and_clear_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) mesh_bss_info_changed(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) sdata_unlock(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) static u8 zero_addr[ETH_ALEN] = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) timer_setup(&ifmsh->housekeeping_timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) ieee80211_mesh_housekeeping_timer, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) ifmsh->accepting_plinks = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) atomic_set(&ifmsh->mpaths, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) mesh_rmc_init(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) ifmsh->last_preq = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) ifmsh->next_perr = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) /* Allocate all mesh structures when creating the first mesh interface. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) if (!mesh_allocated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) ieee80211s_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) mesh_pathtbl_init(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) timer_setup(&ifmsh->mesh_path_timer, ieee80211_mesh_path_timer, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) timer_setup(&ifmsh->mesh_path_root_timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) ieee80211_mesh_path_root_timer, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) INIT_LIST_HEAD(&ifmsh->preq_queue.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) skb_queue_head_init(&ifmsh->ps.bc_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) spin_lock_init(&ifmsh->mesh_preq_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) spin_lock_init(&ifmsh->sync_offset_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) RCU_INIT_POINTER(ifmsh->beacon, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) sdata->vif.bss_conf.bssid = zero_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) void ieee80211_mesh_teardown_sdata(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) mesh_rmc_free(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) mesh_pathtbl_unregister(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) }