mesh_plink.c 27.1 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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
static const char * const mplstates[] = {
	[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"
};

static const char * const mplevents[] = {
	[PLINK_UNDEFINED] = "NONE",
	[OPN_ACPT] = "OPN_ACPT",
	[OPN_RJCT] = "OPN_RJCT",
	[OPN_IGNR] = "OPN_IGNR",
	[CNF_ACPT] = "CNF_ACPT",
	[CNF_RJCT] = "CNF_RJCT",
	[CNF_IGNR] = "CNF_IGNR",
	[CLS_ACPT] = "CLS_ACPT",
	[CLS_IGNR] = "CLS_IGNR"
};

62
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
J
Johannes Berg 已提交
63 64
			       enum ieee80211_self_protected_actioncode action,
			       u8 *da, __le16 llid, __le16 plid, __le16 reason);
65

66 67 68
/**
 * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
 *
R
Rui Paulo 已提交
69
 * @sta: mesh peer link to restart
70
 *
71
 * Locking: this function must be called holding sta->lock
72 73 74
 */
static inline void mesh_plink_fsm_restart(struct sta_info *sta)
{
75
	sta->plink_state = NL80211_PLINK_LISTEN;
76 77
	sta->llid = sta->plid = sta->reason = 0;
	sta->plink_retries = 0;
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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
/*
 * 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;
}

140
/**
141
 * mesh_set_ht_prot_mode - set correct HT protection mode
142
 *
143 144 145 146 147 148
 * 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.
149 150 151 152 153 154 155 156
 */
static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;
	struct sta_info *sta;
	u16 ht_opmode;
	bool non_ht_sta = false, ht20_sta = false;

157 158 159 160
	switch (sdata->vif.bss_conf.chandef.width) {
	case NL80211_CHAN_WIDTH_20_NOHT:
	case NL80211_CHAN_WIDTH_5:
	case NL80211_CHAN_WIDTH_10:
161
		return 0;
162 163 164
	default:
		break;
	}
165 166 167

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

172 173 174 175 176 177
		if (sta->sta.bandwidth > IEEE80211_STA_RX_BW_20)
			continue;

		if (!sta->sta.ht_cap.ht_supported) {
			mpl_dbg(sdata, "nonHT sta (%pM) is present\n",
				       sta->sta.addr);
178 179
			non_ht_sta = true;
			break;
180
		}
181 182 183

		mpl_dbg(sdata, "HT20 sta (%pM) is present\n", sta->sta.addr);
		ht20_sta = true;
184 185 186 187 188
	}
	rcu_read_unlock();

	if (non_ht_sta)
		ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED;
189
	else if (ht20_sta &&
190
		 sdata->vif.bss_conf.chandef.width > NL80211_CHAN_WIDTH_20)
191 192 193 194
		ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ;
	else
		ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE;

195 196
	if (sdata->vif.bss_conf.ht_operation_mode == ht_opmode)
		return 0;
197

198 199 200 201
	sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
	sdata->u.mesh.mshcfg.ht_opmode = ht_opmode;
	mpl_dbg(sdata, "selected new HT protection mode %d\n", ht_opmode);
	return BSS_CHANGED_HT;
202 203
}

204
/**
205
 * __mesh_plink_deactivate - deactivate mesh peer link
206 207 208 209
 *
 * @sta: mesh peer link to deactivate
 *
 * All mesh paths with this peer as next hop will be flushed
210
 * Returns beacon changed flag if the beacon content changed.
211
 *
212
 * Locking: the caller must hold sta->lock
213
 */
214
static u32 __mesh_plink_deactivate(struct sta_info *sta)
215
{
216
	struct ieee80211_sub_if_data *sdata = sta->sdata;
217
	u32 changed = 0;
218

219 220
	if (sta->plink_state == NL80211_PLINK_ESTAB)
		changed = mesh_plink_dec_estab_count(sdata);
221
	sta->plink_state = NL80211_PLINK_BLOCKED;
222
	mesh_path_flush_by_nexthop(sta);
223

M
Marco Porsch 已提交
224
	ieee80211_mps_sta_status_update(sta);
225 226
	changed |= ieee80211_mps_set_sta_local_pm(sta,
			NL80211_MESH_POWER_UNKNOWN);
M
Marco Porsch 已提交
227

228
	return changed;
229 230
}

J
Johannes Berg 已提交
231
/**
232
 * mesh_plink_deactivate - deactivate mesh peer link
J
Johannes Berg 已提交
233 234 235 236 237
 *
 * @sta: mesh peer link to deactivate
 *
 * All mesh paths with this peer as next hop will be flushed
 */
238
u32 mesh_plink_deactivate(struct sta_info *sta)
J
Johannes Berg 已提交
239
{
240
	struct ieee80211_sub_if_data *sdata = sta->sdata;
241
	u32 changed;
242

243
	spin_lock_bh(&sta->lock);
244
	changed = __mesh_plink_deactivate(sta);
245 246 247 248
	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);
249
	spin_unlock_bh(&sta->lock);
250

251
	return changed;
J
Johannes Berg 已提交
252 253
}

254
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
J
Johannes Berg 已提交
255 256 257
			       enum ieee80211_self_protected_actioncode action,
			       u8 *da, __le16 llid, __le16 plid, __le16 reason)
{
258
	struct ieee80211_local *local = sdata->local;
259
	struct sk_buff *skb;
260
	struct ieee80211_tx_info *info;
261 262
	struct ieee80211_mgmt *mgmt;
	bool include_plid = false;
263
	u16 peering_proto = 0;
264 265 266
	u8 *pos, ie_len = 4;
	int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
		      sizeof(mgmt->u.action.u.self_prot);
267
	int err = -ENOMEM;
268

269
	skb = dev_alloc_skb(local->tx_headroom +
270 271 272 273 274 275 276
			    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) +
277
			    2 + sizeof(struct ieee80211_ht_cap) +
278
			    2 + sizeof(struct ieee80211_ht_operation) +
279 280
			    2 + 8 + /* peering IE */
			    sdata->u.mesh.ie_len);
281 282
	if (!skb)
		return -1;
283
	info = IEEE80211_SKB_CB(skb);
284
	skb_reserve(skb, local->tx_headroom);
285 286
	mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
	memset(mgmt, 0, hdr_len);
287 288
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
					  IEEE80211_STYPE_ACTION);
289
	memcpy(mgmt->da, da, ETH_ALEN);
290
	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
291
	memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
292 293
	mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED;
	mgmt->u.action.u.self_prot.action_code = action;
294

295
	if (action != WLAN_SP_MESH_PEERING_CLOSE) {
J
Johannes Berg 已提交
296 297
		enum ieee80211_band band = ieee80211_get_sdata_band(sdata);

298 299 300
		/* capability info */
		pos = skb_put(skb, 2);
		memset(pos, 0, 2);
301
		if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
302 303
			/* AID */
			pos = skb_put(skb, 2);
304
			memcpy(pos + 2, &plid, 2);
305
		}
J
Johannes Berg 已提交
306 307
		if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
		    ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
J
Johannes Berg 已提交
308 309 310
		    mesh_add_rsn_ie(sdata, skb) ||
		    mesh_add_meshid_ie(sdata, skb) ||
		    mesh_add_meshconf_ie(sdata, skb))
311
			goto free;
312
	} else {	/* WLAN_SP_MESH_PEERING_CLOSE */
313
		info->flags |= IEEE80211_TX_CTL_NO_ACK;
J
Johannes Berg 已提交
314
		if (mesh_add_meshid_ie(sdata, skb))
315
			goto free;
316 317
	}

318
	/* Add Mesh Peering Management element */
319
	switch (action) {
320
	case WLAN_SP_MESH_PEERING_OPEN:
321
		break;
322
	case WLAN_SP_MESH_PEERING_CONFIRM:
323
		ie_len += 2;
324 325
		include_plid = true;
		break;
326
	case WLAN_SP_MESH_PEERING_CLOSE:
327 328
		if (plid) {
			ie_len += 2;
329 330
			include_plid = true;
		}
331
		ie_len += 2;	/* reason code */
332
		break;
333
	default:
334 335
		err = -EINVAL;
		goto free;
336 337
	}

338
	if (WARN_ON(skb_tailroom(skb) < 2 + ie_len))
339
		goto free;
340

341
	pos = skb_put(skb, 2 + ie_len);
342
	*pos++ = WLAN_EID_PEER_MGMT;
343
	*pos++ = ie_len;
344 345
	memcpy(pos, &peering_proto, 2);
	pos += 2;
346
	memcpy(pos, &llid, 2);
347
	pos += 2;
348 349
	if (include_plid) {
		memcpy(pos, &plid, 2);
350
		pos += 2;
351
	}
352
	if (action == WLAN_SP_MESH_PEERING_CLOSE) {
353
		memcpy(pos, &reason, 2);
354
		pos += 2;
355
	}
356 357

	if (action != WLAN_SP_MESH_PEERING_CLOSE) {
J
Johannes Berg 已提交
358 359
		if (mesh_add_ht_cap_ie(sdata, skb) ||
		    mesh_add_ht_oper_ie(sdata, skb))
360
			goto free;
361 362
	}

J
Johannes Berg 已提交
363
	if (mesh_add_vendor_ies(sdata, skb))
364
		goto free;
365

366
	ieee80211_tx_skb(sdata, skb);
367
	return 0;
368 369 370
free:
	kfree_skb(skb);
	return err;
371 372
}

373 374 375
static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
			       struct sta_info *sta,
			       struct ieee802_11_elems *elems, bool insert)
376
{
377
	struct ieee80211_local *local = sdata->local;
J
Johannes Berg 已提交
378
	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
379
	struct ieee80211_supported_band *sband;
380
	u32 rates, basic_rates = 0, changed = 0;
381

382
	sband = local->hw.wiphy->bands[band];
383
	rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates);
384

385
	spin_lock_bh(&sta->lock);
386
	sta->last_rx = jiffies;
387 388 389 390

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

392 393
	if (sta->sta.supp_rates[band] != rates)
		changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
394
	sta->sta.supp_rates[band] = rates;
395

396 397 398
	if (ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
					      elems->ht_cap_elem, sta))
		changed |= IEEE80211_RC_BW_CHANGED;
399

400 401 402 403 404
	/* HT peer is operating 20MHz-only */
	if (elems->ht_operation &&
	    !(elems->ht_operation->ht_param &
	      IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
		if (sta->sta.bandwidth != IEEE80211_STA_RX_BW_20)
405
			changed |= IEEE80211_RC_BW_CHANGED;
406
		sta->sta.bandwidth = IEEE80211_STA_RX_BW_20;
407
	}
408

409 410
	if (insert)
		rate_control_rate_init(sta);
411 412
	else
		rate_control_rate_update(local, sband, sta, changed);
413
out:
414
	spin_unlock_bh(&sta->lock);
415 416 417 418 419 420
}

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

422
	if (sdata->local->num_sta >= MESH_MAX_PLINKS)
423 424
		return NULL;

425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
	sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
	if (!sta)
		return NULL;

	sta->plink_state = NL80211_PLINK_LISTEN;

	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;

446 447 448
	/* Userspace handles station allocation */
	if (sdata->u.mesh.user_mpm ||
	    sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)
449 450 451 452 453 454 455
		cfg80211_notify_new_peer_candidate(sdata->dev, addr,
						   elems->ie_start,
						   elems->total_len,
						   GFP_KERNEL);
	else
		sta = __mesh_sta_info_alloc(sdata, addr);

456 457 458
	return sta;
}

459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
/*
 * 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;
		}

488 489
		mesh_sta_info_init(sdata, sta, elems, true);

490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
		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.
 */
506 507
void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
			   u8 *hw_addr,
508 509 510
			   struct ieee802_11_elems *elems)
{
	struct sta_info *sta;
511
	u32 changed = 0;
512

513
	sta = mesh_sta_info_get(sdata, hw_addr, elems);
514 515 516
	if (!sta)
		goto out;

517
	if (mesh_peer_accepts_plinks(elems) &&
518 519 520 521
	    sta->plink_state == NL80211_PLINK_LISTEN &&
	    sdata->u.mesh.accepting_plinks &&
	    sdata->u.mesh.mshcfg.auto_open_plinks &&
	    rssi_threshold_check(sta, sdata))
522
		changed = mesh_plink_open(sta);
523

M
Marco Porsch 已提交
524
	ieee80211_mps_frame_release(sta, elems);
525
out:
526
	rcu_read_unlock();
T
Thomas Pedersen 已提交
527
	ieee80211_mbss_info_change_notify(sdata, changed);
528 529 530 531 532 533 534
}

static void mesh_plink_timer(unsigned long data)
{
	struct sta_info *sta;
	__le16 llid, plid, reason;
	struct ieee80211_sub_if_data *sdata;
535
	struct mesh_config *mshcfg;
536
	enum ieee80211_self_protected_actioncode action = 0;
537

538 539 540 541 542
	/*
	 * 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.)
	 */
543 544
	sta = (struct sta_info *) data;

545
	if (sta->sdata->local->quiescing)
546 547
		return;

548
	spin_lock_bh(&sta->lock);
549 550
	if (sta->ignore_plink_timer) {
		sta->ignore_plink_timer = false;
551
		spin_unlock_bh(&sta->lock);
552 553
		return;
	}
J
Johannes Berg 已提交
554
	mpl_dbg(sta->sdata,
555 556
		"Mesh plink timer for %pM fired on state %s\n",
		sta->sta.addr, mplstates[sta->plink_state]);
557 558 559
	reason = 0;
	llid = sta->llid;
	plid = sta->plid;
560
	sdata = sta->sdata;
561
	mshcfg = &sdata->u.mesh.mshcfg;
562 563

	switch (sta->plink_state) {
564 565
	case NL80211_PLINK_OPN_RCVD:
	case NL80211_PLINK_OPN_SNT:
566
		/* retry timer */
567
		if (sta->plink_retries < mshcfg->dot11MeshMaxRetries) {
568
			u32 rand;
J
Johannes Berg 已提交
569 570
			mpl_dbg(sta->sdata,
				"Mesh plink for %pM (retry, timeout): %d %d\n",
571 572
				sta->sta.addr, sta->plink_retries,
				sta->plink_timeout);
573 574 575 576
			get_random_bytes(&rand, sizeof(u32));
			sta->plink_timeout = sta->plink_timeout +
					     rand % sta->plink_timeout;
			++sta->plink_retries;
577
			mod_plink_timer(sta, sta->plink_timeout);
578
			action = WLAN_SP_MESH_PEERING_OPEN;
579 580
			break;
		}
581
		reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES);
582
		/* fall through on else */
583
	case NL80211_PLINK_CNF_RCVD:
584 585
		/* confirm timer */
		if (!reason)
586
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
587
		sta->plink_state = NL80211_PLINK_HOLDING;
588
		mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
589
		action = WLAN_SP_MESH_PEERING_CLOSE;
590
		break;
591
	case NL80211_PLINK_HOLDING:
592
		/* holding timer */
593
		del_timer(&sta->plink_timer);
594 595 596 597 598
		mesh_plink_fsm_restart(sta);
		break;
	default:
		break;
	}
599
	spin_unlock_bh(&sta->lock);
600 601 602
	if (action)
		mesh_plink_frame_tx(sdata, action, sta->sta.addr,
				    llid, plid, reason);
603 604 605 606 607 608 609 610 611 612 613
}

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

614
u32 mesh_plink_open(struct sta_info *sta)
615 616
{
	__le16 llid;
617
	struct ieee80211_sub_if_data *sdata = sta->sdata;
618
	u32 changed;
619

J
Johannes Berg 已提交
620
	if (!test_sta_flag(sta, WLAN_STA_AUTH))
621
		return 0;
622

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

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

641 642 643
	mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
			    sta->sta.addr, llid, 0, 0);
	return changed;
644 645
}

646
u32 mesh_plink_block(struct sta_info *sta)
647
{
648
	u32 changed;
649

650
	spin_lock_bh(&sta->lock);
651
	changed = __mesh_plink_deactivate(sta);
652
	sta->plink_state = NL80211_PLINK_BLOCKED;
653
	spin_unlock_bh(&sta->lock);
654

655
	return changed;
656 657 658
}


J
Johannes Berg 已提交
659 660 661
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
			 struct ieee80211_mgmt *mgmt, size_t len,
			 struct ieee80211_rx_status *rx_status)
662
{
663
	struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
664
	enum ieee80211_self_protected_actioncode action = 0;
665 666 667
	struct ieee802_11_elems elems;
	struct sta_info *sta;
	enum plink_event event;
668
	enum ieee80211_self_protected_actioncode ftype;
669
	size_t baselen;
670
	bool matches_local = true;
671 672
	u8 ie_len;
	u8 *baseaddr;
673
	u32 changed = 0;
674 675
	__le16 plid, llid, reason;

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

680 681 682 683
	if (sdata->u.mesh.user_mpm)
		/* userspace must register for these */
		return;

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

690 691 692
	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 ==
693
						WLAN_SP_MESH_PEERING_CONFIRM) {
694
		baseaddr += 4;
695
		baselen += 4;
696
	}
697
	ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems);
J
Johannes Berg 已提交
698

699
	if (!elems.peering) {
J
Johannes Berg 已提交
700 701
		mpl_dbg(sdata,
			"Mesh plink: missing necessary peer link ie\n");
702 703
		return;
	}
J
Johannes Berg 已提交
704

705
	if (elems.rsn_len &&
J
Johannes Berg 已提交
706
	    sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
J
Johannes Berg 已提交
707 708
		mpl_dbg(sdata,
			"Mesh plink: can't establish link with secure peer\n");
709 710
		return;
	}
711

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

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

737
	/* WARNING: Only for sta pointer, is dropped & re-acquired */
738 739
	rcu_read_lock();

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

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

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

761
	if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) {
762
		rcu_read_unlock();
763 764 765 766 767
		return;
	}

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

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

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

851 852
	mpl_dbg(sdata, "peer %pM in state %s got event %s\n", mgmt->sa,
		       mplstates[sta->plink_state], mplevents[event]);
853
	reason = 0;
854
	spin_lock_bh(&sta->lock);
855
	switch (sta->plink_state) {
856
	case NL80211_PLINK_LISTEN:
857 858 859 860 861
		switch (event) {
		case CLS_ACPT:
			mesh_plink_fsm_restart(sta);
			break;
		case OPN_ACPT:
862
			sta->plink_state = NL80211_PLINK_OPN_RCVD;
863 864 865
			sta->plid = plid;
			get_random_bytes(&llid, 2);
			sta->llid = llid;
866 867
			mesh_plink_timer_set(sta,
					     mshcfg->dot11MeshRetryTimeout);
M
Marco Porsch 已提交
868 869

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

872
			action = WLAN_SP_MESH_PEERING_OPEN;
873 874 875 876 877 878
			break;
		default:
			break;
		}
		break;

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

893
			action = WLAN_SP_MESH_PEERING_CLOSE;
894 895 896
			break;
		case OPN_ACPT:
			/* retry timer is left untouched */
897
			sta->plink_state = NL80211_PLINK_OPN_RCVD;
898
			sta->plid = plid;
899
			action = WLAN_SP_MESH_PEERING_CONFIRM;
900 901
			break;
		case CNF_ACPT:
902
			sta->plink_state = NL80211_PLINK_CNF_RCVD;
903
			if (!mod_plink_timer(sta,
904
					     mshcfg->dot11MeshConfirmTimeout))
905 906 907 908 909 910 911 912
				sta->ignore_plink_timer = true;

			break;
		default:
			break;
		}
		break;

913
	case NL80211_PLINK_OPN_RCVD:
914 915 916
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
917
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
918 919
		case CLS_ACPT:
			if (!reason)
920
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
921
			sta->reason = reason;
922
			sta->plink_state = NL80211_PLINK_HOLDING;
923
			if (!mod_plink_timer(sta,
924
					     mshcfg->dot11MeshHoldingTimeout))
925 926
				sta->ignore_plink_timer = true;

927
			action = WLAN_SP_MESH_PEERING_CLOSE;
928 929
			break;
		case OPN_ACPT:
930
			action = WLAN_SP_MESH_PEERING_CONFIRM;
931 932
			break;
		case CNF_ACPT:
933
			del_timer(&sta->plink_timer);
934
			sta->plink_state = NL80211_PLINK_ESTAB;
935
			changed |= mesh_plink_inc_estab_count(sdata);
936
			changed |= mesh_set_ht_prot_mode(sdata);
937
			changed |= mesh_set_short_slot_time(sdata);
J
Johannes Berg 已提交
938
			mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
939
				sta->sta.addr);
M
Marco Porsch 已提交
940
			ieee80211_mps_sta_status_update(sta);
941
			changed |= ieee80211_mps_set_sta_local_pm(sta,
M
Marco Porsch 已提交
942
						       mshcfg->power_mode);
943 944 945 946 947 948
			break;
		default:
			break;
		}
		break;

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

963
			action = WLAN_SP_MESH_PEERING_CLOSE;
964
			break;
965
		case OPN_ACPT:
966
			del_timer(&sta->plink_timer);
967
			sta->plink_state = NL80211_PLINK_ESTAB;
968
			changed |= mesh_plink_inc_estab_count(sdata);
969
			changed |= mesh_set_ht_prot_mode(sdata);
970
			changed |= mesh_set_short_slot_time(sdata);
J
Johannes Berg 已提交
971
			mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
972
				sta->sta.addr);
973
			action = WLAN_SP_MESH_PEERING_CONFIRM;
M
Marco Porsch 已提交
974
			ieee80211_mps_sta_status_update(sta);
975 976
			changed |= ieee80211_mps_set_sta_local_pm(sta,
							mshcfg->power_mode);
977 978 979 980 981 982
			break;
		default:
			break;
		}
		break;

983
	case NL80211_PLINK_ESTAB:
984 985
		switch (event) {
		case CLS_ACPT:
986
			reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
987
			sta->reason = reason;
988
			changed |= __mesh_plink_deactivate(sta);
989
			sta->plink_state = NL80211_PLINK_HOLDING;
990
			mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
991
			changed |= mesh_set_ht_prot_mode(sdata);
992
			changed |= mesh_set_short_slot_time(sdata);
993
			action = WLAN_SP_MESH_PEERING_CLOSE;
994 995
			break;
		case OPN_ACPT:
996
			action = WLAN_SP_MESH_PEERING_CONFIRM;
997 998 999 1000 1001
			break;
		default:
			break;
		}
		break;
1002
	case NL80211_PLINK_HOLDING:
1003 1004
		switch (event) {
		case CLS_ACPT:
1005
			if (del_timer(&sta->plink_timer))
1006 1007 1008 1009 1010 1011 1012
				sta->ignore_plink_timer = 1;
			mesh_plink_fsm_restart(sta);
			break;
		case OPN_ACPT:
		case CNF_ACPT:
		case OPN_RJCT:
		case CNF_RJCT:
1013
			action = WLAN_SP_MESH_PEERING_CLOSE;
1014 1015
			break;
		default:
1016
			break;
1017 1018 1019
		}
		break;
	default:
1020
		/* should not get here, PLINK_BLOCKED is dealt with at the
D
Daniel Mack 已提交
1021
		 * beginning of the function
1022 1023 1024
		 */
		break;
	}
1025
	spin_unlock_bh(&sta->lock);
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037
	if (action) {
		mesh_plink_frame_tx(sdata, action, sta->sta.addr,
				    sta->llid, sta->plid, sta->reason);

		/* also send confirm in open case */
		if (action == WLAN_SP_MESH_PEERING_OPEN) {
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, sta->llid,
					    sta->plid, 0);
		}
	}
1038 1039

	rcu_read_unlock();
1040

T
Thomas Pedersen 已提交
1041
	if (changed)
T
Thomas Pedersen 已提交
1042
		ieee80211_mbss_info_change_notify(sdata, changed);
1043
}