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
		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
376
						  elems->ht_cap_elem, sta);
377 378 379
	else
		memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap));

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

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

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

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

406
	if (sdata->local->num_sta >= MESH_MAX_PLINKS)
407 408
		return NULL;

409 410 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
	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);

440 441 442
	return sta;
}

443 444 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
/*
 * 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;
		}

472 473
		mesh_sta_info_init(sdata, sta, elems, true);

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

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

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

M
Marco Porsch 已提交
508
	ieee80211_mps_frame_release(sta, elems);
509
out:
510
	rcu_read_unlock();
T
Thomas Pedersen 已提交
511
	ieee80211_mbss_info_change_notify(sdata, changed);
512 513 514 515 516 517 518
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

656
u32 mesh_plink_block(struct sta_info *sta)
657
{
658
	u32 changed;
659

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

665
	return changed;
666 667 668
}


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	rcu_read_unlock();
1091 1092

	if (changed)
T
Thomas Pedersen 已提交
1093
		ieee80211_mbss_info_change_notify(sdata, changed);
1094
}