aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c12
-rw-r--r--net/mac80211/mesh.h3
-rw-r--r--net/mac80211/mesh_hwmp.c22
-rw-r--r--net/mac80211/mesh_pathtbl.c56
4 files changed, 42 insertions, 51 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6e43feb49a76..edca2a288abd 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1540,7 +1540,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
1540 struct ieee80211_sub_if_data *sdata; 1540 struct ieee80211_sub_if_data *sdata;
1541 struct mesh_path *mpath; 1541 struct mesh_path *mpath;
1542 struct sta_info *sta; 1542 struct sta_info *sta;
1543 int err;
1544 1543
1545 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1544 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1546 1545
@@ -1551,17 +1550,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
1551 return -ENOENT; 1550 return -ENOENT;
1552 } 1551 }
1553 1552
1554 err = mesh_path_add(sdata, dst); 1553 mpath = mesh_path_add(sdata, dst);
1555 if (err) { 1554 if (IS_ERR(mpath)) {
1556 rcu_read_unlock(); 1555 rcu_read_unlock();
1557 return err; 1556 return PTR_ERR(mpath);
1558 } 1557 }
1559 1558
1560 mpath = mesh_path_lookup(sdata, dst);
1561 if (!mpath) {
1562 rcu_read_unlock();
1563 return -ENXIO;
1564 }
1565 mesh_path_fix_nexthop(mpath, sta); 1559 mesh_path_fix_nexthop(mpath, sta);
1566 1560
1567 rcu_read_unlock(); 1561 rcu_read_unlock();
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 6ffabbe99c46..da158774eebb 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -275,7 +275,8 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
275void mesh_path_expire(struct ieee80211_sub_if_data *sdata); 275void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
276void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, 276void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
277 struct ieee80211_mgmt *mgmt, size_t len); 277 struct ieee80211_mgmt *mgmt, size_t len);
278int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst); 278struct mesh_path *
279mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst);
279 280
280int mesh_path_add_gate(struct mesh_path *mpath); 281int mesh_path_add_gate(struct mesh_path *mpath);
281int mesh_path_send_to_gates(struct mesh_path *mpath); 282int mesh_path_send_to_gates(struct mesh_path *mpath);
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 94904337784c..c82d5e6a24c0 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -445,9 +445,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
445 } 445 }
446 } 446 }
447 } else { 447 } else {
448 mesh_path_add(sdata, orig_addr); 448 mpath = mesh_path_add(sdata, orig_addr);
449 mpath = mesh_path_lookup(sdata, orig_addr); 449 if (IS_ERR(mpath)) {
450 if (!mpath) {
451 rcu_read_unlock(); 450 rcu_read_unlock();
452 return 0; 451 return 0;
453 } 452 }
@@ -486,9 +485,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
486 (last_hop_metric > mpath->metric))) 485 (last_hop_metric > mpath->metric)))
487 fresh_info = false; 486 fresh_info = false;
488 } else { 487 } else {
489 mesh_path_add(sdata, ta); 488 mpath = mesh_path_add(sdata, ta);
490 mpath = mesh_path_lookup(sdata, ta); 489 if (IS_ERR(mpath)) {
491 if (!mpath) {
492 rcu_read_unlock(); 490 rcu_read_unlock();
493 return 0; 491 return 0;
494 } 492 }
@@ -804,9 +802,8 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
804 802
805 mpath = mesh_path_lookup(sdata, orig_addr); 803 mpath = mesh_path_lookup(sdata, orig_addr);
806 if (!mpath) { 804 if (!mpath) {
807 mesh_path_add(sdata, orig_addr); 805 mpath = mesh_path_add(sdata, orig_addr);
808 mpath = mesh_path_lookup(sdata, orig_addr); 806 if (IS_ERR(mpath)) {
809 if (!mpath) {
810 rcu_read_unlock(); 807 rcu_read_unlock();
811 sdata->u.mesh.mshstats.dropped_frames_no_route++; 808 sdata->u.mesh.mshstats.dropped_frames_no_route++;
812 return; 809 return;
@@ -1098,11 +1095,10 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
1098 /* no nexthop found, start resolving */ 1095 /* no nexthop found, start resolving */
1099 mpath = mesh_path_lookup(sdata, target_addr); 1096 mpath = mesh_path_lookup(sdata, target_addr);
1100 if (!mpath) { 1097 if (!mpath) {
1101 mesh_path_add(sdata, target_addr); 1098 mpath = mesh_path_add(sdata, target_addr);
1102 mpath = mesh_path_lookup(sdata, target_addr); 1099 if (IS_ERR(mpath)) {
1103 if (!mpath) {
1104 mesh_path_discard_frame(sdata, skb); 1100 mesh_path_discard_frame(sdata, skb);
1105 err = -ENOSPC; 1101 err = PTR_ERR(mpath);
1106 goto endlookup; 1102 goto endlookup;
1107 } 1103 }
1108 } 1104 }
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index dc7c8df40c2c..89aacfd2756d 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -493,7 +493,8 @@ int mesh_gate_num(struct ieee80211_sub_if_data *sdata)
493 * 493 *
494 * State: the initial state of the new path is set to 0 494 * State: the initial state of the new path is set to 0
495 */ 495 */
496int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) 496struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
497 const u8 *dst)
497{ 498{
498 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 499 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
499 struct ieee80211_local *local = sdata->local; 500 struct ieee80211_local *local = sdata->local;
@@ -502,18 +503,33 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
502 struct mpath_node *node, *new_node; 503 struct mpath_node *node, *new_node;
503 struct hlist_head *bucket; 504 struct hlist_head *bucket;
504 int grow = 0; 505 int grow = 0;
505 int err = 0; 506 int err;
506 u32 hash_idx; 507 u32 hash_idx;
507 508
508 if (ether_addr_equal(dst, sdata->vif.addr)) 509 if (ether_addr_equal(dst, sdata->vif.addr))
509 /* never add ourselves as neighbours */ 510 /* never add ourselves as neighbours */
510 return -ENOTSUPP; 511 return ERR_PTR(-ENOTSUPP);
511 512
512 if (is_multicast_ether_addr(dst)) 513 if (is_multicast_ether_addr(dst))
513 return -ENOTSUPP; 514 return ERR_PTR(-ENOTSUPP);
514 515
515 if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) 516 if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0)
516 return -ENOSPC; 517 return ERR_PTR(-ENOSPC);
518
519 read_lock_bh(&pathtbl_resize_lock);
520 tbl = resize_dereference_mesh_paths();
521
522 hash_idx = mesh_table_hash(dst, sdata, tbl);
523 bucket = &tbl->hash_buckets[hash_idx];
524
525 spin_lock(&tbl->hashwlock[hash_idx]);
526
527 hlist_for_each_entry(node, bucket, list) {
528 mpath = node->mpath;
529 if (mpath->sdata == sdata &&
530 ether_addr_equal(dst, mpath->dst))
531 goto found;
532 }
517 533
518 err = -ENOMEM; 534 err = -ENOMEM;
519 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC); 535 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
@@ -524,7 +540,6 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
524 if (!new_node) 540 if (!new_node)
525 goto err_node_alloc; 541 goto err_node_alloc;
526 542
527 read_lock_bh(&pathtbl_resize_lock);
528 memcpy(new_mpath->dst, dst, ETH_ALEN); 543 memcpy(new_mpath->dst, dst, ETH_ALEN);
529 eth_broadcast_addr(new_mpath->rann_snd_addr); 544 eth_broadcast_addr(new_mpath->rann_snd_addr);
530 new_mpath->is_root = false; 545 new_mpath->is_root = false;
@@ -538,21 +553,6 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
538 spin_lock_init(&new_mpath->state_lock); 553 spin_lock_init(&new_mpath->state_lock);
539 init_timer(&new_mpath->timer); 554 init_timer(&new_mpath->timer);
540 555
541 tbl = resize_dereference_mesh_paths();
542
543 hash_idx = mesh_table_hash(dst, sdata, tbl);
544 bucket = &tbl->hash_buckets[hash_idx];
545
546 spin_lock(&tbl->hashwlock[hash_idx]);
547
548 err = -EEXIST;
549 hlist_for_each_entry(node, bucket, list) {
550 mpath = node->mpath;
551 if (mpath->sdata == sdata &&
552 ether_addr_equal(dst, mpath->dst))
553 goto err_exists;
554 }
555
556 hlist_add_head_rcu(&new_node->list, bucket); 556 hlist_add_head_rcu(&new_node->list, bucket);
557 if (atomic_inc_return(&tbl->entries) >= 557 if (atomic_inc_return(&tbl->entries) >=
558 tbl->mean_chain_len * (tbl->hash_mask + 1)) 558 tbl->mean_chain_len * (tbl->hash_mask + 1))
@@ -560,23 +560,23 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
560 560
561 mesh_paths_generation++; 561 mesh_paths_generation++;
562 562
563 spin_unlock(&tbl->hashwlock[hash_idx]);
564 read_unlock_bh(&pathtbl_resize_lock);
565 if (grow) { 563 if (grow) {
566 set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); 564 set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
567 ieee80211_queue_work(&local->hw, &sdata->work); 565 ieee80211_queue_work(&local->hw, &sdata->work);
568 } 566 }
569 return 0; 567 mpath = new_mpath;
570 568found:
571err_exists:
572 spin_unlock(&tbl->hashwlock[hash_idx]); 569 spin_unlock(&tbl->hashwlock[hash_idx]);
573 read_unlock_bh(&pathtbl_resize_lock); 570 read_unlock_bh(&pathtbl_resize_lock);
574 kfree(new_node); 571 return mpath;
572
575err_node_alloc: 573err_node_alloc:
576 kfree(new_mpath); 574 kfree(new_mpath);
577err_path_alloc: 575err_path_alloc:
578 atomic_dec(&sdata->u.mesh.mpaths); 576 atomic_dec(&sdata->u.mesh.mpaths);
579 return err; 577 spin_unlock(&tbl->hashwlock[hash_idx]);
578 read_unlock_bh(&pathtbl_resize_lock);
579 return ERR_PTR(err);
580} 580}
581 581
582static void mesh_table_free_rcu(struct rcu_head *rcu) 582static void mesh_table_free_rcu(struct rcu_head *rcu)