diff options
-rw-r--r-- | net/mac80211/cfg.c | 12 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 3 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 22 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 56 |
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); | |||
275 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); | 275 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); |
276 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, | 276 | void 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); |
278 | int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst); | 278 | struct mesh_path * |
279 | mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst); | ||
279 | 280 | ||
280 | int mesh_path_add_gate(struct mesh_path *mpath); | 281 | int mesh_path_add_gate(struct mesh_path *mpath); |
281 | int mesh_path_send_to_gates(struct mesh_path *mpath); | 282 | int 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 | */ |
496 | int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) | 496 | struct 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 | 568 | found: | |
571 | err_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 | |||
575 | err_node_alloc: | 573 | err_node_alloc: |
576 | kfree(new_mpath); | 574 | kfree(new_mpath); |
577 | err_path_alloc: | 575 | err_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 | ||
582 | static void mesh_table_free_rcu(struct rcu_head *rcu) | 582 | static void mesh_table_free_rcu(struct rcu_head *rcu) |