aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh_plink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh_plink.c')
-rw-r--r--net/mac80211/mesh_plink.c70
1 files changed, 46 insertions, 24 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 0f7c6e6a4248..ea13a80a476c 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -6,6 +6,7 @@
6 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 */ 8 */
9#include <linux/gfp.h>
9#include <linux/kernel.h> 10#include <linux/kernel.h>
10#include <linux/random.h> 11#include <linux/random.h>
11#include "ieee80211_i.h" 12#include "ieee80211_i.h"
@@ -64,7 +65,6 @@ void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
64{ 65{
65 atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); 66 atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
66 mesh_accept_plinks_update(sdata); 67 mesh_accept_plinks_update(sdata);
67 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
68} 68}
69 69
70static inline 70static inline
@@ -72,7 +72,6 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
72{ 72{
73 atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); 73 atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
74 mesh_accept_plinks_update(sdata); 74 mesh_accept_plinks_update(sdata);
75 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
76} 75}
77 76
78/** 77/**
@@ -102,7 +101,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
102 if (local->num_sta >= MESH_MAX_PLINKS) 101 if (local->num_sta >= MESH_MAX_PLINKS)
103 return NULL; 102 return NULL;
104 103
105 sta = sta_info_alloc(sdata, hw_addr, GFP_ATOMIC); 104 sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
106 if (!sta) 105 if (!sta)
107 return NULL; 106 return NULL;
108 107
@@ -114,7 +113,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
114} 113}
115 114
116/** 115/**
117 * mesh_plink_deactivate - deactivate mesh peer link 116 * __mesh_plink_deactivate - deactivate mesh peer link
118 * 117 *
119 * @sta: mesh peer link to deactivate 118 * @sta: mesh peer link to deactivate
120 * 119 *
@@ -122,18 +121,23 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
122 * 121 *
123 * Locking: the caller must hold sta->lock 122 * Locking: the caller must hold sta->lock
124 */ 123 */
125static void __mesh_plink_deactivate(struct sta_info *sta) 124static bool __mesh_plink_deactivate(struct sta_info *sta)
126{ 125{
127 struct ieee80211_sub_if_data *sdata = sta->sdata; 126 struct ieee80211_sub_if_data *sdata = sta->sdata;
127 bool deactivated = false;
128 128
129 if (sta->plink_state == PLINK_ESTAB) 129 if (sta->plink_state == PLINK_ESTAB) {
130 mesh_plink_dec_estab_count(sdata); 130 mesh_plink_dec_estab_count(sdata);
131 deactivated = true;
132 }
131 sta->plink_state = PLINK_BLOCKED; 133 sta->plink_state = PLINK_BLOCKED;
132 mesh_path_flush_by_nexthop(sta); 134 mesh_path_flush_by_nexthop(sta);
135
136 return deactivated;
133} 137}
134 138
135/** 139/**
136 * __mesh_plink_deactivate - deactivate mesh peer link 140 * mesh_plink_deactivate - deactivate mesh peer link
137 * 141 *
138 * @sta: mesh peer link to deactivate 142 * @sta: mesh peer link to deactivate
139 * 143 *
@@ -141,9 +145,15 @@ static void __mesh_plink_deactivate(struct sta_info *sta)
141 */ 145 */
142void mesh_plink_deactivate(struct sta_info *sta) 146void mesh_plink_deactivate(struct sta_info *sta)
143{ 147{
148 struct ieee80211_sub_if_data *sdata = sta->sdata;
149 bool deactivated;
150
144 spin_lock_bh(&sta->lock); 151 spin_lock_bh(&sta->lock);
145 __mesh_plink_deactivate(sta); 152 deactivated = __mesh_plink_deactivate(sta);
146 spin_unlock_bh(&sta->lock); 153 spin_unlock_bh(&sta->lock);
154
155 if (deactivated)
156 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
147} 157}
148 158
149static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, 159static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
@@ -169,9 +179,9 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
169 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 179 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
170 IEEE80211_STYPE_ACTION); 180 IEEE80211_STYPE_ACTION);
171 memcpy(mgmt->da, da, ETH_ALEN); 181 memcpy(mgmt->da, da, ETH_ALEN);
172 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 182 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
173 /* BSSID is left zeroed, wildcard value */ 183 /* BSSID is left zeroed, wildcard value */
174 mgmt->u.action.category = MESH_PLINK_CATEGORY; 184 mgmt->u.action.category = WLAN_CATEGORY_MESH_PLINK;
175 mgmt->u.action.u.plink_action.action_code = action; 185 mgmt->u.action.u.plink_action.action_code = action;
176 186
177 if (action == PLINK_CLOSE) 187 if (action == PLINK_CLOSE)
@@ -234,14 +244,14 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data
234 244
235 rcu_read_lock(); 245 rcu_read_lock();
236 246
237 sta = sta_info_get(local, hw_addr); 247 sta = sta_info_get(sdata, hw_addr);
238 if (!sta) { 248 if (!sta) {
249 rcu_read_unlock();
250
239 sta = mesh_plink_alloc(sdata, hw_addr, rates); 251 sta = mesh_plink_alloc(sdata, hw_addr, rates);
240 if (!sta) { 252 if (!sta)
241 rcu_read_unlock();
242 return; 253 return;
243 } 254 if (sta_info_insert_rcu(sta)) {
244 if (sta_info_insert(sta)) {
245 rcu_read_unlock(); 255 rcu_read_unlock();
246 return; 256 return;
247 } 257 }
@@ -380,10 +390,16 @@ int mesh_plink_open(struct sta_info *sta)
380 390
381void mesh_plink_block(struct sta_info *sta) 391void mesh_plink_block(struct sta_info *sta)
382{ 392{
393 struct ieee80211_sub_if_data *sdata = sta->sdata;
394 bool deactivated;
395
383 spin_lock_bh(&sta->lock); 396 spin_lock_bh(&sta->lock);
384 __mesh_plink_deactivate(sta); 397 deactivated = __mesh_plink_deactivate(sta);
385 sta->plink_state = PLINK_BLOCKED; 398 sta->plink_state = PLINK_BLOCKED;
386 spin_unlock_bh(&sta->lock); 399 spin_unlock_bh(&sta->lock);
400
401 if (deactivated)
402 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
387} 403}
388 404
389 405
@@ -396,6 +412,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
396 enum plink_event event; 412 enum plink_event event;
397 enum plink_frame_type ftype; 413 enum plink_frame_type ftype;
398 size_t baselen; 414 size_t baselen;
415 bool deactivated;
399 u8 ie_len; 416 u8 ie_len;
400 u8 *baseaddr; 417 u8 *baseaddr;
401 __le16 plid, llid, reason; 418 __le16 plid, llid, reason;
@@ -455,7 +472,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
455 472
456 rcu_read_lock(); 473 rcu_read_lock();
457 474
458 sta = sta_info_get(local, mgmt->sa); 475 sta = sta_info_get(sdata, mgmt->sa);
459 if (!sta && ftype != PLINK_OPEN) { 476 if (!sta && ftype != PLINK_OPEN) {
460 mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); 477 mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
461 rcu_read_unlock(); 478 rcu_read_unlock();
@@ -485,9 +502,11 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
485 } else if (!sta) { 502 } else if (!sta) {
486 /* ftype == PLINK_OPEN */ 503 /* ftype == PLINK_OPEN */
487 u32 rates; 504 u32 rates;
505
506 rcu_read_unlock();
507
488 if (!mesh_plink_free_count(sdata)) { 508 if (!mesh_plink_free_count(sdata)) {
489 mpl_dbg("Mesh plink error: no more free plinks\n"); 509 mpl_dbg("Mesh plink error: no more free plinks\n");
490 rcu_read_unlock();
491 return; 510 return;
492 } 511 }
493 512
@@ -495,10 +514,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
495 sta = mesh_plink_alloc(sdata, mgmt->sa, rates); 514 sta = mesh_plink_alloc(sdata, mgmt->sa, rates);
496 if (!sta) { 515 if (!sta) {
497 mpl_dbg("Mesh plink error: plink table full\n"); 516 mpl_dbg("Mesh plink error: plink table full\n");
498 rcu_read_unlock();
499 return; 517 return;
500 } 518 }
501 if (sta_info_insert(sta)) { 519 if (sta_info_insert_rcu(sta)) {
502 rcu_read_unlock(); 520 rcu_read_unlock();
503 return; 521 return;
504 } 522 }
@@ -649,8 +667,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
649 case CNF_ACPT: 667 case CNF_ACPT:
650 del_timer(&sta->plink_timer); 668 del_timer(&sta->plink_timer);
651 sta->plink_state = PLINK_ESTAB; 669 sta->plink_state = PLINK_ESTAB;
652 mesh_plink_inc_estab_count(sdata);
653 spin_unlock_bh(&sta->lock); 670 spin_unlock_bh(&sta->lock);
671 mesh_plink_inc_estab_count(sdata);
672 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
654 mpl_dbg("Mesh plink with %pM ESTABLISHED\n", 673 mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
655 sta->sta.addr); 674 sta->sta.addr);
656 break; 675 break;
@@ -682,8 +701,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
682 case OPN_ACPT: 701 case OPN_ACPT:
683 del_timer(&sta->plink_timer); 702 del_timer(&sta->plink_timer);
684 sta->plink_state = PLINK_ESTAB; 703 sta->plink_state = PLINK_ESTAB;
685 mesh_plink_inc_estab_count(sdata);
686 spin_unlock_bh(&sta->lock); 704 spin_unlock_bh(&sta->lock);
705 mesh_plink_inc_estab_count(sdata);
706 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
687 mpl_dbg("Mesh plink with %pM ESTABLISHED\n", 707 mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
688 sta->sta.addr); 708 sta->sta.addr);
689 mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, 709 mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
@@ -700,11 +720,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
700 case CLS_ACPT: 720 case CLS_ACPT:
701 reason = cpu_to_le16(MESH_CLOSE_RCVD); 721 reason = cpu_to_le16(MESH_CLOSE_RCVD);
702 sta->reason = reason; 722 sta->reason = reason;
703 __mesh_plink_deactivate(sta); 723 deactivated = __mesh_plink_deactivate(sta);
704 sta->plink_state = PLINK_HOLDING; 724 sta->plink_state = PLINK_HOLDING;
705 llid = sta->llid; 725 llid = sta->llid;
706 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); 726 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
707 spin_unlock_bh(&sta->lock); 727 spin_unlock_bh(&sta->lock);
728 if (deactivated)
729 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
708 mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, 730 mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
709 plid, reason); 731 plid, reason);
710 break; 732 break;
@@ -743,7 +765,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
743 break; 765 break;
744 default: 766 default:
745 /* should not get here, PLINK_BLOCKED is dealt with at the 767 /* should not get here, PLINK_BLOCKED is dealt with at the
746 * beggining of the function 768 * beginning of the function
747 */ 769 */
748 spin_unlock_bh(&sta->lock); 770 spin_unlock_bh(&sta->lock);
749 break; 771 break;