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 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
/*
 * 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;
		}

		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.
 */
427 428
void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
			   u8 *hw_addr,
429 430 431 432
			   struct ieee802_11_elems *elems)
{
	struct sta_info *sta;

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

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

444
out:
445
	rcu_read_unlock();
446 447 448 449 450 451 452
}

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

455 456 457 458 459
	/*
	 * 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.)
	 */
460 461
	sta = (struct sta_info *) data;

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

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

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

526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
#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

542 543 544 545 546 547 548 549 550 551 552 553
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;
554
	struct ieee80211_sub_if_data *sdata = sta->sdata;
555

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

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

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

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

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

588
	ieee80211_bss_info_change_notify(sdata, changed);
589 590 591
}


592
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
593 594
			 size_t len, struct ieee80211_rx_status *rx_status)
{
595
	struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
596 597 598
	struct ieee802_11_elems elems;
	struct sta_info *sta;
	enum plink_event event;
599
	enum ieee80211_self_protected_actioncode ftype;
600
	size_t baselen;
601
	bool matches_local = true;
602 603
	u8 ie_len;
	u8 *baseaddr;
604
	u32 changed = 0;
605
	__le16 plid, llid, reason;
606
	static const char *mplstates[] = {
607 608 609 610 611 612 613
		[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"
614
	};
615

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

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

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

646 647 648 649 650 651
	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 已提交
652 653 654
		mpl_dbg(sdata,
			"Mesh plink: incorrect plink ie length %d %d\n",
			ftype, ie_len);
655 656 657
		return;
	}

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

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

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

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

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

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

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

	if (!sta && !matches_local) {
		rcu_read_unlock();
719
		reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
720
		llid = 0;
721 722
		mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
				    mgmt->sa, llid, plid, reason);
723
		return;
724
	} else if (!sta) {
725
		/* ftype == WLAN_SP_MESH_PEERING_OPEN */
726
		if (!mesh_plink_free_count(sdata)) {
J
Johannes Berg 已提交
727
			mpl_dbg(sdata, "Mesh plink error: no more free plinks\n");
J
Johannes Berg 已提交
728 729 730
			rcu_read_unlock();
			return;
		}
731
		event = OPN_ACPT;
732
	} else if (matches_local) {
733
		switch (ftype) {
734
		case WLAN_SP_MESH_PEERING_OPEN:
735
			if (!mesh_plink_free_count(sdata) ||
736
			    (sta->plid && sta->plid != plid))
737 738 739 740
				event = OPN_IGNR;
			else
				event = OPN_ACPT;
			break;
741
		case WLAN_SP_MESH_PEERING_CONFIRM:
742
			if (!mesh_plink_free_count(sdata) ||
743
			    (sta->llid != llid || sta->plid != plid))
744 745 746 747
				event = CNF_IGNR;
			else
				event = CNF_ACPT;
			break;
748
		case WLAN_SP_MESH_PEERING_CLOSE:
749
			if (sta->plink_state == NL80211_PLINK_ESTAB)
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767
				/* 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 已提交
768
			mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n");
769
			rcu_read_unlock();
770 771
			return;
		}
772 773 774
	}

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

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

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

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

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

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

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

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

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

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

	rcu_read_unlock();
1001 1002 1003

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