mesh_plink.c 26.3 KB
Newer Older
1
/*
R
Rui Paulo 已提交
2
 * Copyright (c) 2008, 2009 open80211s Ltd.
3 4 5 6 7 8
 * Author:     Luis Carlos Cobo <luisca@cozybit.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
9
#include <linux/gfp.h>
J
Johannes Berg 已提交
10 11
#include <linux/kernel.h>
#include <linux/random.h>
12
#include "ieee80211_i.h"
J
Johannes Berg 已提交
13
#include "rate.h"
14 15
#include "mesh.h"

16 17
#define PLINK_GET_LLID(p) (p + 2)
#define PLINK_GET_PLID(p) (p + 4)
18 19 20 21

#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
				jiffies + HZ * t / 1000))

22 23
/* We only need a valid sta if user configured a minimum rssi_threshold. */
#define rssi_threshold_check(sta, sdata) \
24
		(sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\
25 26
		(sta && (s8) -ewma_read(&sta->avg_signal) > \
		sdata->u.mesh.mshcfg.rssi_threshold))
27

28 29 30 31 32 33 34 35 36 37 38 39
enum plink_event {
	PLINK_UNDEFINED,
	OPN_ACPT,
	OPN_RJCT,
	OPN_IGNR,
	CNF_ACPT,
	CNF_RJCT,
	CNF_IGNR,
	CLS_ACPT,
	CLS_IGNR
};

40 41 42 43
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
		enum ieee80211_self_protected_actioncode action,
		u8 *da, __le16 llid, __le16 plid, __le16 reason);

44 45 46
/**
 * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
 *
R
Rui Paulo 已提交
47
 * @sta: mesh peer link to restart
48
 *
49
 * Locking: this function must be called holding sta->lock
50 51 52
 */
static inline void mesh_plink_fsm_restart(struct sta_info *sta)
{
53
	sta->plink_state = NL80211_PLINK_LISTEN;
54 55
	sta->llid = sta->plid = sta->reason = 0;
	sta->plink_retries = 0;
56 57
}

58
/**
59
 * mesh_set_ht_prot_mode - set correct HT protection mode
60
 *
61 62 63 64 65 66
 * Section 9.23.3.5 of IEEE 80211-2012 describes the protection rules for HT
 * mesh STA in a MBSS. Three HT protection modes are supported for now, non-HT
 * mixed mode, 20MHz-protection and no-protection mode. non-HT mixed mode is
 * selected if any non-HT peers are present in our MBSS.  20MHz-protection mode
 * is selected if all peers in our 20/40MHz MBSS support HT and atleast one
 * HT20 peer is present. Otherwise no-protection mode is selected.
67 68 69 70 71 72 73 74 75
 */
static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;
	struct sta_info *sta;
	u32 changed = 0;
	u16 ht_opmode;
	bool non_ht_sta = false, ht20_sta = false;

76
	if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
77 78 79 80
		return 0;

	rcu_read_lock();
	list_for_each_entry_rcu(sta, &local->sta_list, list) {
81 82 83 84
		if (sdata != sta->sdata ||
		    sta->plink_state != NL80211_PLINK_ESTAB)
			continue;

85 86
		switch (sta->ch_width) {
		case NL80211_CHAN_WIDTH_20_NOHT:
J
Johannes Berg 已提交
87 88
			mpl_dbg(sdata,
				"mesh_plink %pM: nonHT sta (%pM) is present\n",
89 90 91
				sdata->vif.addr, sta->sta.addr);
			non_ht_sta = true;
			goto out;
92
		case NL80211_CHAN_WIDTH_20:
J
Johannes Berg 已提交
93 94
			mpl_dbg(sdata,
				"mesh_plink %pM: HT20 sta (%pM) is present\n",
95 96 97 98
				sdata->vif.addr, sta->sta.addr);
			ht20_sta = true;
		default:
			break;
99 100 101 102 103 104 105
		}
	}
out:
	rcu_read_unlock();

	if (non_ht_sta)
		ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED;
106
	else if (ht20_sta &&
107
		 sdata->vif.bss_conf.chandef.width > NL80211_CHAN_WIDTH_20)
108 109 110 111 112 113
		ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ;
	else
		ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE;

	if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
		sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
114
		sdata->u.mesh.mshcfg.ht_opmode = ht_opmode;
115
		changed = BSS_CHANGED_HT;
J
Johannes Berg 已提交
116 117
		mpl_dbg(sdata,
			"mesh_plink %pM: protection mode changed to %d\n",
118 119 120 121 122 123
			sdata->vif.addr, ht_opmode);
	}

	return changed;
}

124
/**
125
 * __mesh_plink_deactivate - deactivate mesh peer link
126 127 128 129
 *
 * @sta: mesh peer link to deactivate
 *
 * All mesh paths with this peer as next hop will be flushed
130
 * Returns beacon changed flag if the beacon content changed.
131
 *
132
 * Locking: the caller must hold sta->lock
133
 */
134
static u32 __mesh_plink_deactivate(struct sta_info *sta)
135
{
136
	struct ieee80211_sub_if_data *sdata = sta->sdata;
137
	u32 changed = 0;
138

139 140
	if (sta->plink_state == NL80211_PLINK_ESTAB)
		changed = mesh_plink_dec_estab_count(sdata);
141
	sta->plink_state = NL80211_PLINK_BLOCKED;
142
	mesh_path_flush_by_nexthop(sta);
143

144
	return changed;
145 146
}

J
Johannes Berg 已提交
147
/**
148
 * mesh_plink_deactivate - deactivate mesh peer link
J
Johannes Berg 已提交
149 150 151 152 153 154 155
 *
 * @sta: mesh peer link to deactivate
 *
 * All mesh paths with this peer as next hop will be flushed
 */
void mesh_plink_deactivate(struct sta_info *sta)
{
156
	struct ieee80211_sub_if_data *sdata = sta->sdata;
157
	u32 changed;
158

159
	spin_lock_bh(&sta->lock);
160
	changed = __mesh_plink_deactivate(sta);
161 162 163 164
	sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED);
	mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
			    sta->sta.addr, sta->llid, sta->plid,
			    sta->reason);
165
	spin_unlock_bh(&sta->lock);
166

167
	ieee80211_bss_info_change_notify(sdata, changed);
J
Johannes Berg 已提交
168 169
}

170
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
171 172
		enum ieee80211_self_protected_actioncode action,
		u8 *da, __le16 llid, __le16 plid, __le16 reason) {
173
	struct ieee80211_local *local = sdata->local;
174
	struct sk_buff *skb;
175
	struct ieee80211_tx_info *info;
176 177
	struct ieee80211_mgmt *mgmt;
	bool include_plid = false;
178
	u16 peering_proto = 0;
179 180 181
	u8 *pos, ie_len = 4;
	int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
		      sizeof(mgmt->u.action.u.self_prot);
182
	int err = -ENOMEM;
183

184
	skb = dev_alloc_skb(local->tx_headroom +
185 186 187 188 189 190 191
			    hdr_len +
			    2 + /* capability info */
			    2 + /* AID */
			    2 + 8 + /* supported rates */
			    2 + (IEEE80211_MAX_SUPP_RATES - 8) +
			    2 + sdata->u.mesh.mesh_id_len +
			    2 + sizeof(struct ieee80211_meshconf_ie) +
192
			    2 + sizeof(struct ieee80211_ht_cap) +
193
			    2 + sizeof(struct ieee80211_ht_operation) +
194 195
			    2 + 8 + /* peering IE */
			    sdata->u.mesh.ie_len);
196 197
	if (!skb)
		return -1;
198
	info = IEEE80211_SKB_CB(skb);
199
	skb_reserve(skb, local->tx_headroom);
200 201
	mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
	memset(mgmt, 0, hdr_len);
202 203
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
					  IEEE80211_STYPE_ACTION);
204
	memcpy(mgmt->da, da, ETH_ALEN);
205
	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
206
	memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
207 208
	mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED;
	mgmt->u.action.u.self_prot.action_code = action;
209

210
	if (action != WLAN_SP_MESH_PEERING_CLOSE) {
J
Johannes Berg 已提交
211 212
		enum ieee80211_band band = ieee80211_get_sdata_band(sdata);

213 214 215
		/* capability info */
		pos = skb_put(skb, 2);
		memset(pos, 0, 2);
216
		if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
217 218
			/* AID */
			pos = skb_put(skb, 2);
219
			memcpy(pos + 2, &plid, 2);
220
		}
J
Johannes Berg 已提交
221 222
		if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
		    ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
223 224 225
		    mesh_add_rsn_ie(skb, sdata) ||
		    mesh_add_meshid_ie(skb, sdata) ||
		    mesh_add_meshconf_ie(skb, sdata))
226
			goto free;
227
	} else {	/* WLAN_SP_MESH_PEERING_CLOSE */
228
		info->flags |= IEEE80211_TX_CTL_NO_ACK;
229
		if (mesh_add_meshid_ie(skb, sdata))
230
			goto free;
231 232
	}

233
	/* Add Mesh Peering Management element */
234
	switch (action) {
235
	case WLAN_SP_MESH_PEERING_OPEN:
236
		break;
237
	case WLAN_SP_MESH_PEERING_CONFIRM:
238
		ie_len += 2;
239 240
		include_plid = true;
		break;
241
	case WLAN_SP_MESH_PEERING_CLOSE:
242 243
		if (plid) {
			ie_len += 2;
244 245
			include_plid = true;
		}
246
		ie_len += 2;	/* reason code */
247
		break;
248
	default:
249 250
		err = -EINVAL;
		goto free;
251 252
	}

253
	if (WARN_ON(skb_tailroom(skb) < 2 + ie_len))
254
		goto free;
255

256
	pos = skb_put(skb, 2 + ie_len);
257
	*pos++ = WLAN_EID_PEER_MGMT;
258
	*pos++ = ie_len;
259 260
	memcpy(pos, &peering_proto, 2);
	pos += 2;
261
	memcpy(pos, &llid, 2);
262
	pos += 2;
263 264
	if (include_plid) {
		memcpy(pos, &plid, 2);
265
		pos += 2;
266
	}
267
	if (action == WLAN_SP_MESH_PEERING_CLOSE) {
268
		memcpy(pos, &reason, 2);
269
		pos += 2;
270
	}
271 272 273

	if (action != WLAN_SP_MESH_PEERING_CLOSE) {
		if (mesh_add_ht_cap_ie(skb, sdata) ||
274
		    mesh_add_ht_oper_ie(skb, sdata))
275
			goto free;
276 277
	}

278
	if (mesh_add_vendor_ies(skb, sdata))
279
		goto free;
280

281
	ieee80211_tx_skb(sdata, skb);
282
	return 0;
283 284 285
free:
	kfree_skb(skb);
	return err;
286 287
}

288 289 290
static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
			       struct sta_info *sta,
			       struct ieee802_11_elems *elems, bool insert)
291
{
292
	struct ieee80211_local *local = sdata->local;
J
Johannes Berg 已提交
293
	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
294
	struct ieee80211_supported_band *sband;
295
	u32 rates, basic_rates = 0, changed = 0;
296

297 298
	sband = local->hw.wiphy->bands[band];
	rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates);
299

300
	spin_lock_bh(&sta->lock);
301
	sta->last_rx = jiffies;
302 303 304 305

	/* rates and capabilities don't change during peering */
	if (sta->plink_state == NL80211_PLINK_ESTAB)
		goto out;
306

307 308
	if (sta->sta.supp_rates[band] != rates)
		changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
309
	sta->sta.supp_rates[band] = rates;
310
	if (elems->ht_cap_elem &&
311
	    sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
312 313 314 315 316 317
		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
						  elems->ht_cap_elem,
						  &sta->sta.ht_cap);
	else
		memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap));

318
	if (elems->ht_operation) {
319 320
		struct cfg80211_chan_def chandef;

321 322 323 324
		if (!(elems->ht_operation->ht_param &
		      IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
			sta->sta.ht_cap.cap &=
					    ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
325 326
		ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
					     elems->ht_operation, &chandef);
327 328
		if (sta->ch_width != chandef.width)
			changed |= IEEE80211_RC_BW_CHANGED;
329
		sta->ch_width = chandef.width;
330
	}
331

332 333
	if (insert)
		rate_control_rate_init(sta);
334 335
	else
		rate_control_rate_update(local, sband, sta, changed);
336
out:
337
	spin_unlock_bh(&sta->lock);
338 339 340 341 342 343
}

static struct sta_info *
__mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr)
{
	struct sta_info *sta;
344

345
	if (sdata->local->num_sta >= MESH_MAX_PLINKS)
346 347
		return NULL;

348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
	sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
	if (!sta)
		return NULL;

	sta->plink_state = NL80211_PLINK_LISTEN;
	init_timer(&sta->plink_timer);

	sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
	sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
	sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);

	set_sta_flag(sta, WLAN_STA_WME);

	return sta;
}

static struct sta_info *
mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr,
		    struct ieee802_11_elems *elems)
{
	struct sta_info *sta = NULL;

	/* Userspace handles peer allocation when security is enabled */
	if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)
		cfg80211_notify_new_peer_candidate(sdata->dev, addr,
						   elems->ie_start,
						   elems->total_len,
						   GFP_KERNEL);
	else
		sta = __mesh_sta_info_alloc(sdata, addr);

379 380 381
	return sta;
}

382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
/*
 * mesh_sta_info_get - return mesh sta info entry for @addr.
 *
 * @sdata: local meshif
 * @addr: peer's address
 * @elems: IEs from beacon or mesh peering frame.
 *
 * Return existing or newly allocated sta_info under RCU read lock.
 * (re)initialize with given IEs.
 */
static struct sta_info *
mesh_sta_info_get(struct ieee80211_sub_if_data *sdata,
		  u8 *addr, struct ieee802_11_elems *elems) __acquires(RCU)
{
	struct sta_info *sta = NULL;

	rcu_read_lock();
	sta = sta_info_get(sdata, addr);
	if (sta) {
		mesh_sta_info_init(sdata, sta, elems, false);
	} else {
		rcu_read_unlock();
		/* can't run atomic */
		sta = mesh_sta_info_alloc(sdata, addr, elems);
		if (!sta) {
			rcu_read_lock();
			return NULL;
		}

411 412
		mesh_sta_info_init(sdata, sta, elems, true);

413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
		if (sta_info_insert_rcu(sta))
			return NULL;
	}

	return sta;
}

/*
 * mesh_neighbour_update - update or initialize new mesh neighbor.
 *
 * @sdata: local meshif
 * @addr: peer's address
 * @elems: IEs from beacon or mesh peering frame
 *
 * Initiates peering if appropriate.
 */
429 430
void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
			   u8 *hw_addr,
431 432 433 434
			   struct ieee802_11_elems *elems)
{
	struct sta_info *sta;

435
	sta = mesh_sta_info_get(sdata, hw_addr, elems);
436 437 438
	if (!sta)
		goto out;

439
	if (mesh_peer_accepts_plinks(elems) &&
440 441 442 443
	    sta->plink_state == NL80211_PLINK_LISTEN &&
	    sdata->u.mesh.accepting_plinks &&
	    sdata->u.mesh.mshcfg.auto_open_plinks &&
	    rssi_threshold_check(sta, sdata))
444 445
		mesh_plink_open(sta);

446
out:
447
	rcu_read_unlock();
448 449 450 451 452 453 454
}

static void mesh_plink_timer(unsigned long data)
{
	struct sta_info *sta;
	__le16 llid, plid, reason;
	struct ieee80211_sub_if_data *sdata;
455
	struct mesh_config *mshcfg;
456

457 458 459 460 461
	/*
	 * This STA is valid because sta_info_destroy() will
	 * del_timer_sync() this timer after having made sure
	 * it cannot be readded (by deleting the plink.)
	 */
462 463
	sta = (struct sta_info *) data;

464 465 466 467 468
	if (sta->sdata->local->quiescing) {
		sta->plink_timer_was_running = true;
		return;
	}

469
	spin_lock_bh(&sta->lock);
470 471
	if (sta->ignore_plink_timer) {
		sta->ignore_plink_timer = false;
472
		spin_unlock_bh(&sta->lock);
473 474
		return;
	}
J
Johannes Berg 已提交
475 476
	mpl_dbg(sta->sdata,
		"Mesh plink timer for %pM fired on state %d\n",
477
		sta->sta.addr, sta->plink_state);
478 479 480
	reason = 0;
	llid = sta->llid;
	plid = sta->plid;
481
	sdata = sta->sdata;
482
	mshcfg = &sdata->u.mesh.mshcfg;
483 484

	switch (sta->plink_state) {
485 486
	case NL80211_PLINK_OPN_RCVD:
	case NL80211_PLINK_OPN_SNT:
487
		/* retry timer */
488
		if (sta->plink_retries < mshcfg->dot11MeshMaxRetries) {
489
			u32 rand;
J
Johannes Berg 已提交
490 491
			mpl_dbg(sta->sdata,
				"Mesh plink for %pM (retry, timeout): %d %d\n",
492 493
				sta->sta.addr, sta->plink_retries,
				sta->plink_timeout);
494 495 496 497
			get_random_bytes(&rand, sizeof(u32));
			sta->plink_timeout = sta->plink_timeout +
					     rand % sta->plink_timeout;
			++sta->plink_retries;
498
			mod_plink_timer(sta, sta->plink_timeout);
499
			spin_unlock_bh(&sta->lock);
500 501
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
					    sta->sta.addr, llid, 0, 0);
502 503
			break;
		}
504
		reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES);
505
		/* fall through on else */
506
	case NL80211_PLINK_CNF_RCVD:
507 508
		/* confirm timer */
		if (!reason)
509
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
510
		sta->plink_state = NL80211_PLINK_HOLDING;
511
		mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
512
		spin_unlock_bh(&sta->lock);
513 514
		mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
				    sta->sta.addr, llid, plid, reason);
515
		break;
516
	case NL80211_PLINK_HOLDING:
517
		/* holding timer */
518
		del_timer(&sta->plink_timer);
519
		mesh_plink_fsm_restart(sta);
520
		spin_unlock_bh(&sta->lock);
521 522
		break;
	default:
523
		spin_unlock_bh(&sta->lock);
524 525 526 527
		break;
	}
}

528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
#ifdef CONFIG_PM
void mesh_plink_quiesce(struct sta_info *sta)
{
	if (del_timer_sync(&sta->plink_timer))
		sta->plink_timer_was_running = true;
}

void mesh_plink_restart(struct sta_info *sta)
{
	if (sta->plink_timer_was_running) {
		add_timer(&sta->plink_timer);
		sta->plink_timer_was_running = false;
	}
}
#endif

544 545 546 547 548 549 550 551 552 553 554 555
static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
{
	sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
	sta->plink_timer.data = (unsigned long) sta;
	sta->plink_timer.function = mesh_plink_timer;
	sta->plink_timeout = timeout;
	add_timer(&sta->plink_timer);
}

int mesh_plink_open(struct sta_info *sta)
{
	__le16 llid;
556
	struct ieee80211_sub_if_data *sdata = sta->sdata;
557

J
Johannes Berg 已提交
558
	if (!test_sta_flag(sta, WLAN_STA_AUTH))
559 560
		return -EPERM;

561
	spin_lock_bh(&sta->lock);
562 563
	get_random_bytes(&llid, 2);
	sta->llid = llid;
564 565
	if (sta->plink_state != NL80211_PLINK_LISTEN &&
	    sta->plink_state != NL80211_PLINK_BLOCKED) {
566
		spin_unlock_bh(&sta->lock);
567 568
		return -EBUSY;
	}
569
	sta->plink_state = NL80211_PLINK_OPN_SNT;
570
	mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout);
571
	spin_unlock_bh(&sta->lock);
J
Johannes Berg 已提交
572 573
	mpl_dbg(sdata,
		"Mesh plink: starting establishment with %pM\n",
574
		sta->sta.addr);
575

576
	return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
577
				   sta->sta.addr, llid, 0, 0);
578 579 580 581
}

void mesh_plink_block(struct sta_info *sta)
{
582
	struct ieee80211_sub_if_data *sdata = sta->sdata;
583
	u32 changed;
584

585
	spin_lock_bh(&sta->lock);
586
	changed = __mesh_plink_deactivate(sta);
587
	sta->plink_state = NL80211_PLINK_BLOCKED;
588
	spin_unlock_bh(&sta->lock);
589

590
	ieee80211_bss_info_change_notify(sdata, changed);
591 592 593
}


594
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
595 596
			 size_t len, struct ieee80211_rx_status *rx_status)
{
597
	struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
598 599 600
	struct ieee802_11_elems elems;
	struct sta_info *sta;
	enum plink_event event;
601
	enum ieee80211_self_protected_actioncode ftype;
602
	size_t baselen;
603
	bool matches_local = true;
604 605
	u8 ie_len;
	u8 *baseaddr;
606
	u32 changed = 0;
607
	__le16 plid, llid, reason;
608
	static const char *mplstates[] = {
609 610 611 612 613 614 615
		[NL80211_PLINK_LISTEN] = "LISTEN",
		[NL80211_PLINK_OPN_SNT] = "OPN-SNT",
		[NL80211_PLINK_OPN_RCVD] = "OPN-RCVD",
		[NL80211_PLINK_CNF_RCVD] = "CNF_RCVD",
		[NL80211_PLINK_ESTAB] = "ESTAB",
		[NL80211_PLINK_HOLDING] = "HOLDING",
		[NL80211_PLINK_BLOCKED] = "BLOCKED"
616
	};
617

618 619 620 621
	/* need action_code, aux */
	if (len < IEEE80211_MIN_ACTION_SIZE + 3)
		return;

622
	if (is_multicast_ether_addr(mgmt->da)) {
J
Johannes Berg 已提交
623 624
		mpl_dbg(sdata,
			"Mesh plink: ignore frame from multicast address\n");
625 626 627
		return;
	}

628 629 630
	baseaddr = mgmt->u.action.u.self_prot.variable;
	baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt;
	if (mgmt->u.action.u.self_prot.action_code ==
631
						WLAN_SP_MESH_PEERING_CONFIRM) {
632
		baseaddr += 4;
633
		baselen += 4;
634 635
	}
	ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
636
	if (!elems.peering) {
J
Johannes Berg 已提交
637 638
		mpl_dbg(sdata,
			"Mesh plink: missing necessary peer link ie\n");
639 640
		return;
	}
641 642
	if (elems.rsn_len &&
			sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
J
Johannes Berg 已提交
643 644
		mpl_dbg(sdata,
			"Mesh plink: can't establish link with secure peer\n");
645 646
		return;
	}
647

648 649 650 651 652 653
	ftype = mgmt->u.action.u.self_prot.action_code;
	ie_len = elems.peering_len;
	if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) ||
	    (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) ||
	    (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6
							&& ie_len != 8)) {
J
Johannes Berg 已提交
654 655 656
		mpl_dbg(sdata,
			"Mesh plink: incorrect plink ie length %d %d\n",
			ftype, ie_len);
657 658 659
		return;
	}

660 661
	if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
				(!elems.mesh_id || !elems.mesh_config)) {
J
Johannes Berg 已提交
662
		mpl_dbg(sdata, "Mesh plink: missing necessary ie\n");
663 664 665 666 667
		return;
	}
	/* Note the lines below are correct, the llid in the frame is the plid
	 * from the point of view of this host.
	 */
668
	memcpy(&plid, PLINK_GET_LLID(elems.peering), 2);
669
	if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||
670 671
	    (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8))
		memcpy(&llid, PLINK_GET_PLID(elems.peering), 2);
672

673
	/* WARNING: Only for sta pointer, is dropped & re-acquired */
674 675
	rcu_read_lock();

676
	sta = sta_info_get(sdata, mgmt->sa);
677
	if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) {
J
Johannes Berg 已提交
678
		mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n");
679
		rcu_read_unlock();
680 681 682
		return;
	}

683
	if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
684
	    !rssi_threshold_check(sta, sdata)) {
J
Johannes Berg 已提交
685
		mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n",
686
			mgmt->sa);
687 688 689 690
		rcu_read_unlock();
		return;
	}

J
Johannes Berg 已提交
691
	if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
J
Johannes Berg 已提交
692
		mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n");
693 694 695 696
		rcu_read_unlock();
		return;
	}

697
	if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) {
698
		rcu_read_unlock();
699 700 701 702 703
		return;
	}

	/* Now we will figure out the appropriate event... */
	event = PLINK_UNDEFINED;
704
	if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
705
	    !mesh_matches_local(sdata, &elems)) {
706
		matches_local = false;
707
		switch (ftype) {
708
		case WLAN_SP_MESH_PEERING_OPEN:
709 710
			event = OPN_RJCT;
			break;
711
		case WLAN_SP_MESH_PEERING_CONFIRM:
712 713
			event = CNF_RJCT;
			break;
714
		default:
715 716
			break;
		}
717 718 719 720
	}

	if (!sta && !matches_local) {
		rcu_read_unlock();
721
		reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
722
		llid = 0;
723 724
		mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
				    mgmt->sa, llid, plid, reason);
725
		return;
726
	} else if (!sta) {
727
		/* ftype == WLAN_SP_MESH_PEERING_OPEN */
728
		if (!mesh_plink_free_count(sdata)) {
J
Johannes Berg 已提交
729
			mpl_dbg(sdata, "Mesh plink error: no more free plinks\n");
J
Johannes Berg 已提交
730 731 732
			rcu_read_unlock();
			return;
		}
733
		event = OPN_ACPT;
734
	} else if (matches_local) {
735
		switch (ftype) {
736
		case WLAN_SP_MESH_PEERING_OPEN:
737
			if (!mesh_plink_free_count(sdata) ||
738
			    (sta->plid && sta->plid != plid))
739 740 741 742
				event = OPN_IGNR;
			else
				event = OPN_ACPT;
			break;
743
		case WLAN_SP_MESH_PEERING_CONFIRM:
744
			if (!mesh_plink_free_count(sdata) ||
745
			    (sta->llid != llid || sta->plid != plid))
746 747 748 749
				event = CNF_IGNR;
			else
				event = CNF_ACPT;
			break;
750
		case WLAN_SP_MESH_PEERING_CLOSE:
751
			if (sta->plink_state == NL80211_PLINK_ESTAB)
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
				/* Do not check for llid or plid. This does not
				 * follow the standard but since multiple plinks
				 * per sta are not supported, it is necessary in
				 * order to avoid a livelock when MP A sees an
				 * establish peer link to MP B but MP B does not
				 * see it. This can be caused by a timeout in
				 * B's peer link establishment or B beign
				 * restarted.
				 */
				event = CLS_ACPT;
			else if (sta->plid != plid)
				event = CLS_IGNR;
			else if (ie_len == 7 && sta->llid != llid)
				event = CLS_IGNR;
			else
				event = CLS_ACPT;
			break;
		default:
J
Johannes Berg 已提交
770
			mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n");
771
			rcu_read_unlock();
772 773
			return;
		}
774 775 776
	}

	if (event == OPN_ACPT) {
777
		rcu_read_unlock();
778
		/* allocate sta entry if necessary and update info */
779
		sta = mesh_sta_info_get(sdata, mgmt->sa, &elems);
780
		if (!sta) {
J
Johannes Berg 已提交
781
			mpl_dbg(sdata, "Mesh plink: failed to init peer!\n");
782 783 784
			rcu_read_unlock();
			return;
		}
785 786
	}

J
Johannes Berg 已提交
787 788
	mpl_dbg(sdata,
		"Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
789
		mgmt->sa, mplstates[sta->plink_state],
790 791
		le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
		event);
792
	reason = 0;
793
	spin_lock_bh(&sta->lock);
794 795
	switch (sta->plink_state) {
		/* spin_unlock as soon as state is updated at each case */
796
	case NL80211_PLINK_LISTEN:
797 798 799
		switch (event) {
		case CLS_ACPT:
			mesh_plink_fsm_restart(sta);
800
			spin_unlock_bh(&sta->lock);
801 802
			break;
		case OPN_ACPT:
803
			sta->plink_state = NL80211_PLINK_OPN_RCVD;
804 805 806
			sta->plid = plid;
			get_random_bytes(&llid, 2);
			sta->llid = llid;
807 808
			mesh_plink_timer_set(sta,
					     mshcfg->dot11MeshRetryTimeout);
809
			spin_unlock_bh(&sta->lock);
810 811 812 813 814 815
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_OPEN,
					    sta->sta.addr, llid, 0, 0);
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
816 817
			break;
		default:
818
			spin_unlock_bh(&sta->lock);
819 820 821 822
			break;
		}
		break;

823
	case NL80211_PLINK_OPN_SNT:
824 825 826
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
827
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
828 829
		case CLS_ACPT:
			if (!reason)
830
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
831
			sta->reason = reason;
832
			sta->plink_state = NL80211_PLINK_HOLDING;
833
			if (!mod_plink_timer(sta,
834
					     mshcfg->dot11MeshHoldingTimeout))
835 836 837
				sta->ignore_plink_timer = true;

			llid = sta->llid;
838
			spin_unlock_bh(&sta->lock);
839 840 841
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
842 843 844
			break;
		case OPN_ACPT:
			/* retry timer is left untouched */
845
			sta->plink_state = NL80211_PLINK_OPN_RCVD;
846 847
			sta->plid = plid;
			llid = sta->llid;
848
			spin_unlock_bh(&sta->lock);
849 850 851
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
852 853
			break;
		case CNF_ACPT:
854
			sta->plink_state = NL80211_PLINK_CNF_RCVD;
855
			if (!mod_plink_timer(sta,
856
					     mshcfg->dot11MeshConfirmTimeout))
857 858
				sta->ignore_plink_timer = true;

859
			spin_unlock_bh(&sta->lock);
860 861
			break;
		default:
862
			spin_unlock_bh(&sta->lock);
863 864 865 866
			break;
		}
		break;

867
	case NL80211_PLINK_OPN_RCVD:
868 869 870
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
871
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
872 873
		case CLS_ACPT:
			if (!reason)
874
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
875
			sta->reason = reason;
876
			sta->plink_state = NL80211_PLINK_HOLDING;
877
			if (!mod_plink_timer(sta,
878
					     mshcfg->dot11MeshHoldingTimeout))
879 880 881
				sta->ignore_plink_timer = true;

			llid = sta->llid;
882
			spin_unlock_bh(&sta->lock);
883 884
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
885 886 887
			break;
		case OPN_ACPT:
			llid = sta->llid;
888
			spin_unlock_bh(&sta->lock);
889 890 891
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
892 893
			break;
		case CNF_ACPT:
894
			del_timer(&sta->plink_timer);
895
			sta->plink_state = NL80211_PLINK_ESTAB;
896
			spin_unlock_bh(&sta->lock);
897
			changed |= mesh_plink_inc_estab_count(sdata);
898
			changed |= mesh_set_ht_prot_mode(sdata);
J
Johannes Berg 已提交
899
			mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
900
				sta->sta.addr);
901 902
			break;
		default:
903
			spin_unlock_bh(&sta->lock);
904 905 906 907
			break;
		}
		break;

908
	case NL80211_PLINK_CNF_RCVD:
909 910 911
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
912
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
913 914
		case CLS_ACPT:
			if (!reason)
915
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
916
			sta->reason = reason;
917
			sta->plink_state = NL80211_PLINK_HOLDING;
918
			if (!mod_plink_timer(sta,
919
					     mshcfg->dot11MeshHoldingTimeout))
920 921 922
				sta->ignore_plink_timer = true;

			llid = sta->llid;
923
			spin_unlock_bh(&sta->lock);
924 925 926
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
927
			break;
928
		case OPN_ACPT:
929
			del_timer(&sta->plink_timer);
930
			sta->plink_state = NL80211_PLINK_ESTAB;
931
			spin_unlock_bh(&sta->lock);
932
			changed |= mesh_plink_inc_estab_count(sdata);
933
			changed |= mesh_set_ht_prot_mode(sdata);
J
Johannes Berg 已提交
934
			mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
935
				sta->sta.addr);
936 937 938
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
939 940
			break;
		default:
941
			spin_unlock_bh(&sta->lock);
942 943 944 945
			break;
		}
		break;

946
	case NL80211_PLINK_ESTAB:
947 948
		switch (event) {
		case CLS_ACPT:
949
			reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
950
			sta->reason = reason;
951
			changed |= __mesh_plink_deactivate(sta);
952
			sta->plink_state = NL80211_PLINK_HOLDING;
953
			llid = sta->llid;
954
			mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
955
			spin_unlock_bh(&sta->lock);
956
			changed |= mesh_set_ht_prot_mode(sdata);
957 958
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
959 960 961
			break;
		case OPN_ACPT:
			llid = sta->llid;
962
			spin_unlock_bh(&sta->lock);
963 964 965
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
966 967
			break;
		default:
968
			spin_unlock_bh(&sta->lock);
969 970 971
			break;
		}
		break;
972
	case NL80211_PLINK_HOLDING:
973 974
		switch (event) {
		case CLS_ACPT:
975
			if (del_timer(&sta->plink_timer))
976 977
				sta->ignore_plink_timer = 1;
			mesh_plink_fsm_restart(sta);
978
			spin_unlock_bh(&sta->lock);
979 980 981 982 983 984 985
			break;
		case OPN_ACPT:
		case CNF_ACPT:
		case OPN_RJCT:
		case CNF_RJCT:
			llid = sta->llid;
			reason = sta->reason;
986
			spin_unlock_bh(&sta->lock);
987 988
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
989 990
			break;
		default:
991
			spin_unlock_bh(&sta->lock);
992 993 994
		}
		break;
	default:
995
		/* should not get here, PLINK_BLOCKED is dealt with at the
D
Daniel Mack 已提交
996
		 * beginning of the function
997
		 */
998
		spin_unlock_bh(&sta->lock);
999 1000
		break;
	}
1001 1002

	rcu_read_unlock();
1003 1004 1005

	if (changed)
		ieee80211_bss_info_change_notify(sdata, changed);
1006
}