mesh_plink.c 28.2 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

204
	return changed;
205 206
}

J
Johannes Berg 已提交
207
/**
208
 * mesh_plink_deactivate - deactivate mesh peer link
J
Johannes Berg 已提交
209 210 211 212 213 214 215
 *
 * @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)
{
216
	struct ieee80211_sub_if_data *sdata = sta->sdata;
217
	u32 changed;
218

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

227
	ieee80211_bss_info_change_notify(sdata, changed);
J
Johannes Berg 已提交
228 229
}

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

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

270
	if (action != WLAN_SP_MESH_PEERING_CLOSE) {
J
Johannes Berg 已提交
271 272
		enum ieee80211_band band = ieee80211_get_sdata_band(sdata);

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

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

313
	if (WARN_ON(skb_tailroom(skb) < 2 + ie_len))
314
		goto free;
315

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

	if (action != WLAN_SP_MESH_PEERING_CLOSE) {
		if (mesh_add_ht_cap_ie(skb, sdata) ||
334
		    mesh_add_ht_oper_ie(skb, sdata))
335
			goto free;
336 337
	}

338
	if (mesh_add_vendor_ies(skb, sdata))
339
		goto free;
340

341
	ieee80211_tx_skb(sdata, skb);
342
	return 0;
343 344 345
free:
	kfree_skb(skb);
	return err;
346 347
}

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

357 358
	sband = local->hw.wiphy->bands[band];
	rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates);
359

360
	spin_lock_bh(&sta->lock);
361
	sta->last_rx = jiffies;
362 363 364 365

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

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

378
	if (elems->ht_operation) {
379 380
		struct cfg80211_chan_def chandef;

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

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

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

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

408 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
	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);

439 440 441
	return sta;
}

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

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

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

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

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

506
out:
507
	rcu_read_unlock();
508 509 510 511 512 513 514
}

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

517 518 519 520 521
	/*
	 * 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.)
	 */
522 523
	sta = (struct sta_info *) data;

524 525 526 527 528
	if (sta->sdata->local->quiescing) {
		sta->plink_timer_was_running = true;
		return;
	}

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

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

588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
#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

604 605 606 607 608 609 610 611 612 613 614 615
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;
616
	struct ieee80211_sub_if_data *sdata = sta->sdata;
617

J
Johannes Berg 已提交
618
	if (!test_sta_flag(sta, WLAN_STA_AUTH))
619 620
		return -EPERM;

621
	spin_lock_bh(&sta->lock);
622 623
	get_random_bytes(&llid, 2);
	sta->llid = llid;
624 625
	if (sta->plink_state != NL80211_PLINK_LISTEN &&
	    sta->plink_state != NL80211_PLINK_BLOCKED) {
626
		spin_unlock_bh(&sta->lock);
627 628
		return -EBUSY;
	}
629
	sta->plink_state = NL80211_PLINK_OPN_SNT;
630
	mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout);
631
	spin_unlock_bh(&sta->lock);
J
Johannes Berg 已提交
632 633
	mpl_dbg(sdata,
		"Mesh plink: starting establishment with %pM\n",
634
		sta->sta.addr);
635

636
	return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
637
				   sta->sta.addr, llid, 0, 0);
638 639 640 641
}

void mesh_plink_block(struct sta_info *sta)
{
642
	struct ieee80211_sub_if_data *sdata = sta->sdata;
643
	u32 changed;
644

645
	spin_lock_bh(&sta->lock);
646
	changed = __mesh_plink_deactivate(sta);
647
	sta->plink_state = NL80211_PLINK_BLOCKED;
648
	spin_unlock_bh(&sta->lock);
649

650
	ieee80211_bss_info_change_notify(sdata, changed);
651 652 653
}


654
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
655 656
			 size_t len, struct ieee80211_rx_status *rx_status)
{
657
	struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
658 659 660
	struct ieee802_11_elems elems;
	struct sta_info *sta;
	enum plink_event event;
661
	enum ieee80211_self_protected_actioncode ftype;
662
	size_t baselen;
663
	bool matches_local = true;
664 665
	u8 ie_len;
	u8 *baseaddr;
666
	u32 changed = 0;
667
	__le16 plid, llid, reason;
668
	static const char *mplstates[] = {
669 670 671 672 673 674 675
		[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"
676
	};
677

678 679 680 681
	/* need action_code, aux */
	if (len < IEEE80211_MIN_ACTION_SIZE + 3)
		return;

682
	if (is_multicast_ether_addr(mgmt->da)) {
J
Johannes Berg 已提交
683 684
		mpl_dbg(sdata,
			"Mesh plink: ignore frame from multicast address\n");
685 686 687
		return;
	}

688 689 690
	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 ==
691
						WLAN_SP_MESH_PEERING_CONFIRM) {
692
		baseaddr += 4;
693
		baselen += 4;
694 695
	}
	ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
696
	if (!elems.peering) {
J
Johannes Berg 已提交
697 698
		mpl_dbg(sdata,
			"Mesh plink: missing necessary peer link ie\n");
699 700
		return;
	}
701 702
	if (elems.rsn_len &&
			sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
J
Johannes Berg 已提交
703 704
		mpl_dbg(sdata,
			"Mesh plink: can't establish link with secure peer\n");
705 706
		return;
	}
707

708 709 710 711 712 713
	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 已提交
714 715 716
		mpl_dbg(sdata,
			"Mesh plink: incorrect plink ie length %d %d\n",
			ftype, ie_len);
717 718 719
		return;
	}

720 721
	if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
				(!elems.mesh_id || !elems.mesh_config)) {
J
Johannes Berg 已提交
722
		mpl_dbg(sdata, "Mesh plink: missing necessary ie\n");
723 724 725 726 727
		return;
	}
	/* Note the lines below are correct, the llid in the frame is the plid
	 * from the point of view of this host.
	 */
728
	memcpy(&plid, PLINK_GET_LLID(elems.peering), 2);
729
	if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||
730 731
	    (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8))
		memcpy(&llid, PLINK_GET_PLID(elems.peering), 2);
732

733
	/* WARNING: Only for sta pointer, is dropped & re-acquired */
734 735
	rcu_read_lock();

736
	sta = sta_info_get(sdata, mgmt->sa);
737
	if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) {
J
Johannes Berg 已提交
738
		mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n");
739
		rcu_read_unlock();
740 741 742
		return;
	}

743
	if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
744
	    !rssi_threshold_check(sta, sdata)) {
J
Johannes Berg 已提交
745
		mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n",
746
			mgmt->sa);
747 748 749 750
		rcu_read_unlock();
		return;
	}

J
Johannes Berg 已提交
751
	if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
J
Johannes Berg 已提交
752
		mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n");
753 754 755 756
		rcu_read_unlock();
		return;
	}

757
	if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) {
758
		rcu_read_unlock();
759 760 761 762 763
		return;
	}

	/* Now we will figure out the appropriate event... */
	event = PLINK_UNDEFINED;
764
	if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
765
	    !mesh_matches_local(sdata, &elems)) {
766
		matches_local = false;
767
		switch (ftype) {
768
		case WLAN_SP_MESH_PEERING_OPEN:
769 770
			event = OPN_RJCT;
			break;
771
		case WLAN_SP_MESH_PEERING_CONFIRM:
772 773
			event = CNF_RJCT;
			break;
774
		default:
775 776
			break;
		}
777 778 779 780
	}

	if (!sta && !matches_local) {
		rcu_read_unlock();
781
		reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
782
		llid = 0;
783 784
		mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
				    mgmt->sa, llid, plid, reason);
785
		return;
786
	} else if (!sta) {
787
		/* ftype == WLAN_SP_MESH_PEERING_OPEN */
788
		if (!mesh_plink_free_count(sdata)) {
J
Johannes Berg 已提交
789
			mpl_dbg(sdata, "Mesh plink error: no more free plinks\n");
J
Johannes Berg 已提交
790 791 792
			rcu_read_unlock();
			return;
		}
793
		event = OPN_ACPT;
794
	} else if (matches_local) {
795
		switch (ftype) {
796
		case WLAN_SP_MESH_PEERING_OPEN:
797
			if (!mesh_plink_free_count(sdata) ||
798
			    (sta->plid && sta->plid != plid))
799 800 801 802
				event = OPN_IGNR;
			else
				event = OPN_ACPT;
			break;
803
		case WLAN_SP_MESH_PEERING_CONFIRM:
804
			if (!mesh_plink_free_count(sdata) ||
805
			    (sta->llid != llid || sta->plid != plid))
806 807 808 809
				event = CNF_IGNR;
			else
				event = CNF_ACPT;
			break;
810
		case WLAN_SP_MESH_PEERING_CLOSE:
811
			if (sta->plink_state == NL80211_PLINK_ESTAB)
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
				/* 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 已提交
830
			mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n");
831
			rcu_read_unlock();
832 833
			return;
		}
834 835 836
	}

	if (event == OPN_ACPT) {
837
		rcu_read_unlock();
838
		/* allocate sta entry if necessary and update info */
839
		sta = mesh_sta_info_get(sdata, mgmt->sa, &elems);
840
		if (!sta) {
J
Johannes Berg 已提交
841
			mpl_dbg(sdata, "Mesh plink: failed to init peer!\n");
842 843 844
			rcu_read_unlock();
			return;
		}
845 846
	}

J
Johannes Berg 已提交
847 848
	mpl_dbg(sdata,
		"Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
849
		mgmt->sa, mplstates[sta->plink_state],
850 851
		le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
		event);
852
	reason = 0;
853
	spin_lock_bh(&sta->lock);
854 855
	switch (sta->plink_state) {
		/* spin_unlock as soon as state is updated at each case */
856
	case NL80211_PLINK_LISTEN:
857 858 859
		switch (event) {
		case CLS_ACPT:
			mesh_plink_fsm_restart(sta);
860
			spin_unlock_bh(&sta->lock);
861 862
			break;
		case OPN_ACPT:
863
			sta->plink_state = NL80211_PLINK_OPN_RCVD;
864 865 866
			sta->plid = plid;
			get_random_bytes(&llid, 2);
			sta->llid = llid;
867 868
			mesh_plink_timer_set(sta,
					     mshcfg->dot11MeshRetryTimeout);
869
			spin_unlock_bh(&sta->lock);
870 871 872 873 874 875
			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);
876 877
			break;
		default:
878
			spin_unlock_bh(&sta->lock);
879 880 881 882
			break;
		}
		break;

883
	case NL80211_PLINK_OPN_SNT:
884 885 886
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
887
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
888 889
		case CLS_ACPT:
			if (!reason)
890
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
891
			sta->reason = reason;
892
			sta->plink_state = NL80211_PLINK_HOLDING;
893
			if (!mod_plink_timer(sta,
894
					     mshcfg->dot11MeshHoldingTimeout))
895 896 897
				sta->ignore_plink_timer = true;

			llid = sta->llid;
898
			spin_unlock_bh(&sta->lock);
899 900 901
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
902 903 904
			break;
		case OPN_ACPT:
			/* retry timer is left untouched */
905
			sta->plink_state = NL80211_PLINK_OPN_RCVD;
906 907
			sta->plid = plid;
			llid = sta->llid;
908
			spin_unlock_bh(&sta->lock);
909 910 911
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
912 913
			break;
		case CNF_ACPT:
914
			sta->plink_state = NL80211_PLINK_CNF_RCVD;
915
			if (!mod_plink_timer(sta,
916
					     mshcfg->dot11MeshConfirmTimeout))
917 918
				sta->ignore_plink_timer = true;

919
			spin_unlock_bh(&sta->lock);
920 921
			break;
		default:
922
			spin_unlock_bh(&sta->lock);
923 924 925 926
			break;
		}
		break;

927
	case NL80211_PLINK_OPN_RCVD:
928 929 930
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
931
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
932 933
		case CLS_ACPT:
			if (!reason)
934
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
935
			sta->reason = reason;
936
			sta->plink_state = NL80211_PLINK_HOLDING;
937
			if (!mod_plink_timer(sta,
938
					     mshcfg->dot11MeshHoldingTimeout))
939 940 941
				sta->ignore_plink_timer = true;

			llid = sta->llid;
942
			spin_unlock_bh(&sta->lock);
943 944
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
945 946 947
			break;
		case OPN_ACPT:
			llid = sta->llid;
948
			spin_unlock_bh(&sta->lock);
949 950 951
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
952 953
			break;
		case CNF_ACPT:
954
			del_timer(&sta->plink_timer);
955
			sta->plink_state = NL80211_PLINK_ESTAB;
956
			spin_unlock_bh(&sta->lock);
957
			changed |= mesh_plink_inc_estab_count(sdata);
958
			changed |= mesh_set_ht_prot_mode(sdata);
959
			changed |= mesh_set_short_slot_time(sdata);
J
Johannes Berg 已提交
960
			mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
961
				sta->sta.addr);
962 963
			break;
		default:
964
			spin_unlock_bh(&sta->lock);
965 966 967 968
			break;
		}
		break;

969
	case NL80211_PLINK_CNF_RCVD:
970 971 972
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
973
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
974 975
		case CLS_ACPT:
			if (!reason)
976
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
977
			sta->reason = reason;
978
			sta->plink_state = NL80211_PLINK_HOLDING;
979
			if (!mod_plink_timer(sta,
980
					     mshcfg->dot11MeshHoldingTimeout))
981 982 983
				sta->ignore_plink_timer = true;

			llid = sta->llid;
984
			spin_unlock_bh(&sta->lock);
985 986 987
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
988
			break;
989
		case OPN_ACPT:
990
			del_timer(&sta->plink_timer);
991
			sta->plink_state = NL80211_PLINK_ESTAB;
992
			spin_unlock_bh(&sta->lock);
993
			changed |= mesh_plink_inc_estab_count(sdata);
994
			changed |= mesh_set_ht_prot_mode(sdata);
995
			changed |= mesh_set_short_slot_time(sdata);
J
Johannes Berg 已提交
996
			mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
997
				sta->sta.addr);
998 999 1000
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
1001 1002
			break;
		default:
1003
			spin_unlock_bh(&sta->lock);
1004 1005 1006 1007
			break;
		}
		break;

1008
	case NL80211_PLINK_ESTAB:
1009 1010
		switch (event) {
		case CLS_ACPT:
1011
			reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
1012
			sta->reason = reason;
1013
			changed |= __mesh_plink_deactivate(sta);
1014
			sta->plink_state = NL80211_PLINK_HOLDING;
1015
			llid = sta->llid;
1016
			mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
1017
			spin_unlock_bh(&sta->lock);
1018
			changed |= mesh_set_ht_prot_mode(sdata);
1019
			changed |= mesh_set_short_slot_time(sdata);
1020 1021
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
1022 1023 1024
			break;
		case OPN_ACPT:
			llid = sta->llid;
1025
			spin_unlock_bh(&sta->lock);
1026 1027 1028
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
1029 1030
			break;
		default:
1031
			spin_unlock_bh(&sta->lock);
1032 1033 1034
			break;
		}
		break;
1035
	case NL80211_PLINK_HOLDING:
1036 1037
		switch (event) {
		case CLS_ACPT:
1038
			if (del_timer(&sta->plink_timer))
1039 1040
				sta->ignore_plink_timer = 1;
			mesh_plink_fsm_restart(sta);
1041
			spin_unlock_bh(&sta->lock);
1042 1043 1044 1045 1046 1047 1048
			break;
		case OPN_ACPT:
		case CNF_ACPT:
		case OPN_RJCT:
		case CNF_RJCT:
			llid = sta->llid;
			reason = sta->reason;
1049
			spin_unlock_bh(&sta->lock);
1050 1051
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
1052 1053
			break;
		default:
1054
			spin_unlock_bh(&sta->lock);
1055 1056 1057
		}
		break;
	default:
1058
		/* should not get here, PLINK_BLOCKED is dealt with at the
D
Daniel Mack 已提交
1059
		 * beginning of the function
1060
		 */
1061
		spin_unlock_bh(&sta->lock);
1062 1063
		break;
	}
1064 1065

	rcu_read_unlock();
1066 1067 1068

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