]> err.no Git - linux-2.6/blob - net/mac80211/mesh_plink.c
mac80211: split sta_info_add
[linux-2.6] / net / mac80211 / mesh_plink.c
1 /*
2  * Copyright (c) 2008 open80211s Ltd.
3  * Author:     Luis Carlos Cobo <luisca@cozybit.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9 #include <linux/kernel.h>
10 #include <linux/random.h>
11 #include "ieee80211_i.h"
12 #include "ieee80211_rate.h"
13 #include "mesh.h"
14
15 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
16 #define mpl_dbg(fmt, args...)   printk(KERN_DEBUG fmt, ##args)
17 #else
18 #define mpl_dbg(fmt, args...)   do { (void)(0); } while (0)
19 #endif
20
21 #define IEEE80211_FC(type, stype) cpu_to_le16(type | stype)
22 #define PLINK_GET_FRAME_SUBTYPE(p) (p)
23 #define PLINK_GET_LLID(p) (p + 1)
24 #define PLINK_GET_PLID(p) (p + 3)
25
26 #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
27                                 jiffies + HZ * t / 1000))
28
29 /* Peer link cancel reasons, all subject to ANA approval */
30 #define MESH_LINK_CANCELLED                     2
31 #define MESH_MAX_NEIGHBORS                      3
32 #define MESH_CAPABILITY_POLICY_VIOLATION        4
33 #define MESH_CLOSE_RCVD                         5
34 #define MESH_MAX_RETRIES                        6
35 #define MESH_CONFIRM_TIMEOUT                    7
36 #define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS  8
37 #define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9
38 #define MESH_SECURITY_FAILED_VERIFICATION       10
39
40 #define dot11MeshMaxRetries(s) (s->u.sta.mshcfg.dot11MeshMaxRetries)
41 #define dot11MeshRetryTimeout(s) (s->u.sta.mshcfg.dot11MeshRetryTimeout)
42 #define dot11MeshConfirmTimeout(s) (s->u.sta.mshcfg.dot11MeshConfirmTimeout)
43 #define dot11MeshHoldingTimeout(s) (s->u.sta.mshcfg.dot11MeshHoldingTimeout)
44 #define dot11MeshMaxPeerLinks(s) (s->u.sta.mshcfg.dot11MeshMaxPeerLinks)
45
46 enum plink_frame_type {
47         PLINK_OPEN = 0,
48         PLINK_CONFIRM,
49         PLINK_CLOSE
50 };
51
52 enum plink_event {
53         PLINK_UNDEFINED,
54         OPN_ACPT,
55         OPN_RJCT,
56         OPN_IGNR,
57         CNF_ACPT,
58         CNF_RJCT,
59         CNF_IGNR,
60         CLS_ACPT,
61         CLS_IGNR
62 };
63
64 static inline
65 void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
66 {
67         atomic_inc(&sdata->u.sta.mshstats.estab_plinks);
68         mesh_accept_plinks_update(sdata);
69 }
70
71 static inline
72 void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
73 {
74         atomic_dec(&sdata->u.sta.mshstats.estab_plinks);
75         mesh_accept_plinks_update(sdata);
76 }
77
78 /**
79  * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
80  *
81  * @sta: mes peer link to restart
82  *
83  * Locking: this function must be called holding sta->plink_lock
84  */
85 static inline void mesh_plink_fsm_restart(struct sta_info *sta)
86 {
87         sta->plink_state = LISTEN;
88         sta->llid = sta->plid = sta->reason = sta->plink_retries = 0;
89 }
90
91 /**
92  * mesh_plink_alloc - allocate a new mesh peer link
93  *
94  * @sdata: local mesh interface
95  * @hw_addr: hardware address (ETH_ALEN length)
96  * @rates: rates the mesh peer supports
97  *
98  * The initial state of the new plink is set to LISTEN
99  *
100  * Returns: NULL on error.
101  */
102 struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
103                                   u8 *hw_addr, u64 rates, gfp_t gfp)
104 {
105         struct ieee80211_local *local = sdata->local;
106         struct sta_info *sta;
107
108         if (compare_ether_addr(hw_addr, sdata->dev->dev_addr) == 0)
109                 /* never add ourselves as neighbours */
110                 return NULL;
111
112         if (is_multicast_ether_addr(hw_addr))
113                 return NULL;
114
115         if (local->num_sta >= MESH_MAX_PLINKS)
116                 return NULL;
117
118         sta = sta_info_alloc(sdata, hw_addr, gfp);
119         if (!sta)
120                 return NULL;
121
122         sta->plink_state = LISTEN;
123         spin_lock_init(&sta->plink_lock);
124         init_timer(&sta->plink_timer);
125         sta->flags |= WLAN_STA_AUTHORIZED;
126         sta->supp_rates[local->hw.conf.channel->band] = rates;
127
128         return sta;
129 }
130
131 /**
132  * mesh_plink_deactivate - deactivate mesh peer link
133  *
134  * @sta: mesh peer link to deactivate
135  *
136  * All mesh paths with this peer as next hop will be flushed
137  *
138  * Locking: the caller must hold sta->plink_lock
139  */
140 static void __mesh_plink_deactivate(struct sta_info *sta)
141 {
142         struct ieee80211_sub_if_data *sdata = sta->sdata;
143
144         if (sta->plink_state == ESTAB)
145                 mesh_plink_dec_estab_count(sdata);
146         sta->plink_state = BLOCKED;
147         mesh_path_flush_by_nexthop(sta);
148 }
149
150 /**
151  * __mesh_plink_deactivate - deactivate mesh peer link
152  *
153  * @sta: mesh peer link to deactivate
154  *
155  * All mesh paths with this peer as next hop will be flushed
156  */
157 void mesh_plink_deactivate(struct sta_info *sta)
158 {
159         spin_lock_bh(&sta->plink_lock);
160         __mesh_plink_deactivate(sta);
161         spin_unlock_bh(&sta->plink_lock);
162 }
163
164 static int mesh_plink_frame_tx(struct net_device *dev,
165                 enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid,
166                 __le16 reason) {
167         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
168         struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
169         struct ieee80211_mgmt *mgmt;
170         bool include_plid = false;
171         u8 *pos;
172         int ie_len;
173
174         if (!skb)
175                 return -1;
176         skb_reserve(skb, local->hw.extra_tx_headroom);
177         /* 25 is the size of the common mgmt part (24) plus the size of the
178          * common action part (1)
179          */
180         mgmt = (struct ieee80211_mgmt *)
181                 skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action));
182         memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action));
183         mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
184                                            IEEE80211_STYPE_ACTION);
185         memcpy(mgmt->da, da, ETH_ALEN);
186         memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
187         /* BSSID is left zeroed, wildcard value */
188         mgmt->u.action.category = PLINK_CATEGORY;
189         mgmt->u.action.u.plink_action.action_code = action;
190
191         if (action == PLINK_CLOSE)
192                 mgmt->u.action.u.plink_action.aux = reason;
193         else {
194                 mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0);
195                 if (action == PLINK_CONFIRM) {
196                         pos = skb_put(skb, 4);
197                         /* two-byte status code followed by two-byte AID */
198                         memset(pos, 0, 4);
199                 }
200                 mesh_mgmt_ies_add(skb, dev);
201         }
202
203         /* Add Peer Link Management element */
204         switch (action) {
205         case PLINK_OPEN:
206                 ie_len = 3;
207                 break;
208         case PLINK_CONFIRM:
209                 ie_len = 5;
210                 include_plid = true;
211                 break;
212         case PLINK_CLOSE:
213         default:
214                 if (!plid)
215                         ie_len = 5;
216                 else {
217                         ie_len = 7;
218                         include_plid = true;
219                 }
220                 break;
221         }
222
223         pos = skb_put(skb, 2 + ie_len);
224         *pos++ = WLAN_EID_PEER_LINK;
225         *pos++ = ie_len;
226         *pos++ = action;
227         memcpy(pos, &llid, 2);
228         if (include_plid) {
229                 pos += 2;
230                 memcpy(pos, &plid, 2);
231         }
232         if (action == PLINK_CLOSE) {
233                 pos += 2;
234                 memcpy(pos, &reason, 2);
235         }
236
237         ieee80211_sta_tx(dev, skb, 0);
238         return 0;
239 }
240
241 void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev,
242                            bool peer_accepting_plinks)
243 {
244         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
245         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
246         struct sta_info *sta;
247
248         rcu_read_lock();
249
250         sta = sta_info_get(local, hw_addr);
251         if (!sta) {
252                 sta = mesh_plink_alloc(sdata, hw_addr, rates, GFP_ATOMIC);
253                 if (!sta) {
254                         rcu_read_unlock();
255                         return;
256                 }
257                 if (sta_info_insert(sta)) {
258                         sta_info_destroy(sta);
259                         rcu_read_unlock();
260                         return;
261                 }
262         }
263
264         sta->last_rx = jiffies;
265         sta->supp_rates[local->hw.conf.channel->band] = rates;
266         if (peer_accepting_plinks && sta->plink_state == LISTEN &&
267                         sdata->u.sta.accepting_plinks &&
268                         sdata->u.sta.mshcfg.auto_open_plinks)
269                 mesh_plink_open(sta);
270
271         rcu_read_unlock();
272 }
273
274 static void mesh_plink_timer(unsigned long data)
275 {
276         struct sta_info *sta;
277         __le16 llid, plid, reason;
278         struct net_device *dev = NULL;
279         struct ieee80211_sub_if_data *sdata;
280 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
281         DECLARE_MAC_BUF(mac);
282 #endif
283
284         /*
285          * This STA is valid because sta_info_destroy() will
286          * del_timer_sync() this timer after having made sure
287          * it cannot be readded (by deleting the plink.)
288          */
289         sta = (struct sta_info *) data;
290
291         spin_lock_bh(&sta->plink_lock);
292         if (sta->ignore_plink_timer) {
293                 sta->ignore_plink_timer = false;
294                 spin_unlock_bh(&sta->plink_lock);
295                 return;
296         }
297         mpl_dbg("Mesh plink timer for %s fired on state %d\n",
298                         print_mac(mac, sta->addr), sta->plink_state);
299         reason = 0;
300         llid = sta->llid;
301         plid = sta->plid;
302         sdata = sta->sdata;
303         dev = sdata->dev;
304
305         switch (sta->plink_state) {
306         case OPN_RCVD:
307         case OPN_SNT:
308                 /* retry timer */
309                 if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
310                         u32 rand;
311                         mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n",
312                                         print_mac(mac, sta->addr),
313                                         sta->plink_retries, sta->plink_timeout);
314                         get_random_bytes(&rand, sizeof(u32));
315                         sta->plink_timeout = sta->plink_timeout +
316                                              rand % sta->plink_timeout;
317                         ++sta->plink_retries;
318                         mod_plink_timer(sta, sta->plink_timeout);
319                         spin_unlock_bh(&sta->plink_lock);
320                         mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
321                                             0, 0);
322                         break;
323                 }
324                 reason = cpu_to_le16(MESH_MAX_RETRIES);
325                 /* fall through on else */
326         case CNF_RCVD:
327                 /* confirm timer */
328                 if (!reason)
329                         reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT);
330                 sta->plink_state = HOLDING;
331                 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
332                 spin_unlock_bh(&sta->plink_lock);
333                 mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid,
334                                     reason);
335                 break;
336         case HOLDING:
337                 /* holding timer */
338                 del_timer(&sta->plink_timer);
339                 mesh_plink_fsm_restart(sta);
340                 spin_unlock_bh(&sta->plink_lock);
341                 break;
342         default:
343                 spin_unlock_bh(&sta->plink_lock);
344                 break;
345         }
346 }
347
348 static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
349 {
350         sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
351         sta->plink_timer.data = (unsigned long) sta;
352         sta->plink_timer.function = mesh_plink_timer;
353         sta->plink_timeout = timeout;
354         add_timer(&sta->plink_timer);
355 }
356
357 int mesh_plink_open(struct sta_info *sta)
358 {
359         __le16 llid;
360         struct ieee80211_sub_if_data *sdata = sta->sdata;
361 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
362         DECLARE_MAC_BUF(mac);
363 #endif
364
365         spin_lock_bh(&sta->plink_lock);
366         get_random_bytes(&llid, 2);
367         sta->llid = llid;
368         if (sta->plink_state != LISTEN) {
369                 spin_unlock_bh(&sta->plink_lock);
370                 return -EBUSY;
371         }
372         sta->plink_state = OPN_SNT;
373         mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
374         spin_unlock_bh(&sta->plink_lock);
375         mpl_dbg("Mesh plink: starting establishment with %s\n",
376                 print_mac(mac, sta->addr));
377
378         return mesh_plink_frame_tx(sdata->dev, PLINK_OPEN,
379                                    sta->addr, llid, 0, 0);
380 }
381
382 void mesh_plink_block(struct sta_info *sta)
383 {
384 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
385         DECLARE_MAC_BUF(mac);
386 #endif
387
388         spin_lock_bh(&sta->plink_lock);
389         __mesh_plink_deactivate(sta);
390         sta->plink_state = BLOCKED;
391         spin_unlock_bh(&sta->plink_lock);
392 }
393
394 int mesh_plink_close(struct sta_info *sta)
395 {
396         struct ieee80211_sub_if_data *sdata = sta->sdata;
397         int llid, plid, reason;
398 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
399         DECLARE_MAC_BUF(mac);
400 #endif
401
402         mpl_dbg("Mesh plink: closing link with %s\n",
403                         print_mac(mac, sta->addr));
404         spin_lock_bh(&sta->plink_lock);
405         sta->reason = cpu_to_le16(MESH_LINK_CANCELLED);
406         reason = sta->reason;
407
408         if (sta->plink_state == LISTEN || sta->plink_state == BLOCKED) {
409                 mesh_plink_fsm_restart(sta);
410                 spin_unlock_bh(&sta->plink_lock);
411                 return 0;
412         } else if (sta->plink_state == ESTAB) {
413                 __mesh_plink_deactivate(sta);
414                 /* The timer should not be running */
415                 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
416         } else if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)))
417                 sta->ignore_plink_timer = true;
418
419         sta->plink_state = HOLDING;
420         llid = sta->llid;
421         plid = sta->plid;
422         spin_unlock_bh(&sta->plink_lock);
423         mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid,
424                             plid, reason);
425         return 0;
426 }
427
428 void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
429                          size_t len, struct ieee80211_rx_status *rx_status)
430 {
431         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
432         struct ieee80211_local *local = sdata->local;
433         struct ieee802_11_elems elems;
434         struct sta_info *sta;
435         enum plink_event event;
436         enum plink_frame_type ftype;
437         size_t baselen;
438         u8 ie_len;
439         u8 *baseaddr;
440         __le16 plid, llid, reason;
441 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
442         DECLARE_MAC_BUF(mac);
443 #endif
444
445         if (is_multicast_ether_addr(mgmt->da)) {
446                 mpl_dbg("Mesh plink: ignore frame from multicast address");
447                 return;
448         }
449
450         baseaddr = mgmt->u.action.u.plink_action.variable;
451         baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt;
452         if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) {
453                 baseaddr += 4;
454                 baselen -= 4;
455         }
456         ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
457         if (!elems.peer_link) {
458                 mpl_dbg("Mesh plink: missing necessary peer link ie\n");
459                 return;
460         }
461
462         ftype = *((u8 *)PLINK_GET_FRAME_SUBTYPE(elems.peer_link));
463         ie_len = elems.peer_link_len;
464         if ((ftype == PLINK_OPEN && ie_len != 3) ||
465             (ftype == PLINK_CONFIRM && ie_len != 5) ||
466             (ftype == PLINK_CLOSE && ie_len != 5 && ie_len != 7)) {
467                 mpl_dbg("Mesh plink: incorrect plink ie length\n");
468                 return;
469         }
470
471         if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) {
472                 mpl_dbg("Mesh plink: missing necessary ie\n");
473                 return;
474         }
475         /* Note the lines below are correct, the llid in the frame is the plid
476          * from the point of view of this host.
477          */
478         memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2);
479         if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 7))
480                 memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2);
481
482         rcu_read_lock();
483
484         sta = sta_info_get(local, mgmt->sa);
485         if (!sta && ftype != PLINK_OPEN) {
486                 mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
487                 rcu_read_unlock();
488                 return;
489         }
490
491         if (sta && sta->plink_state == BLOCKED) {
492                 rcu_read_unlock();
493                 return;
494         }
495
496         /* Now we will figure out the appropriate event... */
497         event = PLINK_UNDEFINED;
498         if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, dev))) {
499                 switch (ftype) {
500                 case PLINK_OPEN:
501                         event = OPN_RJCT;
502                         break;
503                 case PLINK_CONFIRM:
504                         event = CNF_RJCT;
505                         break;
506                 case PLINK_CLOSE:
507                         /* avoid warning */
508                         break;
509                 }
510                 spin_lock_bh(&sta->plink_lock);
511         } else if (!sta) {
512                 /* ftype == PLINK_OPEN */
513                 u64 rates;
514                 if (!mesh_plink_free_count(sdata)) {
515                         mpl_dbg("Mesh plink error: no more free plinks\n");
516                         rcu_read_unlock();
517                         return;
518                 }
519
520                 rates = ieee80211_sta_get_rates(local, &elems, rx_status->band);
521                 sta = mesh_plink_alloc(sdata, mgmt->sa, rates, GFP_ATOMIC);
522                 if (!sta) {
523                         mpl_dbg("Mesh plink error: plink table full\n");
524                         rcu_read_unlock();
525                         return;
526                 }
527                 if (sta_info_insert(sta)) {
528                         sta_info_destroy(sta);
529                         rcu_read_unlock();
530                         return;
531                 }
532                 event = OPN_ACPT;
533                 spin_lock_bh(&sta->plink_lock);
534         } else {
535                 spin_lock_bh(&sta->plink_lock);
536                 switch (ftype) {
537                 case PLINK_OPEN:
538                         if (!mesh_plink_free_count(sdata) ||
539                             (sta->plid && sta->plid != plid))
540                                 event = OPN_IGNR;
541                         else
542                                 event = OPN_ACPT;
543                         break;
544                 case PLINK_CONFIRM:
545                         if (!mesh_plink_free_count(sdata) ||
546                             (sta->llid != llid || sta->plid != plid))
547                                 event = CNF_IGNR;
548                         else
549                                 event = CNF_ACPT;
550                         break;
551                 case PLINK_CLOSE:
552                         if (sta->plink_state == ESTAB)
553                                 /* Do not check for llid or plid. This does not
554                                  * follow the standard but since multiple plinks
555                                  * per sta are not supported, it is necessary in
556                                  * order to avoid a livelock when MP A sees an
557                                  * establish peer link to MP B but MP B does not
558                                  * see it. This can be caused by a timeout in
559                                  * B's peer link establishment or B beign
560                                  * restarted.
561                                  */
562                                 event = CLS_ACPT;
563                         else if (sta->plid != plid)
564                                 event = CLS_IGNR;
565                         else if (ie_len == 7 && sta->llid != llid)
566                                 event = CLS_IGNR;
567                         else
568                                 event = CLS_ACPT;
569                         break;
570                 default:
571                         mpl_dbg("Mesh plink: unknown frame subtype\n");
572                         spin_unlock_bh(&sta->plink_lock);
573                         rcu_read_unlock();
574                         return;
575                 }
576         }
577
578         mpl_dbg("Mesh plink (peer, state, llid, plid, event): %s %d %d %d %d\n",
579                         print_mac(mac, mgmt->sa), sta->plink_state,
580                         __le16_to_cpu(sta->llid), __le16_to_cpu(sta->plid),
581                         event);
582         reason = 0;
583         switch (sta->plink_state) {
584                 /* spin_unlock as soon as state is updated at each case */
585         case LISTEN:
586                 switch (event) {
587                 case CLS_ACPT:
588                         mesh_plink_fsm_restart(sta);
589                         spin_unlock_bh(&sta->plink_lock);
590                         break;
591                 case OPN_ACPT:
592                         sta->plink_state = OPN_RCVD;
593                         sta->plid = plid;
594                         get_random_bytes(&llid, 2);
595                         sta->llid = llid;
596                         mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
597                         spin_unlock_bh(&sta->plink_lock);
598                         mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
599                                             0, 0);
600                         mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr,
601                                             llid, plid, 0);
602                         break;
603                 default:
604                         spin_unlock_bh(&sta->plink_lock);
605                         break;
606                 }
607                 break;
608
609         case OPN_SNT:
610                 switch (event) {
611                 case OPN_RJCT:
612                 case CNF_RJCT:
613                         reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
614                 case CLS_ACPT:
615                         if (!reason)
616                                 reason = cpu_to_le16(MESH_CLOSE_RCVD);
617                         sta->reason = reason;
618                         sta->plink_state = HOLDING;
619                         if (!mod_plink_timer(sta,
620                                              dot11MeshHoldingTimeout(sdata)))
621                                 sta->ignore_plink_timer = true;
622
623                         llid = sta->llid;
624                         spin_unlock_bh(&sta->plink_lock);
625                         mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
626                                             plid, reason);
627                         break;
628                 case OPN_ACPT:
629                         /* retry timer is left untouched */
630                         sta->plink_state = OPN_RCVD;
631                         sta->plid = plid;
632                         llid = sta->llid;
633                         spin_unlock_bh(&sta->plink_lock);
634                         mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
635                                             plid, 0);
636                         break;
637                 case CNF_ACPT:
638                         sta->plink_state = CNF_RCVD;
639                         if (!mod_plink_timer(sta,
640                                              dot11MeshConfirmTimeout(sdata)))
641                                 sta->ignore_plink_timer = true;
642
643                         spin_unlock_bh(&sta->plink_lock);
644                         break;
645                 default:
646                         spin_unlock_bh(&sta->plink_lock);
647                         break;
648                 }
649                 break;
650
651         case OPN_RCVD:
652                 switch (event) {
653                 case OPN_RJCT:
654                 case CNF_RJCT:
655                         reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
656                 case CLS_ACPT:
657                         if (!reason)
658                                 reason = cpu_to_le16(MESH_CLOSE_RCVD);
659                         sta->reason = reason;
660                         sta->plink_state = HOLDING;
661                         if (!mod_plink_timer(sta,
662                                              dot11MeshHoldingTimeout(sdata)))
663                                 sta->ignore_plink_timer = true;
664
665                         llid = sta->llid;
666                         spin_unlock_bh(&sta->plink_lock);
667                         mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
668                                             plid, reason);
669                         break;
670                 case OPN_ACPT:
671                         llid = sta->llid;
672                         spin_unlock_bh(&sta->plink_lock);
673                         mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
674                                             plid, 0);
675                         break;
676                 case CNF_ACPT:
677                         del_timer(&sta->plink_timer);
678                         sta->plink_state = ESTAB;
679                         mesh_plink_inc_estab_count(sdata);
680                         spin_unlock_bh(&sta->plink_lock);
681                         mpl_dbg("Mesh plink with %s ESTABLISHED\n",
682                                         print_mac(mac, sta->addr));
683                         break;
684                 default:
685                         spin_unlock_bh(&sta->plink_lock);
686                         break;
687                 }
688                 break;
689
690         case CNF_RCVD:
691                 switch (event) {
692                 case OPN_RJCT:
693                 case CNF_RJCT:
694                         reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
695                 case CLS_ACPT:
696                         if (!reason)
697                                 reason = cpu_to_le16(MESH_CLOSE_RCVD);
698                         sta->reason = reason;
699                         sta->plink_state = HOLDING;
700                         if (!mod_plink_timer(sta,
701                                              dot11MeshHoldingTimeout(sdata)))
702                                 sta->ignore_plink_timer = true;
703
704                         llid = sta->llid;
705                         spin_unlock_bh(&sta->plink_lock);
706                         mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
707                                             plid, reason);
708                         break;
709                 case OPN_ACPT:
710                         del_timer(&sta->plink_timer);
711                         sta->plink_state = ESTAB;
712                         mesh_plink_inc_estab_count(sdata);
713                         spin_unlock_bh(&sta->plink_lock);
714                         mpl_dbg("Mesh plink with %s ESTABLISHED\n",
715                                         print_mac(mac, sta->addr));
716                         mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
717                                             plid, 0);
718                         break;
719                 default:
720                         spin_unlock_bh(&sta->plink_lock);
721                         break;
722                 }
723                 break;
724
725         case ESTAB:
726                 switch (event) {
727                 case CLS_ACPT:
728                         reason = cpu_to_le16(MESH_CLOSE_RCVD);
729                         sta->reason = reason;
730                         __mesh_plink_deactivate(sta);
731                         sta->plink_state = HOLDING;
732                         llid = sta->llid;
733                         mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
734                         spin_unlock_bh(&sta->plink_lock);
735                         mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
736                                             plid, reason);
737                         break;
738                 case OPN_ACPT:
739                         llid = sta->llid;
740                         spin_unlock_bh(&sta->plink_lock);
741                         mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
742                                             plid, 0);
743                         break;
744                 default:
745                         spin_unlock_bh(&sta->plink_lock);
746                         break;
747                 }
748                 break;
749         case HOLDING:
750                 switch (event) {
751                 case CLS_ACPT:
752                         if (del_timer(&sta->plink_timer))
753                                 sta->ignore_plink_timer = 1;
754                         mesh_plink_fsm_restart(sta);
755                         spin_unlock_bh(&sta->plink_lock);
756                         break;
757                 case OPN_ACPT:
758                 case CNF_ACPT:
759                 case OPN_RJCT:
760                 case CNF_RJCT:
761                         llid = sta->llid;
762                         reason = sta->reason;
763                         spin_unlock_bh(&sta->plink_lock);
764                         mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
765                                             plid, reason);
766                         break;
767                 default:
768                         spin_unlock_bh(&sta->plink_lock);
769                 }
770                 break;
771         default:
772                 /* should not get here, BLOCKED is dealt with at the beggining
773                  * of the function
774                  */
775                 spin_unlock_bh(&sta->plink_lock);
776                 break;
777         }
778
779         rcu_read_unlock();
780 }