| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2008, 2009 open80211s Ltd. |
|---|
| 3 | 4 | * Author: Luis Carlos Cobo <luisca@cozybit.com> |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 6 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 7 | | - * published by the Free Software Foundation. |
|---|
| 8 | 5 | */ |
|---|
| 9 | 6 | |
|---|
| 10 | 7 | #include <linux/etherdevice.h> |
|---|
| .. | .. |
|---|
| 50 | 47 | mesh_path_free_rcu(tbl, mpath); |
|---|
| 51 | 48 | } |
|---|
| 52 | 49 | |
|---|
| 53 | | -static struct mesh_table *mesh_table_alloc(void) |
|---|
| 50 | +static void mesh_table_init(struct mesh_table *tbl) |
|---|
| 54 | 51 | { |
|---|
| 55 | | - struct mesh_table *newtbl; |
|---|
| 52 | + INIT_HLIST_HEAD(&tbl->known_gates); |
|---|
| 53 | + INIT_HLIST_HEAD(&tbl->walk_head); |
|---|
| 54 | + atomic_set(&tbl->entries, 0); |
|---|
| 55 | + spin_lock_init(&tbl->gates_lock); |
|---|
| 56 | + spin_lock_init(&tbl->walk_lock); |
|---|
| 56 | 57 | |
|---|
| 57 | | - newtbl = kmalloc(sizeof(struct mesh_table), GFP_ATOMIC); |
|---|
| 58 | | - if (!newtbl) |
|---|
| 59 | | - return NULL; |
|---|
| 60 | | - |
|---|
| 61 | | - INIT_HLIST_HEAD(&newtbl->known_gates); |
|---|
| 62 | | - INIT_HLIST_HEAD(&newtbl->walk_head); |
|---|
| 63 | | - atomic_set(&newtbl->entries, 0); |
|---|
| 64 | | - spin_lock_init(&newtbl->gates_lock); |
|---|
| 65 | | - spin_lock_init(&newtbl->walk_lock); |
|---|
| 66 | | - if (rhashtable_init(&newtbl->rhead, &mesh_rht_params)) { |
|---|
| 67 | | - kfree(newtbl); |
|---|
| 68 | | - return NULL; |
|---|
| 69 | | - } |
|---|
| 70 | | - |
|---|
| 71 | | - return newtbl; |
|---|
| 58 | + /* rhashtable_init() may fail only in case of wrong |
|---|
| 59 | + * mesh_rht_params |
|---|
| 60 | + */ |
|---|
| 61 | + WARN_ON(rhashtable_init(&tbl->rhead, &mesh_rht_params)); |
|---|
| 72 | 62 | } |
|---|
| 73 | 63 | |
|---|
| 74 | 64 | static void mesh_table_free(struct mesh_table *tbl) |
|---|
| 75 | 65 | { |
|---|
| 76 | 66 | rhashtable_free_and_destroy(&tbl->rhead, |
|---|
| 77 | 67 | mesh_path_rht_free, tbl); |
|---|
| 78 | | - kfree(tbl); |
|---|
| 79 | 68 | } |
|---|
| 80 | 69 | |
|---|
| 81 | 70 | /** |
|---|
| 82 | | - * |
|---|
| 83 | 71 | * mesh_path_assign_nexthop - update mesh path next hop |
|---|
| 84 | 72 | * |
|---|
| 85 | 73 | * @mpath: mesh path to update |
|---|
| .. | .. |
|---|
| 147 | 135 | } |
|---|
| 148 | 136 | |
|---|
| 149 | 137 | /** |
|---|
| 150 | | - * |
|---|
| 151 | 138 | * mesh_path_move_to_queue - Move or copy frames from one mpath queue to another |
|---|
| 152 | 139 | * |
|---|
| 153 | 140 | * This function is used to transfer or copy frames from an unresolved mpath to |
|---|
| .. | .. |
|---|
| 159 | 146 | * |
|---|
| 160 | 147 | * The gate mpath must be an active mpath with a valid mpath->next_hop. |
|---|
| 161 | 148 | * |
|---|
| 162 | | - * @mpath: An active mpath the frames will be sent to (i.e. the gate) |
|---|
| 149 | + * @gate_mpath: An active mpath the frames will be sent to (i.e. the gate) |
|---|
| 163 | 150 | * @from_mpath: The failed mpath |
|---|
| 164 | 151 | * @copy: When true, copy all the frames to the new mpath queue. When false, |
|---|
| 165 | 152 | * move them. |
|---|
| .. | .. |
|---|
| 221 | 208 | { |
|---|
| 222 | 209 | struct mesh_path *mpath; |
|---|
| 223 | 210 | |
|---|
| 224 | | - mpath = rhashtable_lookup_fast(&tbl->rhead, dst, mesh_rht_params); |
|---|
| 211 | + mpath = rhashtable_lookup(&tbl->rhead, dst, mesh_rht_params); |
|---|
| 225 | 212 | |
|---|
| 226 | 213 | if (mpath && mpath_expired(mpath)) { |
|---|
| 227 | 214 | spin_lock_bh(&mpath->state_lock); |
|---|
| .. | .. |
|---|
| 243 | 230 | struct mesh_path * |
|---|
| 244 | 231 | mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) |
|---|
| 245 | 232 | { |
|---|
| 246 | | - return mpath_lookup(sdata->u.mesh.mesh_paths, dst, sdata); |
|---|
| 233 | + return mpath_lookup(&sdata->u.mesh.mesh_paths, dst, sdata); |
|---|
| 247 | 234 | } |
|---|
| 248 | 235 | |
|---|
| 249 | 236 | struct mesh_path * |
|---|
| 250 | 237 | mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) |
|---|
| 251 | 238 | { |
|---|
| 252 | | - return mpath_lookup(sdata->u.mesh.mpp_paths, dst, sdata); |
|---|
| 239 | + return mpath_lookup(&sdata->u.mesh.mpp_paths, dst, sdata); |
|---|
| 253 | 240 | } |
|---|
| 254 | 241 | |
|---|
| 255 | 242 | static struct mesh_path * |
|---|
| .. | .. |
|---|
| 286 | 273 | struct mesh_path * |
|---|
| 287 | 274 | mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) |
|---|
| 288 | 275 | { |
|---|
| 289 | | - return __mesh_path_lookup_by_idx(sdata->u.mesh.mesh_paths, idx); |
|---|
| 276 | + return __mesh_path_lookup_by_idx(&sdata->u.mesh.mesh_paths, idx); |
|---|
| 290 | 277 | } |
|---|
| 291 | 278 | |
|---|
| 292 | 279 | /** |
|---|
| .. | .. |
|---|
| 301 | 288 | struct mesh_path * |
|---|
| 302 | 289 | mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) |
|---|
| 303 | 290 | { |
|---|
| 304 | | - return __mesh_path_lookup_by_idx(sdata->u.mesh.mpp_paths, idx); |
|---|
| 291 | + return __mesh_path_lookup_by_idx(&sdata->u.mesh.mpp_paths, idx); |
|---|
| 305 | 292 | } |
|---|
| 306 | 293 | |
|---|
| 307 | 294 | /** |
|---|
| .. | .. |
|---|
| 314 | 301 | int err; |
|---|
| 315 | 302 | |
|---|
| 316 | 303 | rcu_read_lock(); |
|---|
| 317 | | - tbl = mpath->sdata->u.mesh.mesh_paths; |
|---|
| 304 | + tbl = &mpath->sdata->u.mesh.mesh_paths; |
|---|
| 318 | 305 | |
|---|
| 319 | 306 | spin_lock_bh(&mpath->state_lock); |
|---|
| 320 | 307 | if (mpath->is_gate) { |
|---|
| .. | .. |
|---|
| 408 | 395 | { |
|---|
| 409 | 396 | struct mesh_table *tbl; |
|---|
| 410 | 397 | struct mesh_path *mpath, *new_mpath; |
|---|
| 411 | | - int ret; |
|---|
| 412 | 398 | |
|---|
| 413 | 399 | if (ether_addr_equal(dst, sdata->vif.addr)) |
|---|
| 414 | 400 | /* never add ourselves as neighbours */ |
|---|
| .. | .. |
|---|
| 424 | 410 | if (!new_mpath) |
|---|
| 425 | 411 | return ERR_PTR(-ENOMEM); |
|---|
| 426 | 412 | |
|---|
| 427 | | - tbl = sdata->u.mesh.mesh_paths; |
|---|
| 413 | + tbl = &sdata->u.mesh.mesh_paths; |
|---|
| 428 | 414 | spin_lock_bh(&tbl->walk_lock); |
|---|
| 429 | | - do { |
|---|
| 430 | | - ret = rhashtable_lookup_insert_fast(&tbl->rhead, |
|---|
| 431 | | - &new_mpath->rhash, |
|---|
| 432 | | - mesh_rht_params); |
|---|
| 433 | | - |
|---|
| 434 | | - if (ret == -EEXIST) |
|---|
| 435 | | - mpath = rhashtable_lookup_fast(&tbl->rhead, |
|---|
| 436 | | - dst, |
|---|
| 437 | | - mesh_rht_params); |
|---|
| 438 | | - else if (!ret) |
|---|
| 439 | | - hlist_add_head(&new_mpath->walk_list, &tbl->walk_head); |
|---|
| 440 | | - } while (unlikely(ret == -EEXIST && !mpath)); |
|---|
| 415 | + mpath = rhashtable_lookup_get_insert_fast(&tbl->rhead, |
|---|
| 416 | + &new_mpath->rhash, |
|---|
| 417 | + mesh_rht_params); |
|---|
| 418 | + if (!mpath) |
|---|
| 419 | + hlist_add_head(&new_mpath->walk_list, &tbl->walk_head); |
|---|
| 441 | 420 | spin_unlock_bh(&tbl->walk_lock); |
|---|
| 442 | 421 | |
|---|
| 443 | | - if (ret) { |
|---|
| 422 | + if (mpath) { |
|---|
| 444 | 423 | kfree(new_mpath); |
|---|
| 445 | 424 | |
|---|
| 446 | | - if (ret != -EEXIST) |
|---|
| 447 | | - return ERR_PTR(ret); |
|---|
| 425 | + if (IS_ERR(mpath)) |
|---|
| 426 | + return mpath; |
|---|
| 448 | 427 | |
|---|
| 449 | 428 | new_mpath = mpath; |
|---|
| 450 | 429 | } |
|---|
| .. | .. |
|---|
| 473 | 452 | return -ENOMEM; |
|---|
| 474 | 453 | |
|---|
| 475 | 454 | memcpy(new_mpath->mpp, mpp, ETH_ALEN); |
|---|
| 476 | | - tbl = sdata->u.mesh.mpp_paths; |
|---|
| 455 | + tbl = &sdata->u.mesh.mpp_paths; |
|---|
| 477 | 456 | |
|---|
| 478 | 457 | spin_lock_bh(&tbl->walk_lock); |
|---|
| 479 | 458 | ret = rhashtable_lookup_insert_fast(&tbl->rhead, |
|---|
| .. | .. |
|---|
| 502 | 481 | void mesh_plink_broken(struct sta_info *sta) |
|---|
| 503 | 482 | { |
|---|
| 504 | 483 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
|---|
| 505 | | - struct mesh_table *tbl = sdata->u.mesh.mesh_paths; |
|---|
| 484 | + struct mesh_table *tbl = &sdata->u.mesh.mesh_paths; |
|---|
| 506 | 485 | static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
|---|
| 507 | 486 | struct mesh_path *mpath; |
|---|
| 508 | 487 | |
|---|
| .. | .. |
|---|
| 561 | 540 | void mesh_path_flush_by_nexthop(struct sta_info *sta) |
|---|
| 562 | 541 | { |
|---|
| 563 | 542 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
|---|
| 564 | | - struct mesh_table *tbl = sdata->u.mesh.mesh_paths; |
|---|
| 543 | + struct mesh_table *tbl = &sdata->u.mesh.mesh_paths; |
|---|
| 565 | 544 | struct mesh_path *mpath; |
|---|
| 566 | 545 | struct hlist_node *n; |
|---|
| 567 | 546 | |
|---|
| .. | .. |
|---|
| 576 | 555 | static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata, |
|---|
| 577 | 556 | const u8 *proxy) |
|---|
| 578 | 557 | { |
|---|
| 579 | | - struct mesh_table *tbl = sdata->u.mesh.mpp_paths; |
|---|
| 558 | + struct mesh_table *tbl = &sdata->u.mesh.mpp_paths; |
|---|
| 580 | 559 | struct mesh_path *mpath; |
|---|
| 581 | 560 | struct hlist_node *n; |
|---|
| 582 | 561 | |
|---|
| .. | .. |
|---|
| 610 | 589 | */ |
|---|
| 611 | 590 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) |
|---|
| 612 | 591 | { |
|---|
| 613 | | - table_flush_by_iface(sdata->u.mesh.mesh_paths); |
|---|
| 614 | | - table_flush_by_iface(sdata->u.mesh.mpp_paths); |
|---|
| 592 | + table_flush_by_iface(&sdata->u.mesh.mesh_paths); |
|---|
| 593 | + table_flush_by_iface(&sdata->u.mesh.mpp_paths); |
|---|
| 615 | 594 | } |
|---|
| 616 | 595 | |
|---|
| 617 | 596 | /** |
|---|
| .. | .. |
|---|
| 657 | 636 | /* flush relevant mpp entries first */ |
|---|
| 658 | 637 | mpp_flush_by_proxy(sdata, addr); |
|---|
| 659 | 638 | |
|---|
| 660 | | - err = table_path_del(sdata->u.mesh.mesh_paths, sdata, addr); |
|---|
| 639 | + err = table_path_del(&sdata->u.mesh.mesh_paths, sdata, addr); |
|---|
| 661 | 640 | sdata->u.mesh.mesh_paths_generation++; |
|---|
| 662 | 641 | return err; |
|---|
| 663 | 642 | } |
|---|
| .. | .. |
|---|
| 695 | 674 | struct mesh_path *gate; |
|---|
| 696 | 675 | bool copy = false; |
|---|
| 697 | 676 | |
|---|
| 698 | | - tbl = sdata->u.mesh.mesh_paths; |
|---|
| 677 | + tbl = &sdata->u.mesh.mesh_paths; |
|---|
| 699 | 678 | |
|---|
| 700 | 679 | rcu_read_lock(); |
|---|
| 701 | 680 | hlist_for_each_entry_rcu(gate, &tbl->known_gates, gate_list) { |
|---|
| .. | .. |
|---|
| 731 | 710 | void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, |
|---|
| 732 | 711 | struct sk_buff *skb) |
|---|
| 733 | 712 | { |
|---|
| 734 | | - kfree_skb(skb); |
|---|
| 713 | + ieee80211_free_txskb(&sdata->local->hw, skb); |
|---|
| 735 | 714 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
|---|
| 736 | 715 | } |
|---|
| 737 | 716 | |
|---|
| .. | .. |
|---|
| 775 | 754 | mesh_path_tx_pending(mpath); |
|---|
| 776 | 755 | } |
|---|
| 777 | 756 | |
|---|
| 778 | | -int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata) |
|---|
| 757 | +void mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata) |
|---|
| 779 | 758 | { |
|---|
| 780 | | - struct mesh_table *tbl_path, *tbl_mpp; |
|---|
| 781 | | - int ret; |
|---|
| 782 | | - |
|---|
| 783 | | - tbl_path = mesh_table_alloc(); |
|---|
| 784 | | - if (!tbl_path) |
|---|
| 785 | | - return -ENOMEM; |
|---|
| 786 | | - |
|---|
| 787 | | - tbl_mpp = mesh_table_alloc(); |
|---|
| 788 | | - if (!tbl_mpp) { |
|---|
| 789 | | - ret = -ENOMEM; |
|---|
| 790 | | - goto free_path; |
|---|
| 791 | | - } |
|---|
| 792 | | - |
|---|
| 793 | | - sdata->u.mesh.mesh_paths = tbl_path; |
|---|
| 794 | | - sdata->u.mesh.mpp_paths = tbl_mpp; |
|---|
| 795 | | - |
|---|
| 796 | | - return 0; |
|---|
| 797 | | - |
|---|
| 798 | | -free_path: |
|---|
| 799 | | - mesh_table_free(tbl_path); |
|---|
| 800 | | - return ret; |
|---|
| 759 | + mesh_table_init(&sdata->u.mesh.mesh_paths); |
|---|
| 760 | + mesh_table_init(&sdata->u.mesh.mpp_paths); |
|---|
| 801 | 761 | } |
|---|
| 802 | 762 | |
|---|
| 803 | 763 | static |
|---|
| .. | .. |
|---|
| 819 | 779 | |
|---|
| 820 | 780 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata) |
|---|
| 821 | 781 | { |
|---|
| 822 | | - mesh_path_tbl_expire(sdata, sdata->u.mesh.mesh_paths); |
|---|
| 823 | | - mesh_path_tbl_expire(sdata, sdata->u.mesh.mpp_paths); |
|---|
| 782 | + mesh_path_tbl_expire(sdata, &sdata->u.mesh.mesh_paths); |
|---|
| 783 | + mesh_path_tbl_expire(sdata, &sdata->u.mesh.mpp_paths); |
|---|
| 824 | 784 | } |
|---|
| 825 | 785 | |
|---|
| 826 | 786 | void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata) |
|---|
| 827 | 787 | { |
|---|
| 828 | | - mesh_table_free(sdata->u.mesh.mesh_paths); |
|---|
| 829 | | - mesh_table_free(sdata->u.mesh.mpp_paths); |
|---|
| 788 | + mesh_table_free(&sdata->u.mesh.mesh_paths); |
|---|
| 789 | + mesh_table_free(&sdata->u.mesh.mpp_paths); |
|---|
| 830 | 790 | } |
|---|