mesh_plink.c 28.9 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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
/*
 * mesh_set_short_slot_time - enable / disable ERP short slot time.
 *
 * The standard indirectly mandates mesh STAs to turn off short slot time by
 * disallowing advertising this (802.11-2012 8.4.1.4), but that doesn't mean we
 * can't be sneaky about it. Enable short slot time if all mesh STAs in the
 * MBSS support ERP rates.
 *
 * Returns BSS_CHANGED_ERP_SLOT or 0 for no change.
 */
static u32 mesh_set_short_slot_time(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;
	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
	struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
	struct sta_info *sta;
	u32 erp_rates = 0, changed = 0;
	int i;
	bool short_slot = false;

	if (band == IEEE80211_BAND_5GHZ) {
		/* (IEEE 802.11-2012 19.4.5) */
		short_slot = true;
		goto out;
	} else if (band != IEEE80211_BAND_2GHZ ||
		   (band == IEEE80211_BAND_2GHZ &&
		    local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
		goto out;

	for (i = 0; i < sband->n_bitrates; i++)
		if (sband->bitrates[i].flags & IEEE80211_RATE_ERP_G)
			erp_rates |= BIT(i);

	if (!erp_rates)
		goto out;

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

		short_slot = false;
		if (erp_rates & sta->sta.supp_rates[band])
			short_slot = true;
		 else
			break;
	}
	rcu_read_unlock();

out:
	if (sdata->vif.bss_conf.use_short_slot != short_slot) {
		sdata->vif.bss_conf.use_short_slot = short_slot;
		changed = BSS_CHANGED_ERP_SLOT;
		mpl_dbg(sdata, "mesh_plink %pM: ERP short slot time %d\n",
			sdata->vif.addr, short_slot);
	}
	return changed;
}

118
/**
119
 * mesh_set_ht_prot_mode - set correct HT protection mode
120
 *
121 122 123 124 125 126
 * 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.
127 128 129 130 131 132 133 134 135
 */
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;

136
	if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
137 138 139 140
		return 0;

	rcu_read_lock();
	list_for_each_entry_rcu(sta, &local->sta_list, list) {
141 142 143 144
		if (sdata != sta->sdata ||
		    sta->plink_state != NL80211_PLINK_ESTAB)
			continue;

145 146
		switch (sta->ch_width) {
		case NL80211_CHAN_WIDTH_20_NOHT:
J
Johannes Berg 已提交
147 148
			mpl_dbg(sdata,
				"mesh_plink %pM: nonHT sta (%pM) is present\n",
149 150 151
				sdata->vif.addr, sta->sta.addr);
			non_ht_sta = true;
			goto out;
152
		case NL80211_CHAN_WIDTH_20:
J
Johannes Berg 已提交
153 154
			mpl_dbg(sdata,
				"mesh_plink %pM: HT20 sta (%pM) is present\n",
155 156 157 158
				sdata->vif.addr, sta->sta.addr);
			ht20_sta = true;
		default:
			break;
159 160 161 162 163 164 165
		}
	}
out:
	rcu_read_unlock();

	if (non_ht_sta)
		ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED;
166
	else if (ht20_sta &&
167
		 sdata->vif.bss_conf.chandef.width > NL80211_CHAN_WIDTH_20)
168 169 170 171 172 173
		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;
174
		sdata->u.mesh.mshcfg.ht_opmode = ht_opmode;
175
		changed = BSS_CHANGED_HT;
J
Johannes Berg 已提交
176 177
		mpl_dbg(sdata,
			"mesh_plink %pM: protection mode changed to %d\n",
178 179 180 181 182 183
			sdata->vif.addr, ht_opmode);
	}

	return changed;
}

184
/**
185
 * __mesh_plink_deactivate - deactivate mesh peer link
186 187 188 189
 *
 * @sta: mesh peer link to deactivate
 *
 * All mesh paths with this peer as next hop will be flushed
190
 * Returns beacon changed flag if the beacon content changed.
191
 *
192
 * Locking: the caller must hold sta->lock
193
 */
194
static u32 __mesh_plink_deactivate(struct sta_info *sta)
195
{
196
	struct ieee80211_sub_if_data *sdata = sta->sdata;
197
	u32 changed = 0;
198

199 200
	if (sta->plink_state == NL80211_PLINK_ESTAB)
		changed = mesh_plink_dec_estab_count(sdata);
201
	sta->plink_state = NL80211_PLINK_BLOCKED;
202
	mesh_path_flush_by_nexthop(sta);
203

M
Marco Porsch 已提交
204
	ieee80211_mps_sta_status_update(sta);
205
	changed |= ieee80211_mps_local_status_update(sdata);
M
Marco Porsch 已提交
206

207
	return changed;
208 209
}

J
Johannes Berg 已提交
210
/**
211
 * mesh_plink_deactivate - deactivate mesh peer link
J
Johannes Berg 已提交
212 213 214 215 216
 *
 * @sta: mesh peer link to deactivate
 *
 * All mesh paths with this peer as next hop will be flushed
 */
217
u32 mesh_plink_deactivate(struct sta_info *sta)
J
Johannes Berg 已提交
218
{
219
	struct ieee80211_sub_if_data *sdata = sta->sdata;
220
	u32 changed;
221

222
	spin_lock_bh(&sta->lock);
223
	changed = __mesh_plink_deactivate(sta);
224 225 226 227
	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);
228
	spin_unlock_bh(&sta->lock);
229

230
	return changed;
J
Johannes Berg 已提交
231 232
}

233
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
234 235
		enum ieee80211_self_protected_actioncode action,
		u8 *da, __le16 llid, __le16 plid, __le16 reason) {
236
	struct ieee80211_local *local = sdata->local;
237
	struct sk_buff *skb;
238
	struct ieee80211_tx_info *info;
239 240
	struct ieee80211_mgmt *mgmt;
	bool include_plid = false;
241
	u16 peering_proto = 0;
242 243 244
	u8 *pos, ie_len = 4;
	int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
		      sizeof(mgmt->u.action.u.self_prot);
245
	int err = -ENOMEM;
246

247
	skb = dev_alloc_skb(local->tx_headroom +
248 249 250 251 252 253 254
			    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) +
255
			    2 + sizeof(struct ieee80211_ht_cap) +
256
			    2 + sizeof(struct ieee80211_ht_operation) +
257 258
			    2 + 8 + /* peering IE */
			    sdata->u.mesh.ie_len);
259 260
	if (!skb)
		return -1;
261
	info = IEEE80211_SKB_CB(skb);
262
	skb_reserve(skb, local->tx_headroom);
263 264
	mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
	memset(mgmt, 0, hdr_len);
265 266
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
					  IEEE80211_STYPE_ACTION);
267
	memcpy(mgmt->da, da, ETH_ALEN);
268
	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
269
	memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
270 271
	mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED;
	mgmt->u.action.u.self_prot.action_code = action;
272

273
	if (action != WLAN_SP_MESH_PEERING_CLOSE) {
J
Johannes Berg 已提交
274 275
		enum ieee80211_band band = ieee80211_get_sdata_band(sdata);

276 277 278
		/* capability info */
		pos = skb_put(skb, 2);
		memset(pos, 0, 2);
279
		if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
280 281
			/* AID */
			pos = skb_put(skb, 2);
282
			memcpy(pos + 2, &plid, 2);
283
		}
J
Johannes Berg 已提交
284 285
		if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
		    ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
286 287 288
		    mesh_add_rsn_ie(skb, sdata) ||
		    mesh_add_meshid_ie(skb, sdata) ||
		    mesh_add_meshconf_ie(skb, sdata))
289
			goto free;
290
	} else {	/* WLAN_SP_MESH_PEERING_CLOSE */
291
		info->flags |= IEEE80211_TX_CTL_NO_ACK;
292
		if (mesh_add_meshid_ie(skb, sdata))
293
			goto free;
294 295
	}

296
	/* Add Mesh Peering Management element */
297
	switch (action) {
298
	case WLAN_SP_MESH_PEERING_OPEN:
299
		break;
300
	case WLAN_SP_MESH_PEERING_CONFIRM:
301
		ie_len += 2;
302 303
		include_plid = true;
		break;
304
	case WLAN_SP_MESH_PEERING_CLOSE:
305 306
		if (plid) {
			ie_len += 2;
307 308
			include_plid = true;
		}
309
		ie_len += 2;	/* reason code */
310
		break;
311
	default:
312 313
		err = -EINVAL;
		goto free;
314 315
	}

316
	if (WARN_ON(skb_tailroom(skb) < 2 + ie_len))
317
		goto free;
318

319
	pos = skb_put(skb, 2 + ie_len);
320
	*pos++ = WLAN_EID_PEER_MGMT;
321
	*pos++ = ie_len;
322 323
	memcpy(pos, &peering_proto, 2);
	pos += 2;
324
	memcpy(pos, &llid, 2);
325
	pos += 2;
326 327
	if (include_plid) {
		memcpy(pos, &plid, 2);
328
		pos += 2;
329
	}
330
	if (action == WLAN_SP_MESH_PEERING_CLOSE) {
331
		memcpy(pos, &reason, 2);
332
		pos += 2;
333
	}
334 335 336

	if (action != WLAN_SP_MESH_PEERING_CLOSE) {
		if (mesh_add_ht_cap_ie(skb, sdata) ||
337
		    mesh_add_ht_oper_ie(skb, sdata))
338
			goto free;
339 340
	}

341
	if (mesh_add_vendor_ies(skb, sdata))
342
		goto free;
343

344
	ieee80211_tx_skb(sdata, skb);
345
	return 0;
346 347 348
free:
	kfree_skb(skb);
	return err;
349 350
}

351 352 353
static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
			       struct sta_info *sta,
			       struct ieee802_11_elems *elems, bool insert)
354
{
355
	struct ieee80211_local *local = sdata->local;
J
Johannes Berg 已提交
356
	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
357
	struct ieee80211_supported_band *sband;
358
	u32 rates, basic_rates = 0, changed = 0;
359

360 361
	sband = local->hw.wiphy->bands[band];
	rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates);
362

363
	spin_lock_bh(&sta->lock);
364
	sta->last_rx = jiffies;
365 366 367 368

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

370 371
	if (sta->sta.supp_rates[band] != rates)
		changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
372
	sta->sta.supp_rates[band] = rates;
373
	if (elems->ht_cap_elem &&
374
	    sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
375 376 377 378 379 380
		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));

381
	if (elems->ht_operation) {
382 383
		struct cfg80211_chan_def chandef;

384 385 386 387
		if (!(elems->ht_operation->ht_param &
		      IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
			sta->sta.ht_cap.cap &=
					    ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
388 389
		ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
					     elems->ht_operation, &chandef);
390 391
		if (sta->ch_width != chandef.width)
			changed |= IEEE80211_RC_BW_CHANGED;
392
		sta->ch_width = chandef.width;
393
	}
394

395 396
	if (insert)
		rate_control_rate_init(sta);
397 398
	else
		rate_control_rate_update(local, sband, sta, changed);
399
out:
400
	spin_unlock_bh(&sta->lock);
401 402 403 404 405 406
}

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

408
	if (sdata->local->num_sta >= MESH_MAX_PLINKS)
409 410
		return NULL;

411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
	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);

442 443 444
	return sta;
}

445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
/*
 * 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;
		}

474 475
		mesh_sta_info_init(sdata, sta, elems, true);

476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
		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.
 */
492 493
void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
			   u8 *hw_addr,
494 495 496
			   struct ieee802_11_elems *elems)
{
	struct sta_info *sta;
497
	u32 changed = 0;
498

499
	sta = mesh_sta_info_get(sdata, hw_addr, elems);
500 501 502
	if (!sta)
		goto out;

503
	if (mesh_peer_accepts_plinks(elems) &&
504 505 506 507
	    sta->plink_state == NL80211_PLINK_LISTEN &&
	    sdata->u.mesh.accepting_plinks &&
	    sdata->u.mesh.mshcfg.auto_open_plinks &&
	    rssi_threshold_check(sta, sdata))
508
		changed = mesh_plink_open(sta);
509

M
Marco Porsch 已提交
510
	ieee80211_mps_frame_release(sta, elems);
511
out:
512
	rcu_read_unlock();
513
	ieee80211_bss_info_change_notify(sdata, changed);
514 515 516 517 518 519 520
}

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

523 524 525 526 527
	/*
	 * 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.)
	 */
528 529
	sta = (struct sta_info *) data;

530 531 532 533 534
	if (sta->sdata->local->quiescing) {
		sta->plink_timer_was_running = true;
		return;
	}

535
	spin_lock_bh(&sta->lock);
536 537
	if (sta->ignore_plink_timer) {
		sta->ignore_plink_timer = false;
538
		spin_unlock_bh(&sta->lock);
539 540
		return;
	}
J
Johannes Berg 已提交
541 542
	mpl_dbg(sta->sdata,
		"Mesh plink timer for %pM fired on state %d\n",
543
		sta->sta.addr, sta->plink_state);
544 545 546
	reason = 0;
	llid = sta->llid;
	plid = sta->plid;
547
	sdata = sta->sdata;
548
	mshcfg = &sdata->u.mesh.mshcfg;
549 550

	switch (sta->plink_state) {
551 552
	case NL80211_PLINK_OPN_RCVD:
	case NL80211_PLINK_OPN_SNT:
553
		/* retry timer */
554
		if (sta->plink_retries < mshcfg->dot11MeshMaxRetries) {
555
			u32 rand;
J
Johannes Berg 已提交
556 557
			mpl_dbg(sta->sdata,
				"Mesh plink for %pM (retry, timeout): %d %d\n",
558 559
				sta->sta.addr, sta->plink_retries,
				sta->plink_timeout);
560 561 562 563
			get_random_bytes(&rand, sizeof(u32));
			sta->plink_timeout = sta->plink_timeout +
					     rand % sta->plink_timeout;
			++sta->plink_retries;
564
			mod_plink_timer(sta, sta->plink_timeout);
565
			spin_unlock_bh(&sta->lock);
566 567
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
					    sta->sta.addr, llid, 0, 0);
568 569
			break;
		}
570
		reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES);
571
		/* fall through on else */
572
	case NL80211_PLINK_CNF_RCVD:
573 574
		/* confirm timer */
		if (!reason)
575
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
576
		sta->plink_state = NL80211_PLINK_HOLDING;
577
		mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
578
		spin_unlock_bh(&sta->lock);
579 580
		mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
				    sta->sta.addr, llid, plid, reason);
581
		break;
582
	case NL80211_PLINK_HOLDING:
583
		/* holding timer */
584
		del_timer(&sta->plink_timer);
585
		mesh_plink_fsm_restart(sta);
586
		spin_unlock_bh(&sta->lock);
587 588
		break;
	default:
589
		spin_unlock_bh(&sta->lock);
590 591 592 593
		break;
	}
}

594 595 596
#ifdef CONFIG_PM
void mesh_plink_quiesce(struct sta_info *sta)
{
597 598 599
	if (!ieee80211_vif_is_mesh(&sta->sdata->vif))
		return;

600 601 602 603
	/* no kernel mesh sta timers have been initialized */
	if (sta->sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)
		return;

604 605 606 607 608 609 610 611 612 613 614 615 616
	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

617 618 619 620 621 622 623 624 625
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);
}

626
u32 mesh_plink_open(struct sta_info *sta)
627 628
{
	__le16 llid;
629
	struct ieee80211_sub_if_data *sdata = sta->sdata;
630
	u32 changed;
631

J
Johannes Berg 已提交
632
	if (!test_sta_flag(sta, WLAN_STA_AUTH))
633
		return 0;
634

635
	spin_lock_bh(&sta->lock);
636 637
	get_random_bytes(&llid, 2);
	sta->llid = llid;
638 639
	if (sta->plink_state != NL80211_PLINK_LISTEN &&
	    sta->plink_state != NL80211_PLINK_BLOCKED) {
640
		spin_unlock_bh(&sta->lock);
641
		return 0;
642
	}
643
	sta->plink_state = NL80211_PLINK_OPN_SNT;
644
	mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout);
645
	spin_unlock_bh(&sta->lock);
J
Johannes Berg 已提交
646 647
	mpl_dbg(sdata,
		"Mesh plink: starting establishment with %pM\n",
648
		sta->sta.addr);
649

M
Marco Porsch 已提交
650
	/* set the non-peer mode to active during peering */
651
	changed = ieee80211_mps_local_status_update(sdata);
M
Marco Porsch 已提交
652

653 654 655
	mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
			    sta->sta.addr, llid, 0, 0);
	return changed;
656 657
}

658
u32 mesh_plink_block(struct sta_info *sta)
659
{
660
	u32 changed;
661

662
	spin_lock_bh(&sta->lock);
663
	changed = __mesh_plink_deactivate(sta);
664
	sta->plink_state = NL80211_PLINK_BLOCKED;
665
	spin_unlock_bh(&sta->lock);
666

667
	return changed;
668 669 670
}


671
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
672 673
			 size_t len, struct ieee80211_rx_status *rx_status)
{
674
	struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
675 676 677
	struct ieee802_11_elems elems;
	struct sta_info *sta;
	enum plink_event event;
678
	enum ieee80211_self_protected_actioncode ftype;
679
	size_t baselen;
680
	bool matches_local = true;
681 682
	u8 ie_len;
	u8 *baseaddr;
683
	u32 changed = 0;
684
	__le16 plid, llid, reason;
685
	static const char *mplstates[] = {
686 687 688 689 690 691 692
		[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"
693
	};
694

695 696 697 698
	/* need action_code, aux */
	if (len < IEEE80211_MIN_ACTION_SIZE + 3)
		return;

699
	if (is_multicast_ether_addr(mgmt->da)) {
J
Johannes Berg 已提交
700 701
		mpl_dbg(sdata,
			"Mesh plink: ignore frame from multicast address\n");
702 703 704
		return;
	}

705 706 707
	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 ==
708
						WLAN_SP_MESH_PEERING_CONFIRM) {
709
		baseaddr += 4;
710
		baselen += 4;
711 712
	}
	ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
713
	if (!elems.peering) {
J
Johannes Berg 已提交
714 715
		mpl_dbg(sdata,
			"Mesh plink: missing necessary peer link ie\n");
716 717
		return;
	}
718 719
	if (elems.rsn_len &&
			sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
J
Johannes Berg 已提交
720 721
		mpl_dbg(sdata,
			"Mesh plink: can't establish link with secure peer\n");
722 723
		return;
	}
724

725 726 727 728 729 730
	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 已提交
731 732 733
		mpl_dbg(sdata,
			"Mesh plink: incorrect plink ie length %d %d\n",
			ftype, ie_len);
734 735 736
		return;
	}

737 738
	if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
				(!elems.mesh_id || !elems.mesh_config)) {
J
Johannes Berg 已提交
739
		mpl_dbg(sdata, "Mesh plink: missing necessary ie\n");
740 741 742 743 744
		return;
	}
	/* Note the lines below are correct, the llid in the frame is the plid
	 * from the point of view of this host.
	 */
745
	memcpy(&plid, PLINK_GET_LLID(elems.peering), 2);
746
	if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||
747 748
	    (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8))
		memcpy(&llid, PLINK_GET_PLID(elems.peering), 2);
749

750
	/* WARNING: Only for sta pointer, is dropped & re-acquired */
751 752
	rcu_read_lock();

753
	sta = sta_info_get(sdata, mgmt->sa);
754
	if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) {
J
Johannes Berg 已提交
755
		mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n");
756
		rcu_read_unlock();
757 758 759
		return;
	}

760
	if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
761
	    !rssi_threshold_check(sta, sdata)) {
J
Johannes Berg 已提交
762
		mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n",
763
			mgmt->sa);
764 765 766 767
		rcu_read_unlock();
		return;
	}

J
Johannes Berg 已提交
768
	if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
J
Johannes Berg 已提交
769
		mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n");
770 771 772 773
		rcu_read_unlock();
		return;
	}

774
	if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) {
775
		rcu_read_unlock();
776 777 778 779 780
		return;
	}

	/* Now we will figure out the appropriate event... */
	event = PLINK_UNDEFINED;
781
	if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
782
	    !mesh_matches_local(sdata, &elems)) {
783
		matches_local = false;
784
		switch (ftype) {
785
		case WLAN_SP_MESH_PEERING_OPEN:
786 787
			event = OPN_RJCT;
			break;
788
		case WLAN_SP_MESH_PEERING_CONFIRM:
789 790
			event = CNF_RJCT;
			break;
791
		default:
792 793
			break;
		}
794 795 796 797
	}

	if (!sta && !matches_local) {
		rcu_read_unlock();
798
		reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
799
		llid = 0;
800 801
		mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
				    mgmt->sa, llid, plid, reason);
802
		return;
803
	} else if (!sta) {
804
		/* ftype == WLAN_SP_MESH_PEERING_OPEN */
805
		if (!mesh_plink_free_count(sdata)) {
J
Johannes Berg 已提交
806
			mpl_dbg(sdata, "Mesh plink error: no more free plinks\n");
J
Johannes Berg 已提交
807 808 809
			rcu_read_unlock();
			return;
		}
810
		event = OPN_ACPT;
811
	} else if (matches_local) {
812
		switch (ftype) {
813
		case WLAN_SP_MESH_PEERING_OPEN:
814
			if (!mesh_plink_free_count(sdata) ||
815
			    (sta->plid && sta->plid != plid))
816 817 818 819
				event = OPN_IGNR;
			else
				event = OPN_ACPT;
			break;
820
		case WLAN_SP_MESH_PEERING_CONFIRM:
821
			if (!mesh_plink_free_count(sdata) ||
822
			    (sta->llid != llid || sta->plid != plid))
823 824 825 826
				event = CNF_IGNR;
			else
				event = CNF_ACPT;
			break;
827
		case WLAN_SP_MESH_PEERING_CLOSE:
828
			if (sta->plink_state == NL80211_PLINK_ESTAB)
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
				/* 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 已提交
847
			mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n");
848
			rcu_read_unlock();
849 850
			return;
		}
851 852 853
	}

	if (event == OPN_ACPT) {
854
		rcu_read_unlock();
855
		/* allocate sta entry if necessary and update info */
856
		sta = mesh_sta_info_get(sdata, mgmt->sa, &elems);
857
		if (!sta) {
J
Johannes Berg 已提交
858
			mpl_dbg(sdata, "Mesh plink: failed to init peer!\n");
859 860 861
			rcu_read_unlock();
			return;
		}
862 863
	}

J
Johannes Berg 已提交
864 865
	mpl_dbg(sdata,
		"Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
866
		mgmt->sa, mplstates[sta->plink_state],
867 868
		le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
		event);
869
	reason = 0;
870
	spin_lock_bh(&sta->lock);
871 872
	switch (sta->plink_state) {
		/* spin_unlock as soon as state is updated at each case */
873
	case NL80211_PLINK_LISTEN:
874 875 876
		switch (event) {
		case CLS_ACPT:
			mesh_plink_fsm_restart(sta);
877
			spin_unlock_bh(&sta->lock);
878 879
			break;
		case OPN_ACPT:
880
			sta->plink_state = NL80211_PLINK_OPN_RCVD;
881 882 883
			sta->plid = plid;
			get_random_bytes(&llid, 2);
			sta->llid = llid;
884 885
			mesh_plink_timer_set(sta,
					     mshcfg->dot11MeshRetryTimeout);
M
Marco Porsch 已提交
886 887

			/* set the non-peer mode to active during peering */
888
			changed |= ieee80211_mps_local_status_update(sdata);
M
Marco Porsch 已提交
889

890
			spin_unlock_bh(&sta->lock);
891 892 893 894 895 896
			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);
897 898
			break;
		default:
899
			spin_unlock_bh(&sta->lock);
900 901 902 903
			break;
		}
		break;

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

			llid = sta->llid;
919
			spin_unlock_bh(&sta->lock);
920 921 922
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
923 924 925
			break;
		case OPN_ACPT:
			/* retry timer is left untouched */
926
			sta->plink_state = NL80211_PLINK_OPN_RCVD;
927 928
			sta->plid = plid;
			llid = sta->llid;
929
			spin_unlock_bh(&sta->lock);
930 931 932
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
933 934
			break;
		case CNF_ACPT:
935
			sta->plink_state = NL80211_PLINK_CNF_RCVD;
936
			if (!mod_plink_timer(sta,
937
					     mshcfg->dot11MeshConfirmTimeout))
938 939
				sta->ignore_plink_timer = true;

940
			spin_unlock_bh(&sta->lock);
941 942
			break;
		default:
943
			spin_unlock_bh(&sta->lock);
944 945 946 947
			break;
		}
		break;

948
	case NL80211_PLINK_OPN_RCVD:
949 950 951
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
952
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
953 954
		case CLS_ACPT:
			if (!reason)
955
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
956
			sta->reason = reason;
957
			sta->plink_state = NL80211_PLINK_HOLDING;
958
			if (!mod_plink_timer(sta,
959
					     mshcfg->dot11MeshHoldingTimeout))
960 961 962
				sta->ignore_plink_timer = true;

			llid = sta->llid;
963
			spin_unlock_bh(&sta->lock);
964 965
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
966 967 968
			break;
		case OPN_ACPT:
			llid = sta->llid;
969
			spin_unlock_bh(&sta->lock);
970 971 972
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
973 974
			break;
		case CNF_ACPT:
975
			del_timer(&sta->plink_timer);
976
			sta->plink_state = NL80211_PLINK_ESTAB;
977
			spin_unlock_bh(&sta->lock);
978
			changed |= mesh_plink_inc_estab_count(sdata);
979
			changed |= mesh_set_ht_prot_mode(sdata);
980
			changed |= mesh_set_short_slot_time(sdata);
J
Johannes Berg 已提交
981
			mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
982
				sta->sta.addr);
M
Marco Porsch 已提交
983
			ieee80211_mps_sta_status_update(sta);
984
			changed |= ieee80211_mps_set_sta_local_pm(sta,
M
Marco Porsch 已提交
985
						       mshcfg->power_mode);
986 987
			break;
		default:
988
			spin_unlock_bh(&sta->lock);
989 990 991 992
			break;
		}
		break;

993
	case NL80211_PLINK_CNF_RCVD:
994 995 996
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
997
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
998 999
		case CLS_ACPT:
			if (!reason)
1000
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
1001
			sta->reason = reason;
1002
			sta->plink_state = NL80211_PLINK_HOLDING;
1003
			if (!mod_plink_timer(sta,
1004
					     mshcfg->dot11MeshHoldingTimeout))
1005 1006 1007
				sta->ignore_plink_timer = true;

			llid = sta->llid;
1008
			spin_unlock_bh(&sta->lock);
1009 1010 1011
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
1012
			break;
1013
		case OPN_ACPT:
1014
			del_timer(&sta->plink_timer);
1015
			sta->plink_state = NL80211_PLINK_ESTAB;
1016
			spin_unlock_bh(&sta->lock);
1017
			changed |= mesh_plink_inc_estab_count(sdata);
1018
			changed |= mesh_set_ht_prot_mode(sdata);
1019
			changed |= mesh_set_short_slot_time(sdata);
J
Johannes Berg 已提交
1020
			mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
1021
				sta->sta.addr);
1022 1023 1024
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
M
Marco Porsch 已提交
1025
			ieee80211_mps_sta_status_update(sta);
1026 1027
			changed |= ieee80211_mps_set_sta_local_pm(sta,
							mshcfg->power_mode);
1028 1029
			break;
		default:
1030
			spin_unlock_bh(&sta->lock);
1031 1032 1033 1034
			break;
		}
		break;

1035
	case NL80211_PLINK_ESTAB:
1036 1037
		switch (event) {
		case CLS_ACPT:
1038
			reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
1039
			sta->reason = reason;
1040
			changed |= __mesh_plink_deactivate(sta);
1041
			sta->plink_state = NL80211_PLINK_HOLDING;
1042
			llid = sta->llid;
1043
			mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
1044
			spin_unlock_bh(&sta->lock);
1045
			changed |= mesh_set_ht_prot_mode(sdata);
1046
			changed |= mesh_set_short_slot_time(sdata);
1047 1048
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
1049 1050 1051
			break;
		case OPN_ACPT:
			llid = sta->llid;
1052
			spin_unlock_bh(&sta->lock);
1053 1054 1055
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
1056 1057
			break;
		default:
1058
			spin_unlock_bh(&sta->lock);
1059 1060 1061
			break;
		}
		break;
1062
	case NL80211_PLINK_HOLDING:
1063 1064
		switch (event) {
		case CLS_ACPT:
1065
			if (del_timer(&sta->plink_timer))
1066 1067
				sta->ignore_plink_timer = 1;
			mesh_plink_fsm_restart(sta);
1068
			spin_unlock_bh(&sta->lock);
1069 1070 1071 1072 1073 1074 1075
			break;
		case OPN_ACPT:
		case CNF_ACPT:
		case OPN_RJCT:
		case CNF_RJCT:
			llid = sta->llid;
			reason = sta->reason;
1076
			spin_unlock_bh(&sta->lock);
1077 1078
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
1079 1080
			break;
		default:
1081
			spin_unlock_bh(&sta->lock);
1082 1083 1084
		}
		break;
	default:
1085
		/* should not get here, PLINK_BLOCKED is dealt with at the
D
Daniel Mack 已提交
1086
		 * beginning of the function
1087
		 */
1088
		spin_unlock_bh(&sta->lock);
1089 1090
		break;
	}
1091 1092

	rcu_read_unlock();
1093 1094 1095

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