Skip to content

Commit 947c2a0

Browse files
bcopelandjmberg-intel
authored andcommitted
mac80211: mesh: embed known gates list in struct mesh_path
The mesh path table uses a struct mesh_node in its hlists in order to support a resizable hash table: the mesh_node provides an indirection to the actual mesh path so that two different bucket lists can point to the same path entry. However, for the known gates list, we don't need this indirection because there is ever only one list. So we can just embed the hlist_node in the mesh path itself, which simplifies things a bit and saves a linear search whenever we need to find an item in the list. Signed-off-by: Bob Copeland <[email protected]> Signed-off-by: Johannes Berg <[email protected]>
1 parent b15dc38 commit 947c2a0

File tree

2 files changed

+45
-56
lines changed

2 files changed

+45
-56
lines changed

net/mac80211/mesh.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ enum mesh_deferred_task_flags {
105105
struct mesh_path {
106106
u8 dst[ETH_ALEN];
107107
u8 mpp[ETH_ALEN]; /* used for MPP or MAP */
108+
struct hlist_node gate_list;
108109
struct ieee80211_sub_if_data *sdata;
109110
struct sta_info __rcu *next_hop;
110111
struct timer_list timer;

net/mac80211/mesh_pathtbl.c

Lines changed: 44 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,18 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
119119
{
120120
struct hlist_head *mesh_hash;
121121
struct hlist_node *p, *q;
122-
struct mpath_node *gate;
122+
struct mesh_path *gate;
123123
int i;
124124

125125
mesh_hash = tbl->hash_buckets;
126+
if (free_leafs) {
127+
spin_lock_bh(&tbl->gates_lock);
128+
hlist_for_each_entry_safe(gate, q,
129+
tbl->known_gates, gate_list)
130+
hlist_del(&gate->gate_list);
131+
kfree(tbl->known_gates);
132+
spin_unlock_bh(&tbl->gates_lock);
133+
}
126134
for (i = 0; i <= tbl->hash_mask; i++) {
127135
spin_lock_bh(&tbl->hashwlock[i]);
128136
hlist_for_each_safe(p, q, &mesh_hash[i]) {
@@ -131,16 +139,6 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
131139
}
132140
spin_unlock_bh(&tbl->hashwlock[i]);
133141
}
134-
if (free_leafs) {
135-
spin_lock_bh(&tbl->gates_lock);
136-
hlist_for_each_entry_safe(gate, q,
137-
tbl->known_gates, list) {
138-
hlist_del(&gate->list);
139-
kfree(gate);
140-
}
141-
kfree(tbl->known_gates);
142-
spin_unlock_bh(&tbl->gates_lock);
143-
}
144142

145143
__mesh_table_free(tbl);
146144
}
@@ -431,30 +429,26 @@ mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx)
431429
int mesh_path_add_gate(struct mesh_path *mpath)
432430
{
433431
struct mesh_table *tbl;
434-
struct mpath_node *gate, *new_gate;
435432
int err;
436433

437434
rcu_read_lock();
438435
tbl = rcu_dereference(mpath->sdata->u.mesh.mesh_paths);
439436

440-
hlist_for_each_entry_rcu(gate, tbl->known_gates, list)
441-
if (gate->mpath == mpath) {
442-
err = -EEXIST;
443-
goto err_rcu;
444-
}
445-
446-
new_gate = kzalloc(sizeof(struct mpath_node), GFP_ATOMIC);
447-
if (!new_gate) {
448-
err = -ENOMEM;
437+
spin_lock_bh(&mpath->state_lock);
438+
if (mpath->is_gate) {
439+
err = -EEXIST;
440+
spin_unlock_bh(&mpath->state_lock);
449441
goto err_rcu;
450442
}
451-
452443
mpath->is_gate = true;
453444
mpath->sdata->u.mesh.num_gates++;
454-
new_gate->mpath = mpath;
455-
spin_lock_bh(&tbl->gates_lock);
456-
hlist_add_head_rcu(&new_gate->list, tbl->known_gates);
457-
spin_unlock_bh(&tbl->gates_lock);
445+
446+
spin_lock(&tbl->gates_lock);
447+
hlist_add_head_rcu(&mpath->gate_list, tbl->known_gates);
448+
spin_unlock(&tbl->gates_lock);
449+
450+
spin_unlock_bh(&mpath->state_lock);
451+
458452
mpath_dbg(mpath->sdata,
459453
"Mesh path: Recorded new gate: %pM. %d known gates\n",
460454
mpath->dst, mpath->sdata->u.mesh.num_gates);
@@ -468,28 +462,22 @@ int mesh_path_add_gate(struct mesh_path *mpath)
468462
* mesh_gate_del - remove a mesh gate from the list of known gates
469463
* @tbl: table which holds our list of known gates
470464
* @mpath: gate mpath
471-
*
472-
* Locking: must be called inside rcu_read_lock() section
473465
*/
474466
static void mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath)
475467
{
476-
struct mpath_node *gate;
477-
struct hlist_node *q;
468+
lockdep_assert_held(&mpath->state_lock);
469+
if (!mpath->is_gate)
470+
return;
478471

479-
hlist_for_each_entry_safe(gate, q, tbl->known_gates, list) {
480-
if (gate->mpath != mpath)
481-
continue;
482-
spin_lock_bh(&tbl->gates_lock);
483-
hlist_del_rcu(&gate->list);
484-
kfree_rcu(gate, rcu);
485-
spin_unlock_bh(&tbl->gates_lock);
486-
mpath->sdata->u.mesh.num_gates--;
487-
mpath->is_gate = false;
488-
mpath_dbg(mpath->sdata,
489-
"Mesh path: Deleted gate: %pM. %d known gates\n",
490-
mpath->dst, mpath->sdata->u.mesh.num_gates);
491-
break;
492-
}
472+
mpath->is_gate = false;
473+
spin_lock_bh(&tbl->gates_lock);
474+
hlist_del_rcu(&mpath->gate_list);
475+
mpath->sdata->u.mesh.num_gates--;
476+
spin_unlock_bh(&tbl->gates_lock);
477+
478+
mpath_dbg(mpath->sdata,
479+
"Mesh path: Deleted gate: %pM. %d known gates\n",
480+
mpath->dst, mpath->sdata->u.mesh.num_gates);
493481
}
494482

495483
/**
@@ -781,13 +769,13 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node)
781769
struct mesh_path *mpath = node->mpath;
782770
struct ieee80211_sub_if_data *sdata = node->mpath->sdata;
783771

784-
spin_lock(&mpath->state_lock);
772+
spin_lock_bh(&mpath->state_lock);
785773
mpath->flags |= MESH_PATH_RESOLVING;
786774
if (mpath->is_gate)
787775
mesh_gate_del(tbl, mpath);
788776
hlist_del_rcu(&node->list);
789777
call_rcu(&node->rcu, mesh_path_node_reclaim);
790-
spin_unlock(&mpath->state_lock);
778+
spin_unlock_bh(&mpath->state_lock);
791779
atomic_dec(&sdata->u.mesh.mpaths);
792780
atomic_dec(&tbl->entries);
793781
}
@@ -999,7 +987,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath)
999987
struct ieee80211_sub_if_data *sdata = mpath->sdata;
1000988
struct mesh_table *tbl;
1001989
struct mesh_path *from_mpath = mpath;
1002-
struct mpath_node *gate = NULL;
990+
struct mesh_path *gate = NULL;
1003991
bool copy = false;
1004992
struct hlist_head *known_gates;
1005993

@@ -1011,22 +999,22 @@ int mesh_path_send_to_gates(struct mesh_path *mpath)
1011999
if (!known_gates)
10121000
return -EHOSTUNREACH;
10131001

1014-
hlist_for_each_entry_rcu(gate, known_gates, list) {
1015-
if (gate->mpath->flags & MESH_PATH_ACTIVE) {
1016-
mpath_dbg(sdata, "Forwarding to %pM\n", gate->mpath->dst);
1017-
mesh_path_move_to_queue(gate->mpath, from_mpath, copy);
1018-
from_mpath = gate->mpath;
1002+
hlist_for_each_entry_rcu(gate, known_gates, gate_list) {
1003+
if (gate->flags & MESH_PATH_ACTIVE) {
1004+
mpath_dbg(sdata, "Forwarding to %pM\n", gate->dst);
1005+
mesh_path_move_to_queue(gate, from_mpath, copy);
1006+
from_mpath = gate;
10191007
copy = true;
10201008
} else {
10211009
mpath_dbg(sdata,
10221010
"Not forwarding to %pM (flags %#x)\n",
1023-
gate->mpath->dst, gate->mpath->flags);
1011+
gate->dst, gate->flags);
10241012
}
10251013
}
10261014

1027-
hlist_for_each_entry_rcu(gate, known_gates, list) {
1028-
mpath_dbg(sdata, "Sending to %pM\n", gate->mpath->dst);
1029-
mesh_path_tx_pending(gate->mpath);
1015+
hlist_for_each_entry_rcu(gate, known_gates, gate_list) {
1016+
mpath_dbg(sdata, "Sending to %pM\n", gate->dst);
1017+
mesh_path_tx_pending(gate);
10301018
}
10311019

10321020
return (from_mpath == mpath) ? -EHOSTUNREACH : 0;

0 commit comments

Comments
 (0)