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