mesh_pathtbl.c 21.9 KB
Newer Older
1
/*
R
Rui Paulo 已提交
2
 * Copyright (c) 2008, 2009 open80211s Ltd.
3 4 5 6 7 8 9 10 11 12
 * 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.
 */

#include <linux/etherdevice.h>
#include <linux/list.h>
#include <linux/random.h>
13
#include <linux/slab.h>
14 15 16 17 18 19
#include <linux/spinlock.h>
#include <linux/string.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
#include "mesh.h"

20 21 22 23 24 25
#ifdef CONFIG_MAC80211_VERBOSE_MPATH_DEBUG
#define mpath_dbg(fmt, args...)	printk(KERN_DEBUG fmt, ##args)
#else
#define mpath_dbg(fmt, args...)	do { (void)(0); } while (0)
#endif

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
/* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */
#define INIT_PATHS_SIZE_ORDER	2

/* Keep the mean chain length below this constant */
#define MEAN_CHAIN_LEN		2

#define MPATH_EXPIRED(mpath) ((mpath->flags & MESH_PATH_ACTIVE) && \
				time_after(jiffies, mpath->exp_time) && \
				!(mpath->flags & MESH_PATH_FIXED))

struct mpath_node {
	struct hlist_node list;
	struct rcu_head rcu;
	/* This indirection allows two different tables to point to the same
	 * mesh_path structure, useful when resizing
	 */
	struct mesh_path *mpath;
};

45 46
static struct mesh_table __rcu *mesh_paths;
static struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */
47

48
int mesh_paths_generation;
49 50 51 52 53 54 55 56

/* This lock will have the grow table function as writer and add / delete nodes
 * as readers. When reading the table (i.e. doing lookups) we are well protected
 * by RCU
 */
static DEFINE_RWLOCK(pathtbl_resize_lock);


57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
static inline struct mesh_table *resize_dereference_mesh_paths(void)
{
	return rcu_dereference_protected(mesh_paths,
		lockdep_is_held(&pathtbl_resize_lock));
}

static inline struct mesh_table *resize_dereference_mpp_paths(void)
{
	return rcu_dereference_protected(mpp_paths,
		lockdep_is_held(&pathtbl_resize_lock));
}

/*
 * CAREFUL -- "tbl" must not be an expression,
 * in particular not an rcu_dereference(), since
 * it's used twice. So it is illegal to do
 *	for_each_mesh_entry(rcu_dereference(...), ...)
 */
#define for_each_mesh_entry(tbl, p, node, i) \
	for (i = 0; i <= tbl->hash_mask; i++) \
		hlist_for_each_entry_rcu(node, p, &tbl->hash_buckets[i], list)


80 81 82 83 84
static struct mesh_table *mesh_table_alloc(int size_order)
{
	int i;
	struct mesh_table *newtbl;

85
	newtbl = kmalloc(sizeof(struct mesh_table), GFP_ATOMIC);
86 87 88 89
	if (!newtbl)
		return NULL;

	newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) *
90
			(1 << size_order), GFP_ATOMIC);
91 92 93 94 95 96 97

	if (!newtbl->hash_buckets) {
		kfree(newtbl);
		return NULL;
	}

	newtbl->hashwlock = kmalloc(sizeof(spinlock_t) *
98
			(1 << size_order), GFP_ATOMIC);
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
	if (!newtbl->hashwlock) {
		kfree(newtbl->hash_buckets);
		kfree(newtbl);
		return NULL;
	}

	newtbl->size_order = size_order;
	newtbl->hash_mask = (1 << size_order) - 1;
	atomic_set(&newtbl->entries,  0);
	get_random_bytes(&newtbl->hash_rnd,
			sizeof(newtbl->hash_rnd));
	for (i = 0; i <= newtbl->hash_mask; i++)
		spin_lock_init(&newtbl->hashwlock[i]);

	return newtbl;
}

116 117 118 119 120 121 122
static void __mesh_table_free(struct mesh_table *tbl)
{
	kfree(tbl->hash_buckets);
	kfree(tbl->hashwlock);
	kfree(tbl);
}

123
static void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
124 125 126 127 128 129 130
{
	struct hlist_head *mesh_hash;
	struct hlist_node *p, *q;
	int i;

	mesh_hash = tbl->hash_buckets;
	for (i = 0; i <= tbl->hash_mask; i++) {
131
		spin_lock_bh(&tbl->hashwlock[i]);
132 133 134 135
		hlist_for_each_safe(p, q, &mesh_hash[i]) {
			tbl->free_node(p, free_leafs);
			atomic_dec(&tbl->entries);
		}
136
		spin_unlock_bh(&tbl->hashwlock[i]);
137 138 139 140
	}
	__mesh_table_free(tbl);
}

141
static int mesh_table_grow(struct mesh_table *oldtbl,
142
			   struct mesh_table *newtbl)
143 144 145 146 147
{
	struct hlist_head *oldhash;
	struct hlist_node *p, *q;
	int i;

148 149 150
	if (atomic_read(&oldtbl->entries)
			< oldtbl->mean_chain_len * (oldtbl->hash_mask + 1))
		return -EAGAIN;
151

152 153 154 155
	newtbl->free_node = oldtbl->free_node;
	newtbl->mean_chain_len = oldtbl->mean_chain_len;
	newtbl->copy_node = oldtbl->copy_node;
	atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries));
156

157 158
	oldhash = oldtbl->hash_buckets;
	for (i = 0; i <= oldtbl->hash_mask; i++)
159
		hlist_for_each(p, &oldhash[i])
160
			if (oldtbl->copy_node(p, newtbl) < 0)
161 162
				goto errcopy;

163
	return 0;
164 165 166 167

errcopy:
	for (i = 0; i <= newtbl->hash_mask; i++) {
		hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
168
			oldtbl->free_node(p, 0);
169
	}
170
	return -ENOMEM;
171 172
}

173 174 175 176 177 178 179
static u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata,
			   struct mesh_table *tbl)
{
	/* Use last four bytes of hw addr and interface index as hash index */
	return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd)
		& tbl->hash_mask;
}
180

181 182 183 184 185 186 187 188 189 190 191 192

/**
 *
 * mesh_path_assign_nexthop - update mesh path next hop
 *
 * @mpath: mesh path to update
 * @sta: next hop to assign
 *
 * Locking: mpath->state_lock must be held when calling this function
 */
void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
{
193 194 195 196 197
	struct sk_buff *skb;
	struct ieee80211_hdr *hdr;
	struct sk_buff_head tmpq;
	unsigned long flags;

198
	rcu_assign_pointer(mpath->next_hop, sta);
199 200 201 202 203 204 205 206 207 208 209 210 211

	__skb_queue_head_init(&tmpq);

	spin_lock_irqsave(&mpath->frame_queue.lock, flags);

	while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) {
		hdr = (struct ieee80211_hdr *) skb->data;
		memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN);
		__skb_queue_tail(&tmpq, skb);
	}

	skb_queue_splice(&tmpq, &mpath->frame_queue);
	spin_unlock_irqrestore(&mpath->frame_queue.lock, flags);
212 213 214 215 216 217
}


/**
 * mesh_path_lookup - look up a path in the mesh path table
 * @dst: hardware address (ETH_ALEN length) of destination
218
 * @sdata: local subif
219 220 221 222 223
 *
 * Returns: pointer to the mesh path structure, or NULL if not found
 *
 * Locking: must be called within a read rcu section.
 */
224
struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
225 226 227 228 229 230 231 232 233
{
	struct mesh_path *mpath;
	struct hlist_node *n;
	struct hlist_head *bucket;
	struct mesh_table *tbl;
	struct mpath_node *node;

	tbl = rcu_dereference(mesh_paths);

234
	bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)];
235 236
	hlist_for_each_entry_rcu(node, n, bucket, list) {
		mpath = node->mpath;
237
		if (mpath->sdata == sdata &&
238 239 240 241 242 243 244 245 246 247 248 249 250
				memcmp(dst, mpath->dst, ETH_ALEN) == 0) {
			if (MPATH_EXPIRED(mpath)) {
				spin_lock_bh(&mpath->state_lock);
				if (MPATH_EXPIRED(mpath))
					mpath->flags &= ~MESH_PATH_ACTIVE;
				spin_unlock_bh(&mpath->state_lock);
			}
			return mpath;
		}
	}
	return NULL;
}

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
{
	struct mesh_path *mpath;
	struct hlist_node *n;
	struct hlist_head *bucket;
	struct mesh_table *tbl;
	struct mpath_node *node;

	tbl = rcu_dereference(mpp_paths);

	bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)];
	hlist_for_each_entry_rcu(node, n, bucket, list) {
		mpath = node->mpath;
		if (mpath->sdata == sdata &&
		    memcmp(dst, mpath->dst, ETH_ALEN) == 0) {
			if (MPATH_EXPIRED(mpath)) {
				spin_lock_bh(&mpath->state_lock);
				if (MPATH_EXPIRED(mpath))
					mpath->flags &= ~MESH_PATH_ACTIVE;
				spin_unlock_bh(&mpath->state_lock);
			}
			return mpath;
		}
	}
	return NULL;
}


279 280 281
/**
 * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index
 * @idx: index
282
 * @sdata: local subif, or NULL for all entries
283 284 285 286 287
 *
 * Returns: pointer to the mesh path structure, or NULL if not found.
 *
 * Locking: must be called within a read rcu section.
 */
288
struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata)
289
{
290
	struct mesh_table *tbl = rcu_dereference(mesh_paths);
291 292 293 294 295
	struct mpath_node *node;
	struct hlist_node *p;
	int i;
	int j = 0;

296
	for_each_mesh_entry(tbl, p, node, i) {
297
		if (sdata && node->mpath->sdata != sdata)
298
			continue;
299 300 301 302 303 304 305 306 307
		if (j++ == idx) {
			if (MPATH_EXPIRED(node->mpath)) {
				spin_lock_bh(&node->mpath->state_lock);
				if (MPATH_EXPIRED(node->mpath))
					node->mpath->flags &= ~MESH_PATH_ACTIVE;
				spin_unlock_bh(&node->mpath->state_lock);
			}
			return node->mpath;
		}
308
	}
309 310 311 312 313 314 315

	return NULL;
}

/**
 * mesh_path_add - allocate and add a new path to the mesh path table
 * @addr: destination address of the path (ETH_ALEN length)
316
 * @sdata: local subif
317
 *
318
 * Returns: 0 on success
319 320 321
 *
 * State: the initial state of the new path is set to 0
 */
322
int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
323
{
324 325
	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
	struct ieee80211_local *local = sdata->local;
326
	struct mesh_table *tbl;
327 328 329 330 331 332 333 334
	struct mesh_path *mpath, *new_mpath;
	struct mpath_node *node, *new_node;
	struct hlist_head *bucket;
	struct hlist_node *n;
	int grow = 0;
	int err = 0;
	u32 hash_idx;

335
	if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0)
336 337 338 339 340 341
		/* never add ourselves as neighbours */
		return -ENOTSUPP;

	if (is_multicast_ether_addr(dst))
		return -ENOTSUPP;

342
	if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0)
343 344
		return -ENOSPC;

345
	err = -ENOMEM;
346
	new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
347 348 349
	if (!new_mpath)
		goto err_path_alloc;

350
	new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
351 352
	if (!new_node)
		goto err_node_alloc;
353

354
	read_lock_bh(&pathtbl_resize_lock);
355
	memcpy(new_mpath->dst, dst, ETH_ALEN);
356
	new_mpath->sdata = sdata;
357 358 359 360 361 362 363 364 365
	new_mpath->flags = 0;
	skb_queue_head_init(&new_mpath->frame_queue);
	new_node->mpath = new_mpath;
	new_mpath->timer.data = (unsigned long) new_mpath;
	new_mpath->timer.function = mesh_path_timer;
	new_mpath->exp_time = jiffies;
	spin_lock_init(&new_mpath->state_lock);
	init_timer(&new_mpath->timer);

366
	tbl = resize_dereference_mesh_paths();
367

368 369
	hash_idx = mesh_table_hash(dst, sdata, tbl);
	bucket = &tbl->hash_buckets[hash_idx];
370

371
	spin_lock_bh(&tbl->hashwlock[hash_idx]);
372

373
	err = -EEXIST;
374 375
	hlist_for_each_entry(node, n, bucket, list) {
		mpath = node->mpath;
376
		if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0)
377
			goto err_exists;
378 379 380
	}

	hlist_add_head_rcu(&new_node->list, bucket);
381 382
	if (atomic_inc_return(&tbl->entries) >=
	    tbl->mean_chain_len * (tbl->hash_mask + 1))
383 384
		grow = 1;

385 386
	mesh_paths_generation++;

387
	spin_unlock_bh(&tbl->hashwlock[hash_idx]);
388
	read_unlock_bh(&pathtbl_resize_lock);
389
	if (grow) {
390
		set_bit(MESH_WORK_GROW_MPATH_TABLE,  &ifmsh->wrkq_flags);
J
Johannes Berg 已提交
391
		ieee80211_queue_work(&local->hw, &sdata->work);
392
	}
393 394 395
	return 0;

err_exists:
396
	spin_unlock_bh(&tbl->hashwlock[hash_idx]);
397
	read_unlock_bh(&pathtbl_resize_lock);
398 399 400 401
	kfree(new_node);
err_node_alloc:
	kfree(new_mpath);
err_path_alloc:
402
	atomic_dec(&sdata->u.mesh.mpaths);
403 404 405
	return err;
}

406 407 408 409 410 411 412
static void mesh_table_free_rcu(struct rcu_head *rcu)
{
	struct mesh_table *tbl = container_of(rcu, struct mesh_table, rcu_head);

	mesh_table_free(tbl, false);
}

413 414 415 416
void mesh_mpath_table_grow(void)
{
	struct mesh_table *oldtbl, *newtbl;

417
	write_lock_bh(&pathtbl_resize_lock);
418 419
	oldtbl = resize_dereference_mesh_paths();
	newtbl = mesh_table_alloc(oldtbl->size_order + 1);
420 421
	if (!newtbl)
		goto out;
422
	if (mesh_table_grow(oldtbl, newtbl) < 0) {
423
		__mesh_table_free(newtbl);
424
		goto out;
425 426 427
	}
	rcu_assign_pointer(mesh_paths, newtbl);

428 429 430 431
	call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu);

 out:
	write_unlock_bh(&pathtbl_resize_lock);
432 433 434 435 436 437
}

void mesh_mpp_table_grow(void)
{
	struct mesh_table *oldtbl, *newtbl;

438
	write_lock_bh(&pathtbl_resize_lock);
439 440
	oldtbl = resize_dereference_mpp_paths();
	newtbl = mesh_table_alloc(oldtbl->size_order + 1);
441 442
	if (!newtbl)
		goto out;
443
	if (mesh_table_grow(oldtbl, newtbl) < 0) {
444
		__mesh_table_free(newtbl);
445
		goto out;
446 447
	}
	rcu_assign_pointer(mpp_paths, newtbl);
448
	call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu);
449

450 451
 out:
	write_unlock_bh(&pathtbl_resize_lock);
452
}
453

454 455
int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
{
456 457
	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
	struct ieee80211_local *local = sdata->local;
458
	struct mesh_table *tbl;
459 460 461 462 463 464 465 466
	struct mesh_path *mpath, *new_mpath;
	struct mpath_node *node, *new_node;
	struct hlist_head *bucket;
	struct hlist_node *n;
	int grow = 0;
	int err = 0;
	u32 hash_idx;

467
	if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0)
468 469 470 471 472 473 474
		/* never add ourselves as neighbours */
		return -ENOTSUPP;

	if (is_multicast_ether_addr(dst))
		return -ENOTSUPP;

	err = -ENOMEM;
475
	new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
476 477 478
	if (!new_mpath)
		goto err_path_alloc;

479
	new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
480 481 482
	if (!new_node)
		goto err_node_alloc;

483
	read_lock_bh(&pathtbl_resize_lock);
484 485 486 487 488 489 490 491 492
	memcpy(new_mpath->dst, dst, ETH_ALEN);
	memcpy(new_mpath->mpp, mpp, ETH_ALEN);
	new_mpath->sdata = sdata;
	new_mpath->flags = 0;
	skb_queue_head_init(&new_mpath->frame_queue);
	new_node->mpath = new_mpath;
	new_mpath->exp_time = jiffies;
	spin_lock_init(&new_mpath->state_lock);

493
	tbl = resize_dereference_mpp_paths();
494

495 496 497 498
	hash_idx = mesh_table_hash(dst, sdata, tbl);
	bucket = &tbl->hash_buckets[hash_idx];

	spin_lock_bh(&tbl->hashwlock[hash_idx]);
499 500 501 502 503 504 505 506 507

	err = -EEXIST;
	hlist_for_each_entry(node, n, bucket, list) {
		mpath = node->mpath;
		if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0)
			goto err_exists;
	}

	hlist_add_head_rcu(&new_node->list, bucket);
508 509
	if (atomic_inc_return(&tbl->entries) >=
	    tbl->mean_chain_len * (tbl->hash_mask + 1))
510 511
		grow = 1;

512
	spin_unlock_bh(&tbl->hashwlock[hash_idx]);
513
	read_unlock_bh(&pathtbl_resize_lock);
514
	if (grow) {
515
		set_bit(MESH_WORK_GROW_MPP_TABLE,  &ifmsh->wrkq_flags);
J
Johannes Berg 已提交
516
		ieee80211_queue_work(&local->hw, &sdata->work);
517 518 519 520
	}
	return 0;

err_exists:
521
	spin_unlock_bh(&tbl->hashwlock[hash_idx]);
522
	read_unlock_bh(&pathtbl_resize_lock);
523 524 525 526 527 528 529 530
	kfree(new_node);
err_node_alloc:
	kfree(new_mpath);
err_path_alloc:
	return err;
}


531 532 533 534 535 536 537 538 539 540
/**
 * mesh_plink_broken - deactivates paths and sends perr when a link breaks
 *
 * @sta: broken peer link
 *
 * This function must be called from the rate control algorithm if enough
 * delivery errors suggest that a peer link is no longer usable.
 */
void mesh_plink_broken(struct sta_info *sta)
{
541
	struct mesh_table *tbl;
542
	static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
543 544 545
	struct mesh_path *mpath;
	struct mpath_node *node;
	struct hlist_node *p;
546
	struct ieee80211_sub_if_data *sdata = sta->sdata;
547
	int i;
548
	__le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
549 550

	rcu_read_lock();
551 552
	tbl = rcu_dereference(mesh_paths);
	for_each_mesh_entry(tbl, p, node, i) {
553 554
		mpath = node->mpath;
		spin_lock_bh(&mpath->state_lock);
555
		if (rcu_dereference(mpath->next_hop) == sta &&
556 557 558
		    mpath->flags & MESH_PATH_ACTIVE &&
		    !(mpath->flags & MESH_PATH_FIXED)) {
			mpath->flags &= ~MESH_PATH_ACTIVE;
559
			++mpath->sn;
560
			spin_unlock_bh(&mpath->state_lock);
561 562
			mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl,
					mpath->dst, cpu_to_le32(mpath->sn),
563
					reason, bcast, sdata);
564 565 566 567 568 569 570 571 572 573 574
		} else
		spin_unlock_bh(&mpath->state_lock);
	}
	rcu_read_unlock();
}

/**
 * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches
 *
 * @sta - mesh peer to match
 *
575 576 577
 * RCU notes: this function is called when a mesh plink transitions from
 * PLINK_ESTAB to any other state, since PLINK_ESTAB state is the only one that
 * allows path creation. This will happen before the sta can be freed (because
578 579
 * sta_info_destroy() calls this) so any reader in a rcu read block will be
 * protected against the plink disappearing.
580 581 582
 */
void mesh_path_flush_by_nexthop(struct sta_info *sta)
{
583
	struct mesh_table *tbl;
584 585 586 587 588
	struct mesh_path *mpath;
	struct mpath_node *node;
	struct hlist_node *p;
	int i;

589 590 591
	rcu_read_lock();
	tbl = rcu_dereference(mesh_paths);
	for_each_mesh_entry(tbl, p, node, i) {
592
		mpath = node->mpath;
593
		if (rcu_dereference(mpath->next_hop) == sta)
594
			mesh_path_del(mpath->dst, mpath->sdata);
595
	}
596
	rcu_read_unlock();
597 598
}

599
void mesh_path_flush(struct ieee80211_sub_if_data *sdata)
600
{
601
	struct mesh_table *tbl;
602 603 604 605 606
	struct mesh_path *mpath;
	struct mpath_node *node;
	struct hlist_node *p;
	int i;

607 608 609
	rcu_read_lock();
	tbl = rcu_dereference(mesh_paths);
	for_each_mesh_entry(tbl, p, node, i) {
610
		mpath = node->mpath;
611 612
		if (mpath->sdata == sdata)
			mesh_path_del(mpath->dst, mpath->sdata);
613
	}
614
	rcu_read_unlock();
615 616 617 618 619
}

static void mesh_path_node_reclaim(struct rcu_head *rp)
{
	struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
620
	struct ieee80211_sub_if_data *sdata = node->mpath->sdata;
621

622 623
	if (node->mpath->timer.function)
		del_timer_sync(&node->mpath->timer);
624
	atomic_dec(&sdata->u.mesh.mpaths);
625 626 627 628 629 630 631 632
	kfree(node->mpath);
	kfree(node);
}

/**
 * mesh_path_del - delete a mesh path from the table
 *
 * @addr: dst address (ETH_ALEN length)
633
 * @sdata: local subif
634
 *
635
 * Returns: 0 if successful
636
 */
637
int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
638
{
639
	struct mesh_table *tbl;
640 641 642 643 644 645 646
	struct mesh_path *mpath;
	struct mpath_node *node;
	struct hlist_head *bucket;
	struct hlist_node *n;
	int hash_idx;
	int err = 0;

647
	read_lock_bh(&pathtbl_resize_lock);
648 649 650
	tbl = resize_dereference_mesh_paths();
	hash_idx = mesh_table_hash(addr, sdata, tbl);
	bucket = &tbl->hash_buckets[hash_idx];
651

652
	spin_lock_bh(&tbl->hashwlock[hash_idx]);
653 654
	hlist_for_each_entry(node, n, bucket, list) {
		mpath = node->mpath;
655
		if (mpath->sdata == sdata &&
656
		    memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
J
Javier Cardona 已提交
657
			spin_lock_bh(&mpath->state_lock);
658 659 660
			mpath->flags |= MESH_PATH_RESOLVING;
			hlist_del_rcu(&node->list);
			call_rcu(&node->rcu, mesh_path_node_reclaim);
661
			atomic_dec(&tbl->entries);
J
Javier Cardona 已提交
662
			spin_unlock_bh(&mpath->state_lock);
663 664 665 666 667 668
			goto enddel;
		}
	}

	err = -ENXIO;
enddel:
669
	mesh_paths_generation++;
670
	spin_unlock_bh(&tbl->hashwlock[hash_idx]);
671
	read_unlock_bh(&pathtbl_resize_lock);
672 673 674 675 676 677 678 679 680 681 682 683 684
	return err;
}

/**
 * mesh_path_tx_pending - sends pending frames in a mesh path queue
 *
 * @mpath: mesh path to activate
 *
 * Locking: the state_lock of the mpath structure must NOT be held when calling
 * this function.
 */
void mesh_path_tx_pending(struct mesh_path *mpath)
{
685 686 687
	if (mpath->flags & MESH_PATH_ACTIVE)
		ieee80211_add_pending_skbs(mpath->sdata->local,
				&mpath->frame_queue);
688 689 690 691 692 693
}

/**
 * mesh_path_discard_frame - discard a frame whose path could not be resolved
 *
 * @skb: frame to discard
694
 * @sdata: network subif the frame was to be sent through
695
 *
696 697 698 699
 * If the frame was being forwarded from another MP, a PERR frame will be sent
 * to the precursor.  The precursor's address (i.e. the previous hop) was saved
 * in addr1 of the frame-to-be-forwarded, and would only be overwritten once
 * the destination is successfully resolved.
700 701 702
 *
 * Locking: the function must me called within a rcu_read_lock region
 */
703 704
void mesh_path_discard_frame(struct sk_buff *skb,
			     struct ieee80211_sub_if_data *sdata)
705
{
706
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
707
	struct mesh_path *mpath;
708
	u32 sn = 0;
709
	__le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD);
710

711
	if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) {
712 713
		u8 *ra, *da;

714
		da = hdr->addr3;
715
		ra = hdr->addr1;
716
		mpath = mesh_path_lookup(da, sdata);
717
		if (mpath)
718
			sn = ++mpath->sn;
719
		mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data,
720
				   cpu_to_le32(sn), reason, ra, sdata);
721 722 723
	}

	kfree_skb(skb);
724
	sdata->u.mesh.mshstats.dropped_frames_no_route++;
725 726 727 728 729 730 731
}

/**
 * mesh_path_flush_pending - free the pending queue of a mesh path
 *
 * @mpath: mesh path whose queue has to be freed
 *
L
Lucas De Marchi 已提交
732
 * Locking: the function must me called within a rcu_read_lock region
733 734 735 736 737
 */
void mesh_path_flush_pending(struct mesh_path *mpath)
{
	struct sk_buff *skb;

738
	while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL)
739
		mesh_path_discard_frame(skb, mpath->sdata);
740 741 742 743 744 745 746 747 748 749 750 751 752 753
}

/**
 * mesh_path_fix_nexthop - force a specific next hop for a mesh path
 *
 * @mpath: the mesh path to modify
 * @next_hop: the next hop to force
 *
 * Locking: this function must be called holding mpath->state_lock
 */
void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop)
{
	spin_lock_bh(&mpath->state_lock);
	mesh_path_assign_nexthop(mpath, next_hop);
754
	mpath->sn = 0xffff;
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
	mpath->metric = 0;
	mpath->hop_count = 0;
	mpath->exp_time = 0;
	mpath->flags |= MESH_PATH_FIXED;
	mesh_path_activate(mpath);
	spin_unlock_bh(&mpath->state_lock);
	mesh_path_tx_pending(mpath);
}

static void mesh_path_node_free(struct hlist_node *p, bool free_leafs)
{
	struct mesh_path *mpath;
	struct mpath_node *node = hlist_entry(p, struct mpath_node, list);
	mpath = node->mpath;
	hlist_del_rcu(p);
770
	if (free_leafs) {
771 772
		if (mpath->timer.function)
			del_timer_sync(&mpath->timer);
773
		kfree(mpath);
774
	}
775 776 777
	kfree(node);
}

778
static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl)
779 780 781 782 783
{
	struct mesh_path *mpath;
	struct mpath_node *node, *new_node;
	u32 hash_idx;

784
	new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
785 786 787
	if (new_node == NULL)
		return -ENOMEM;

788 789 790
	node = hlist_entry(p, struct mpath_node, list);
	mpath = node->mpath;
	new_node->mpath = mpath;
791
	hash_idx = mesh_table_hash(mpath->dst, mpath->sdata, newtbl);
792 793
	hlist_add_head(&new_node->list,
			&newtbl->hash_buckets[hash_idx]);
794
	return 0;
795 796 797 798
}

int mesh_pathtbl_init(void)
{
799 800 801 802
	struct mesh_table *tbl_path, *tbl_mpp;

	tbl_path = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
	if (!tbl_path)
803
		return -ENOMEM;
804 805 806
	tbl_path->free_node = &mesh_path_node_free;
	tbl_path->copy_node = &mesh_path_node_copy;
	tbl_path->mean_chain_len = MEAN_CHAIN_LEN;
807

808 809 810
	tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
	if (!tbl_mpp) {
		mesh_table_free(tbl_path, true);
811
		return -ENOMEM;
812
	}
813 814 815 816 817 818 819
	tbl_mpp->free_node = &mesh_path_node_free;
	tbl_mpp->copy_node = &mesh_path_node_copy;
	tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN;

	/* Need no locking since this is during init */
	RCU_INIT_POINTER(mesh_paths, tbl_path);
	RCU_INIT_POINTER(mpp_paths, tbl_mpp);
820

821 822 823
	return 0;
}

824
void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
825
{
826
	struct mesh_table *tbl;
827 828 829 830 831
	struct mesh_path *mpath;
	struct mpath_node *node;
	struct hlist_node *p;
	int i;

832 833 834
	rcu_read_lock();
	tbl = rcu_dereference(mesh_paths);
	for_each_mesh_entry(tbl, p, node, i) {
835
		if (node->mpath->sdata != sdata)
836 837 838 839 840
			continue;
		mpath = node->mpath;
		spin_lock_bh(&mpath->state_lock);
		if ((!(mpath->flags & MESH_PATH_RESOLVING)) &&
		    (!(mpath->flags & MESH_PATH_FIXED)) &&
841
		     time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) {
842
			spin_unlock_bh(&mpath->state_lock);
843
			mesh_path_del(mpath->dst, mpath->sdata);
844 845 846
		} else
			spin_unlock_bh(&mpath->state_lock);
	}
847
	rcu_read_unlock();
848 849 850 851
}

void mesh_pathtbl_unregister(void)
{
852 853 854
	/* no need for locking during exit path */
	mesh_table_free(rcu_dereference_raw(mesh_paths), true);
	mesh_table_free(rcu_dereference_raw(mpp_paths), true);
855
}