mesh_plink.c revision bf7cd94dcc71682cd6af4a9028f95307b7db41c5
1ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand/* 2ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * Copyright (c) 2008, 2009 open80211s Ltd. 3ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * Author: Luis Carlos Cobo <luisca@cozybit.com> 4ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * 5ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * This program is free software; you can redistribute it and/or modify 6ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * it under the terms of the GNU General Public License version 2 as 7ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * published by the Free Software Foundation. 8ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand */ 9ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand#include <linux/gfp.h> 10ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand#include <linux/kernel.h> 11ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand#include <linux/random.h> 12ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand#include "ieee80211_i.h" 13ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand#include "rate.h" 14ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand#include "mesh.h" 15ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 16ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand#define PLINK_GET_LLID(p) (p + 2) 17ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand#define PLINK_GET_PLID(p) (p + 4) 18ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 19ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ 20ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand jiffies + HZ * t / 1000)) 217a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 22ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand/* We only need a valid sta if user configured a minimum rssi_threshold. */ 23ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand#define rssi_threshold_check(sta, sdata) \ 24ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\ 25ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand (sta && (s8) -ewma_read(&sta->avg_signal) > \ 26ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sdata->u.mesh.mshcfg.rssi_threshold)) 27ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 28ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levandenum plink_event { 29ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand PLINK_UNDEFINED, 30ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand OPN_ACPT, 31ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand OPN_RJCT, 32ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand OPN_IGNR, 33ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand CNF_ACPT, 34ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand CNF_RJCT, 35ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand CNF_IGNR, 36ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand CLS_ACPT, 37ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand CLS_IGNR 38ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand}; 39ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 40ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levandstatic int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, 41ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand enum ieee80211_self_protected_actioncode action, 42ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand u8 *da, __le16 llid, __le16 plid, __le16 reason); 43ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 44ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand/** 45ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * mesh_plink_fsm_restart - restart a mesh peer link finite state machine 46ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * 47ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * @sta: mesh peer link to restart 48ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * 49ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * Locking: this function must be called holding sta->lock 50af1c51fcb2aea23ec2dfe73b7d66515d1622e689Marcelo Tosatti */ 51ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levandstatic inline void mesh_plink_fsm_restart(struct sta_info *sta) 52ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand{ 53ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sta->plink_state = NL80211_PLINK_LISTEN; 54ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sta->llid = sta->plid = sta->reason = 0; 55ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sta->plink_retries = 0; 56ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand} 57ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 58ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand/* 59ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * mesh_set_short_slot_time - enable / disable ERP short slot time. 60ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * 61ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * The standard indirectly mandates mesh STAs to turn off short slot time by 62ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * disallowing advertising this (802.11-2012 8.4.1.4), but that doesn't mean we 63ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * can't be sneaky about it. Enable short slot time if all mesh STAs in the 64ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * MBSS support ERP rates. 65ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * 66ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * Returns BSS_CHANGED_ERP_SLOT or 0 for no change. 67ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand */ 68ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levandstatic u32 mesh_set_short_slot_time(struct ieee80211_sub_if_data *sdata) 69ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand{ 70ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand struct ieee80211_local *local = sdata->local; 71ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand enum ieee80211_band band = ieee80211_get_sdata_band(sdata); 72ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; 73ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand struct sta_info *sta; 74ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand u32 erp_rates = 0, changed = 0; 7590da096ee46b682011b7d549e52b81cf9742e60bBalaji Rao int i; 76ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand bool short_slot = false; 77ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 787a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand if (band == IEEE80211_BAND_5GHZ) { 79ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand /* (IEEE 802.11-2012 19.4.5) */ 80ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand short_slot = true; 81ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand goto out; 82ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand } else if (band != IEEE80211_BAND_2GHZ || 83ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand (band == IEEE80211_BAND_2GHZ && 84ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) 85ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand goto out; 86ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 87ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand for (i = 0; i < sband->n_bitrates; i++) 88ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand if (sband->bitrates[i].flags & IEEE80211_RATE_ERP_G) 89ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand erp_rates |= BIT(i); 907a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 917a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand if (!erp_rates) 927a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand goto out; 937a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 947a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand rcu_read_lock(); 957a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand list_for_each_entry_rcu(sta, &local->sta_list, list) { 967a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand if (sdata != sta->sdata || 977a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand sta->plink_state != NL80211_PLINK_ESTAB) 987a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand continue; 997a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 1007a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand short_slot = false; 1017a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand if (erp_rates & sta->sta.supp_rates[band]) 1027a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand short_slot = true; 1037a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand else 1047a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand break; 1057a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand } 1067a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand rcu_read_unlock(); 107ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 108ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levandout: 109ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand if (sdata->vif.bss_conf.use_short_slot != short_slot) { 110ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sdata->vif.bss_conf.use_short_slot = short_slot; 111ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand changed = BSS_CHANGED_ERP_SLOT; 112ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand mpl_dbg(sdata, "mesh_plink %pM: ERP short slot time %d\n", 1137a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand sdata->vif.addr, short_slot); 114ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand } 115ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand return changed; 116ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand} 117ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 118ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand/** 119dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand * mesh_set_ht_prot_mode - set correct HT protection mode 120ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * 121ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * Section 9.23.3.5 of IEEE 80211-2012 describes the protection rules for HT 122ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * mesh STA in a MBSS. Three HT protection modes are supported for now, non-HT 123ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * mixed mode, 20MHz-protection and no-protection mode. non-HT mixed mode is 124ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * selected if any non-HT peers are present in our MBSS. 20MHz-protection mode 125ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * is selected if all peers in our 20/40MHz MBSS support HT and atleast one 126ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * HT20 peer is present. Otherwise no-protection mode is selected. 127ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand */ 128ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levandstatic u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) 129ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand{ 130ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand struct ieee80211_local *local = sdata->local; 131ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand struct sta_info *sta; 132ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand u32 changed = 0; 133ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand u16 ht_opmode; 134ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand bool non_ht_sta = false, ht20_sta = false; 135ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 136ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) 137ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand return 0; 138ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 139ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand rcu_read_lock(); 140ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand list_for_each_entry_rcu(sta, &local->sta_list, list) { 141ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand if (sdata != sta->sdata || 1427a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand sta->plink_state != NL80211_PLINK_ESTAB) 1437a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand continue; 1447a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 1457a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand switch (sta->ch_width) { 1467a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand case NL80211_CHAN_WIDTH_20_NOHT: 147ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand mpl_dbg(sdata, 148ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand "mesh_plink %pM: nonHT sta (%pM) is present\n", 149ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sdata->vif.addr, sta->sta.addr); 150ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand non_ht_sta = true; 151ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand goto out; 152ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand case NL80211_CHAN_WIDTH_20: 153ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand mpl_dbg(sdata, 154ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand "mesh_plink %pM: HT20 sta (%pM) is present\n", 155ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sdata->vif.addr, sta->sta.addr); 156ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand ht20_sta = true; 157ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand default: 158ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand break; 159ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand } 160ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand } 161ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levandout: 162ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand rcu_read_unlock(); 163ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 164ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand if (non_ht_sta) 165ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; 166ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand else if (ht20_sta && 167ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sdata->vif.bss_conf.chandef.width > NL80211_CHAN_WIDTH_20) 168ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; 169ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand else 170ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; 171ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 172ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) { 173ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sdata->vif.bss_conf.ht_operation_mode = ht_opmode; 174ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sdata->u.mesh.mshcfg.ht_opmode = ht_opmode; 175ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand changed = BSS_CHANGED_HT; 176ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand mpl_dbg(sdata, 177ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand "mesh_plink %pM: protection mode changed to %d\n", 178ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sdata->vif.addr, ht_opmode); 179ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand } 1807a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 181ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand return changed; 182ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand} 183dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand 184ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand/** 185ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * __mesh_plink_deactivate - deactivate mesh peer link 1867a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand * 1877a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand * @sta: mesh peer link to deactivate 1887a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand * 1897a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand * All mesh paths with this peer as next hop will be flushed 1907a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand * Returns beacon changed flag if the beacon content changed. 191ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * 192ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * Locking: the caller must hold sta->lock 193ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand */ 194ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levandstatic u32 __mesh_plink_deactivate(struct sta_info *sta) 1957a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand{ 196ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand struct ieee80211_sub_if_data *sdata = sta->sdata; 1977a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand u32 changed = 0; 198ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand 199ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand if (sta->plink_state == NL80211_PLINK_ESTAB) 200ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand changed = mesh_plink_dec_estab_count(sdata); 2017a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand sta->plink_state = NL80211_PLINK_BLOCKED; 2027a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand mesh_path_flush_by_nexthop(sta); 2037a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2047a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand ieee80211_mps_sta_status_update(sta); 2057a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand changed |= ieee80211_mps_local_status_update(sdata); 2067a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2077a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand return changed; 2087a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand} 2097a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 210ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand/** 211ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand * mesh_plink_deactivate - deactivate mesh peer link 2127a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand * 2137a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand * @sta: mesh peer link to deactivate 2147a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand * 2157a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand * All mesh paths with this peer as next hop will be flushed 2167a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand */ 2177a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levandu32 mesh_plink_deactivate(struct sta_info *sta) 2187a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand{ 2197a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand struct ieee80211_sub_if_data *sdata = sta->sdata; 2207a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand u32 changed; 2217a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2227a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand spin_lock_bh(&sta->lock); 2237a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand changed = __mesh_plink_deactivate(sta); 224ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED); 225ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, 226ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sta->sta.addr, sta->llid, sta->plid, 2277a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand sta->reason); 2287a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand spin_unlock_bh(&sta->lock); 2297a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2307a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand return changed; 2317a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand} 2327a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2337a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levandstatic int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, 2347a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand enum ieee80211_self_protected_actioncode action, 2357a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand u8 *da, __le16 llid, __le16 plid, __le16 reason) 2367a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand{ 2377a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand struct ieee80211_local *local = sdata->local; 2387a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand struct sk_buff *skb; 2397a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand struct ieee80211_tx_info *info; 2407a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand struct ieee80211_mgmt *mgmt; 241ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand bool include_plid = false; 2427a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand u16 peering_proto = 0; 2437a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand u8 *pos, ie_len = 4; 2447a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + 245ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand sizeof(mgmt->u.action.u.self_prot); 2467a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand int err = -ENOMEM; 2477a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2487a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand skb = dev_alloc_skb(local->tx_headroom + 249ad75a41085d80c8ce5e885962c15779935f8267eGeoff Levand hdr_len + 250 2 + /* capability info */ 251 2 + /* AID */ 252 2 + 8 + /* supported rates */ 253 2 + (IEEE80211_MAX_SUPP_RATES - 8) + 254 2 + sdata->u.mesh.mesh_id_len + 255 2 + sizeof(struct ieee80211_meshconf_ie) + 256 2 + sizeof(struct ieee80211_ht_cap) + 257 2 + sizeof(struct ieee80211_ht_operation) + 258 2 + 8 + /* peering IE */ 259 sdata->u.mesh.ie_len); 260 if (!skb) 261 return -1; 262 info = IEEE80211_SKB_CB(skb); 263 skb_reserve(skb, local->tx_headroom); 264 mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); 265 memset(mgmt, 0, hdr_len); 266 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 267 IEEE80211_STYPE_ACTION); 268 memcpy(mgmt->da, da, ETH_ALEN); 269 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 270 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); 271 mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED; 272 mgmt->u.action.u.self_prot.action_code = action; 273 274 if (action != WLAN_SP_MESH_PEERING_CLOSE) { 275 enum ieee80211_band band = ieee80211_get_sdata_band(sdata); 276 277 /* capability info */ 278 pos = skb_put(skb, 2); 279 memset(pos, 0, 2); 280 if (action == WLAN_SP_MESH_PEERING_CONFIRM) { 281 /* AID */ 282 pos = skb_put(skb, 2); 283 memcpy(pos + 2, &plid, 2); 284 } 285 if (ieee80211_add_srates_ie(sdata, skb, true, band) || 286 ieee80211_add_ext_srates_ie(sdata, skb, true, band) || 287 mesh_add_rsn_ie(sdata, skb) || 288 mesh_add_meshid_ie(sdata, skb) || 289 mesh_add_meshconf_ie(sdata, skb)) 290 goto free; 291 } else { /* WLAN_SP_MESH_PEERING_CLOSE */ 292 info->flags |= IEEE80211_TX_CTL_NO_ACK; 293 if (mesh_add_meshid_ie(sdata, skb)) 294 goto free; 295 } 296 297 /* Add Mesh Peering Management element */ 298 switch (action) { 299 case WLAN_SP_MESH_PEERING_OPEN: 300 break; 301 case WLAN_SP_MESH_PEERING_CONFIRM: 302 ie_len += 2; 303 include_plid = true; 304 break; 305 case WLAN_SP_MESH_PEERING_CLOSE: 306 if (plid) { 307 ie_len += 2; 308 include_plid = true; 309 } 310 ie_len += 2; /* reason code */ 311 break; 312 default: 313 err = -EINVAL; 314 goto free; 315 } 316 317 if (WARN_ON(skb_tailroom(skb) < 2 + ie_len)) 318 goto free; 319 320 pos = skb_put(skb, 2 + ie_len); 321 *pos++ = WLAN_EID_PEER_MGMT; 322 *pos++ = ie_len; 323 memcpy(pos, &peering_proto, 2); 324 pos += 2; 325 memcpy(pos, &llid, 2); 326 pos += 2; 327 if (include_plid) { 328 memcpy(pos, &plid, 2); 329 pos += 2; 330 } 331 if (action == WLAN_SP_MESH_PEERING_CLOSE) { 332 memcpy(pos, &reason, 2); 333 pos += 2; 334 } 335 336 if (action != WLAN_SP_MESH_PEERING_CLOSE) { 337 if (mesh_add_ht_cap_ie(sdata, skb) || 338 mesh_add_ht_oper_ie(sdata, skb)) 339 goto free; 340 } 341 342 if (mesh_add_vendor_ies(sdata, skb)) 343 goto free; 344 345 ieee80211_tx_skb(sdata, skb); 346 return 0; 347free: 348 kfree_skb(skb); 349 return err; 350} 351 352static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, 353 struct sta_info *sta, 354 struct ieee802_11_elems *elems, bool insert) 355{ 356 struct ieee80211_local *local = sdata->local; 357 enum ieee80211_band band = ieee80211_get_sdata_band(sdata); 358 struct ieee80211_supported_band *sband; 359 u32 rates, basic_rates = 0, changed = 0; 360 361 sband = local->hw.wiphy->bands[band]; 362 rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates); 363 364 spin_lock_bh(&sta->lock); 365 sta->last_rx = jiffies; 366 367 /* rates and capabilities don't change during peering */ 368 if (sta->plink_state == NL80211_PLINK_ESTAB) 369 goto out; 370 371 if (sta->sta.supp_rates[band] != rates) 372 changed |= IEEE80211_RC_SUPP_RATES_CHANGED; 373 sta->sta.supp_rates[band] = rates; 374 if (elems->ht_cap_elem && 375 sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) 376 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, 377 elems->ht_cap_elem, sta); 378 else 379 memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); 380 381 if (elems->ht_operation) { 382 struct cfg80211_chan_def chandef; 383 384 if (!(elems->ht_operation->ht_param & 385 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) 386 sta->sta.bandwidth = IEEE80211_STA_RX_BW_20; 387 ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, 388 elems->ht_operation, &chandef); 389 if (sta->ch_width != chandef.width) 390 changed |= IEEE80211_RC_BW_CHANGED; 391 sta->ch_width = chandef.width; 392 } 393 394 if (insert) 395 rate_control_rate_init(sta); 396 else 397 rate_control_rate_update(local, sband, sta, changed); 398out: 399 spin_unlock_bh(&sta->lock); 400} 401 402static struct sta_info * 403__mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr) 404{ 405 struct sta_info *sta; 406 407 if (sdata->local->num_sta >= MESH_MAX_PLINKS) 408 return NULL; 409 410 sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); 411 if (!sta) 412 return NULL; 413 414 sta->plink_state = NL80211_PLINK_LISTEN; 415 init_timer(&sta->plink_timer); 416 417 sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); 418 sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); 419 sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); 420 421 set_sta_flag(sta, WLAN_STA_WME); 422 423 return sta; 424} 425 426static struct sta_info * 427mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr, 428 struct ieee802_11_elems *elems) 429{ 430 struct sta_info *sta = NULL; 431 432 /* Userspace handles peer allocation when security is enabled */ 433 if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) 434 cfg80211_notify_new_peer_candidate(sdata->dev, addr, 435 elems->ie_start, 436 elems->total_len, 437 GFP_KERNEL); 438 else 439 sta = __mesh_sta_info_alloc(sdata, addr); 440 441 return sta; 442} 443 444/* 445 * mesh_sta_info_get - return mesh sta info entry for @addr. 446 * 447 * @sdata: local meshif 448 * @addr: peer's address 449 * @elems: IEs from beacon or mesh peering frame. 450 * 451 * Return existing or newly allocated sta_info under RCU read lock. 452 * (re)initialize with given IEs. 453 */ 454static struct sta_info * 455mesh_sta_info_get(struct ieee80211_sub_if_data *sdata, 456 u8 *addr, struct ieee802_11_elems *elems) __acquires(RCU) 457{ 458 struct sta_info *sta = NULL; 459 460 rcu_read_lock(); 461 sta = sta_info_get(sdata, addr); 462 if (sta) { 463 mesh_sta_info_init(sdata, sta, elems, false); 464 } else { 465 rcu_read_unlock(); 466 /* can't run atomic */ 467 sta = mesh_sta_info_alloc(sdata, addr, elems); 468 if (!sta) { 469 rcu_read_lock(); 470 return NULL; 471 } 472 473 mesh_sta_info_init(sdata, sta, elems, true); 474 475 if (sta_info_insert_rcu(sta)) 476 return NULL; 477 } 478 479 return sta; 480} 481 482/* 483 * mesh_neighbour_update - update or initialize new mesh neighbor. 484 * 485 * @sdata: local meshif 486 * @addr: peer's address 487 * @elems: IEs from beacon or mesh peering frame 488 * 489 * Initiates peering if appropriate. 490 */ 491void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, 492 u8 *hw_addr, 493 struct ieee802_11_elems *elems) 494{ 495 struct sta_info *sta; 496 u32 changed = 0; 497 498 sta = mesh_sta_info_get(sdata, hw_addr, elems); 499 if (!sta) 500 goto out; 501 502 if (mesh_peer_accepts_plinks(elems) && 503 sta->plink_state == NL80211_PLINK_LISTEN && 504 sdata->u.mesh.accepting_plinks && 505 sdata->u.mesh.mshcfg.auto_open_plinks && 506 rssi_threshold_check(sta, sdata)) 507 changed = mesh_plink_open(sta); 508 509 ieee80211_mps_frame_release(sta, elems); 510out: 511 rcu_read_unlock(); 512 ieee80211_mbss_info_change_notify(sdata, changed); 513} 514 515static void mesh_plink_timer(unsigned long data) 516{ 517 struct sta_info *sta; 518 __le16 llid, plid, reason; 519 struct ieee80211_sub_if_data *sdata; 520 struct mesh_config *mshcfg; 521 522 /* 523 * This STA is valid because sta_info_destroy() will 524 * del_timer_sync() this timer after having made sure 525 * it cannot be readded (by deleting the plink.) 526 */ 527 sta = (struct sta_info *) data; 528 529 if (sta->sdata->local->quiescing) { 530 sta->plink_timer_was_running = true; 531 return; 532 } 533 534 spin_lock_bh(&sta->lock); 535 if (sta->ignore_plink_timer) { 536 sta->ignore_plink_timer = false; 537 spin_unlock_bh(&sta->lock); 538 return; 539 } 540 mpl_dbg(sta->sdata, 541 "Mesh plink timer for %pM fired on state %d\n", 542 sta->sta.addr, sta->plink_state); 543 reason = 0; 544 llid = sta->llid; 545 plid = sta->plid; 546 sdata = sta->sdata; 547 mshcfg = &sdata->u.mesh.mshcfg; 548 549 switch (sta->plink_state) { 550 case NL80211_PLINK_OPN_RCVD: 551 case NL80211_PLINK_OPN_SNT: 552 /* retry timer */ 553 if (sta->plink_retries < mshcfg->dot11MeshMaxRetries) { 554 u32 rand; 555 mpl_dbg(sta->sdata, 556 "Mesh plink for %pM (retry, timeout): %d %d\n", 557 sta->sta.addr, sta->plink_retries, 558 sta->plink_timeout); 559 get_random_bytes(&rand, sizeof(u32)); 560 sta->plink_timeout = sta->plink_timeout + 561 rand % sta->plink_timeout; 562 ++sta->plink_retries; 563 mod_plink_timer(sta, sta->plink_timeout); 564 spin_unlock_bh(&sta->lock); 565 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, 566 sta->sta.addr, llid, 0, 0); 567 break; 568 } 569 reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES); 570 /* fall through on else */ 571 case NL80211_PLINK_CNF_RCVD: 572 /* confirm timer */ 573 if (!reason) 574 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT); 575 sta->plink_state = NL80211_PLINK_HOLDING; 576 mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); 577 spin_unlock_bh(&sta->lock); 578 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, 579 sta->sta.addr, llid, plid, reason); 580 break; 581 case NL80211_PLINK_HOLDING: 582 /* holding timer */ 583 del_timer(&sta->plink_timer); 584 mesh_plink_fsm_restart(sta); 585 spin_unlock_bh(&sta->lock); 586 break; 587 default: 588 spin_unlock_bh(&sta->lock); 589 break; 590 } 591} 592 593#ifdef CONFIG_PM 594void mesh_plink_quiesce(struct sta_info *sta) 595{ 596 if (!ieee80211_vif_is_mesh(&sta->sdata->vif)) 597 return; 598 599 /* no kernel mesh sta timers have been initialized */ 600 if (sta->sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) 601 return; 602 603 if (del_timer_sync(&sta->plink_timer)) 604 sta->plink_timer_was_running = true; 605} 606 607void mesh_plink_restart(struct sta_info *sta) 608{ 609 if (sta->plink_timer_was_running) { 610 add_timer(&sta->plink_timer); 611 sta->plink_timer_was_running = false; 612 } 613} 614#endif 615 616static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) 617{ 618 sta->plink_timer.expires = jiffies + (HZ * timeout / 1000); 619 sta->plink_timer.data = (unsigned long) sta; 620 sta->plink_timer.function = mesh_plink_timer; 621 sta->plink_timeout = timeout; 622 add_timer(&sta->plink_timer); 623} 624 625u32 mesh_plink_open(struct sta_info *sta) 626{ 627 __le16 llid; 628 struct ieee80211_sub_if_data *sdata = sta->sdata; 629 u32 changed; 630 631 if (!test_sta_flag(sta, WLAN_STA_AUTH)) 632 return 0; 633 634 spin_lock_bh(&sta->lock); 635 get_random_bytes(&llid, 2); 636 sta->llid = llid; 637 if (sta->plink_state != NL80211_PLINK_LISTEN && 638 sta->plink_state != NL80211_PLINK_BLOCKED) { 639 spin_unlock_bh(&sta->lock); 640 return 0; 641 } 642 sta->plink_state = NL80211_PLINK_OPN_SNT; 643 mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout); 644 spin_unlock_bh(&sta->lock); 645 mpl_dbg(sdata, 646 "Mesh plink: starting establishment with %pM\n", 647 sta->sta.addr); 648 649 /* set the non-peer mode to active during peering */ 650 changed = ieee80211_mps_local_status_update(sdata); 651 652 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, 653 sta->sta.addr, llid, 0, 0); 654 return changed; 655} 656 657u32 mesh_plink_block(struct sta_info *sta) 658{ 659 u32 changed; 660 661 spin_lock_bh(&sta->lock); 662 changed = __mesh_plink_deactivate(sta); 663 sta->plink_state = NL80211_PLINK_BLOCKED; 664 spin_unlock_bh(&sta->lock); 665 666 return changed; 667} 668 669 670void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, 671 struct ieee80211_mgmt *mgmt, size_t len, 672 struct ieee80211_rx_status *rx_status) 673{ 674 struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; 675 struct ieee802_11_elems elems; 676 struct sta_info *sta; 677 enum plink_event event; 678 enum ieee80211_self_protected_actioncode ftype; 679 size_t baselen; 680 bool matches_local = true; 681 u8 ie_len; 682 u8 *baseaddr; 683 u32 changed = 0; 684 __le16 plid, llid, reason; 685 static const char * const mplstates[] = { 686 [NL80211_PLINK_LISTEN] = "LISTEN", 687 [NL80211_PLINK_OPN_SNT] = "OPN-SNT", 688 [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD", 689 [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD", 690 [NL80211_PLINK_ESTAB] = "ESTAB", 691 [NL80211_PLINK_HOLDING] = "HOLDING", 692 [NL80211_PLINK_BLOCKED] = "BLOCKED" 693 }; 694 695 /* need action_code, aux */ 696 if (len < IEEE80211_MIN_ACTION_SIZE + 3) 697 return; 698 699 if (is_multicast_ether_addr(mgmt->da)) { 700 mpl_dbg(sdata, 701 "Mesh plink: ignore frame from multicast address\n"); 702 return; 703 } 704 705 baseaddr = mgmt->u.action.u.self_prot.variable; 706 baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt; 707 if (mgmt->u.action.u.self_prot.action_code == 708 WLAN_SP_MESH_PEERING_CONFIRM) { 709 baseaddr += 4; 710 baselen += 4; 711 } 712 ieee802_11_parse_elems(baseaddr, len - baselen, &elems); 713 714 if (!elems.peering) { 715 mpl_dbg(sdata, 716 "Mesh plink: missing necessary peer link ie\n"); 717 return; 718 } 719 720 if (elems.rsn_len && 721 sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { 722 mpl_dbg(sdata, 723 "Mesh plink: can't establish link with secure peer\n"); 724 return; 725 } 726 727 ftype = mgmt->u.action.u.self_prot.action_code; 728 ie_len = elems.peering_len; 729 if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) || 730 (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) || 731 (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6 732 && ie_len != 8)) { 733 mpl_dbg(sdata, 734 "Mesh plink: incorrect plink ie length %d %d\n", 735 ftype, ie_len); 736 return; 737 } 738 739 if (ftype != WLAN_SP_MESH_PEERING_CLOSE && 740 (!elems.mesh_id || !elems.mesh_config)) { 741 mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); 742 return; 743 } 744 /* Note the lines below are correct, the llid in the frame is the plid 745 * from the point of view of this host. 746 */ 747 memcpy(&plid, PLINK_GET_LLID(elems.peering), 2); 748 if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || 749 (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) 750 memcpy(&llid, PLINK_GET_PLID(elems.peering), 2); 751 752 /* WARNING: Only for sta pointer, is dropped & re-acquired */ 753 rcu_read_lock(); 754 755 sta = sta_info_get(sdata, mgmt->sa); 756 if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) { 757 mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n"); 758 rcu_read_unlock(); 759 return; 760 } 761 762 if (ftype == WLAN_SP_MESH_PEERING_OPEN && 763 !rssi_threshold_check(sta, sdata)) { 764 mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n", 765 mgmt->sa); 766 rcu_read_unlock(); 767 return; 768 } 769 770 if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) { 771 mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n"); 772 rcu_read_unlock(); 773 return; 774 } 775 776 if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) { 777 rcu_read_unlock(); 778 return; 779 } 780 781 /* Now we will figure out the appropriate event... */ 782 event = PLINK_UNDEFINED; 783 if (ftype != WLAN_SP_MESH_PEERING_CLOSE && 784 !mesh_matches_local(sdata, &elems)) { 785 matches_local = false; 786 switch (ftype) { 787 case WLAN_SP_MESH_PEERING_OPEN: 788 event = OPN_RJCT; 789 break; 790 case WLAN_SP_MESH_PEERING_CONFIRM: 791 event = CNF_RJCT; 792 break; 793 default: 794 break; 795 } 796 } 797 798 if (!sta && !matches_local) { 799 rcu_read_unlock(); 800 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); 801 llid = 0; 802 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, 803 mgmt->sa, llid, plid, reason); 804 return; 805 } else if (!sta) { 806 /* ftype == WLAN_SP_MESH_PEERING_OPEN */ 807 if (!mesh_plink_free_count(sdata)) { 808 mpl_dbg(sdata, "Mesh plink error: no more free plinks\n"); 809 rcu_read_unlock(); 810 return; 811 } 812 event = OPN_ACPT; 813 } else if (matches_local) { 814 switch (ftype) { 815 case WLAN_SP_MESH_PEERING_OPEN: 816 if (!mesh_plink_free_count(sdata) || 817 (sta->plid && sta->plid != plid)) 818 event = OPN_IGNR; 819 else 820 event = OPN_ACPT; 821 break; 822 case WLAN_SP_MESH_PEERING_CONFIRM: 823 if (!mesh_plink_free_count(sdata) || 824 (sta->llid != llid || sta->plid != plid)) 825 event = CNF_IGNR; 826 else 827 event = CNF_ACPT; 828 break; 829 case WLAN_SP_MESH_PEERING_CLOSE: 830 if (sta->plink_state == NL80211_PLINK_ESTAB) 831 /* Do not check for llid or plid. This does not 832 * follow the standard but since multiple plinks 833 * per sta are not supported, it is necessary in 834 * order to avoid a livelock when MP A sees an 835 * establish peer link to MP B but MP B does not 836 * see it. This can be caused by a timeout in 837 * B's peer link establishment or B beign 838 * restarted. 839 */ 840 event = CLS_ACPT; 841 else if (sta->plid != plid) 842 event = CLS_IGNR; 843 else if (ie_len == 7 && sta->llid != llid) 844 event = CLS_IGNR; 845 else 846 event = CLS_ACPT; 847 break; 848 default: 849 mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n"); 850 rcu_read_unlock(); 851 return; 852 } 853 } 854 855 if (event == OPN_ACPT) { 856 rcu_read_unlock(); 857 /* allocate sta entry if necessary and update info */ 858 sta = mesh_sta_info_get(sdata, mgmt->sa, &elems); 859 if (!sta) { 860 mpl_dbg(sdata, "Mesh plink: failed to init peer!\n"); 861 rcu_read_unlock(); 862 return; 863 } 864 } 865 866 mpl_dbg(sdata, 867 "Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n", 868 mgmt->sa, mplstates[sta->plink_state], 869 le16_to_cpu(sta->llid), le16_to_cpu(sta->plid), 870 event); 871 reason = 0; 872 spin_lock_bh(&sta->lock); 873 switch (sta->plink_state) { 874 /* spin_unlock as soon as state is updated at each case */ 875 case NL80211_PLINK_LISTEN: 876 switch (event) { 877 case CLS_ACPT: 878 mesh_plink_fsm_restart(sta); 879 spin_unlock_bh(&sta->lock); 880 break; 881 case OPN_ACPT: 882 sta->plink_state = NL80211_PLINK_OPN_RCVD; 883 sta->plid = plid; 884 get_random_bytes(&llid, 2); 885 sta->llid = llid; 886 mesh_plink_timer_set(sta, 887 mshcfg->dot11MeshRetryTimeout); 888 889 /* set the non-peer mode to active during peering */ 890 changed |= ieee80211_mps_local_status_update(sdata); 891 892 spin_unlock_bh(&sta->lock); 893 mesh_plink_frame_tx(sdata, 894 WLAN_SP_MESH_PEERING_OPEN, 895 sta->sta.addr, llid, 0, 0); 896 mesh_plink_frame_tx(sdata, 897 WLAN_SP_MESH_PEERING_CONFIRM, 898 sta->sta.addr, llid, plid, 0); 899 break; 900 default: 901 spin_unlock_bh(&sta->lock); 902 break; 903 } 904 break; 905 906 case NL80211_PLINK_OPN_SNT: 907 switch (event) { 908 case OPN_RJCT: 909 case CNF_RJCT: 910 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); 911 case CLS_ACPT: 912 if (!reason) 913 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); 914 sta->reason = reason; 915 sta->plink_state = NL80211_PLINK_HOLDING; 916 if (!mod_plink_timer(sta, 917 mshcfg->dot11MeshHoldingTimeout)) 918 sta->ignore_plink_timer = true; 919 920 llid = sta->llid; 921 spin_unlock_bh(&sta->lock); 922 mesh_plink_frame_tx(sdata, 923 WLAN_SP_MESH_PEERING_CLOSE, 924 sta->sta.addr, llid, plid, reason); 925 break; 926 case OPN_ACPT: 927 /* retry timer is left untouched */ 928 sta->plink_state = NL80211_PLINK_OPN_RCVD; 929 sta->plid = plid; 930 llid = sta->llid; 931 spin_unlock_bh(&sta->lock); 932 mesh_plink_frame_tx(sdata, 933 WLAN_SP_MESH_PEERING_CONFIRM, 934 sta->sta.addr, llid, plid, 0); 935 break; 936 case CNF_ACPT: 937 sta->plink_state = NL80211_PLINK_CNF_RCVD; 938 if (!mod_plink_timer(sta, 939 mshcfg->dot11MeshConfirmTimeout)) 940 sta->ignore_plink_timer = true; 941 942 spin_unlock_bh(&sta->lock); 943 break; 944 default: 945 spin_unlock_bh(&sta->lock); 946 break; 947 } 948 break; 949 950 case NL80211_PLINK_OPN_RCVD: 951 switch (event) { 952 case OPN_RJCT: 953 case CNF_RJCT: 954 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); 955 case CLS_ACPT: 956 if (!reason) 957 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); 958 sta->reason = reason; 959 sta->plink_state = NL80211_PLINK_HOLDING; 960 if (!mod_plink_timer(sta, 961 mshcfg->dot11MeshHoldingTimeout)) 962 sta->ignore_plink_timer = true; 963 964 llid = sta->llid; 965 spin_unlock_bh(&sta->lock); 966 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, 967 sta->sta.addr, llid, plid, reason); 968 break; 969 case OPN_ACPT: 970 llid = sta->llid; 971 spin_unlock_bh(&sta->lock); 972 mesh_plink_frame_tx(sdata, 973 WLAN_SP_MESH_PEERING_CONFIRM, 974 sta->sta.addr, llid, plid, 0); 975 break; 976 case CNF_ACPT: 977 del_timer(&sta->plink_timer); 978 sta->plink_state = NL80211_PLINK_ESTAB; 979 spin_unlock_bh(&sta->lock); 980 changed |= mesh_plink_inc_estab_count(sdata); 981 changed |= mesh_set_ht_prot_mode(sdata); 982 changed |= mesh_set_short_slot_time(sdata); 983 mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", 984 sta->sta.addr); 985 ieee80211_mps_sta_status_update(sta); 986 changed |= ieee80211_mps_set_sta_local_pm(sta, 987 mshcfg->power_mode); 988 break; 989 default: 990 spin_unlock_bh(&sta->lock); 991 break; 992 } 993 break; 994 995 case NL80211_PLINK_CNF_RCVD: 996 switch (event) { 997 case OPN_RJCT: 998 case CNF_RJCT: 999 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); 1000 case CLS_ACPT: 1001 if (!reason) 1002 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); 1003 sta->reason = reason; 1004 sta->plink_state = NL80211_PLINK_HOLDING; 1005 if (!mod_plink_timer(sta, 1006 mshcfg->dot11MeshHoldingTimeout)) 1007 sta->ignore_plink_timer = true; 1008 1009 llid = sta->llid; 1010 spin_unlock_bh(&sta->lock); 1011 mesh_plink_frame_tx(sdata, 1012 WLAN_SP_MESH_PEERING_CLOSE, 1013 sta->sta.addr, llid, plid, reason); 1014 break; 1015 case OPN_ACPT: 1016 del_timer(&sta->plink_timer); 1017 sta->plink_state = NL80211_PLINK_ESTAB; 1018 spin_unlock_bh(&sta->lock); 1019 changed |= mesh_plink_inc_estab_count(sdata); 1020 changed |= mesh_set_ht_prot_mode(sdata); 1021 changed |= mesh_set_short_slot_time(sdata); 1022 mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", 1023 sta->sta.addr); 1024 mesh_plink_frame_tx(sdata, 1025 WLAN_SP_MESH_PEERING_CONFIRM, 1026 sta->sta.addr, llid, plid, 0); 1027 ieee80211_mps_sta_status_update(sta); 1028 changed |= ieee80211_mps_set_sta_local_pm(sta, 1029 mshcfg->power_mode); 1030 break; 1031 default: 1032 spin_unlock_bh(&sta->lock); 1033 break; 1034 } 1035 break; 1036 1037 case NL80211_PLINK_ESTAB: 1038 switch (event) { 1039 case CLS_ACPT: 1040 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); 1041 sta->reason = reason; 1042 changed |= __mesh_plink_deactivate(sta); 1043 sta->plink_state = NL80211_PLINK_HOLDING; 1044 llid = sta->llid; 1045 mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); 1046 spin_unlock_bh(&sta->lock); 1047 changed |= mesh_set_ht_prot_mode(sdata); 1048 changed |= mesh_set_short_slot_time(sdata); 1049 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, 1050 sta->sta.addr, llid, plid, reason); 1051 break; 1052 case OPN_ACPT: 1053 llid = sta->llid; 1054 spin_unlock_bh(&sta->lock); 1055 mesh_plink_frame_tx(sdata, 1056 WLAN_SP_MESH_PEERING_CONFIRM, 1057 sta->sta.addr, llid, plid, 0); 1058 break; 1059 default: 1060 spin_unlock_bh(&sta->lock); 1061 break; 1062 } 1063 break; 1064 case NL80211_PLINK_HOLDING: 1065 switch (event) { 1066 case CLS_ACPT: 1067 if (del_timer(&sta->plink_timer)) 1068 sta->ignore_plink_timer = 1; 1069 mesh_plink_fsm_restart(sta); 1070 spin_unlock_bh(&sta->lock); 1071 break; 1072 case OPN_ACPT: 1073 case CNF_ACPT: 1074 case OPN_RJCT: 1075 case CNF_RJCT: 1076 llid = sta->llid; 1077 reason = sta->reason; 1078 spin_unlock_bh(&sta->lock); 1079 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, 1080 sta->sta.addr, llid, plid, reason); 1081 break; 1082 default: 1083 spin_unlock_bh(&sta->lock); 1084 } 1085 break; 1086 default: 1087 /* should not get here, PLINK_BLOCKED is dealt with at the 1088 * beginning of the function 1089 */ 1090 spin_unlock_bh(&sta->lock); 1091 break; 1092 } 1093 1094 rcu_read_unlock(); 1095 1096 if (changed) 1097 ieee80211_mbss_info_change_notify(sdata, changed); 1098} 1099