struct mesh_path *mpath;
};
-static struct mesh_table __rcu *mesh_paths;
-static struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */
-
-int mesh_paths_generation;
-int mpp_paths_generation;
-
-/* This lock will have the grow table function as writer and add / delete nodes
- * as readers. RCU provides sufficient protection only when reading the table
- * (i.e. doing lookups). Adding or adding or removing nodes requires we take
- * the read lock or we risk operating on an old table. The write lock is only
- * needed when modifying the number of buckets a table.
- */
-static DEFINE_RWLOCK(pathtbl_resize_lock);
-
-
static inline struct mesh_table *resize_dereference_paths(
+ struct ieee80211_sub_if_data *sdata,
struct mesh_table __rcu *table)
{
return rcu_dereference_protected(table,
- lockdep_is_held(&pathtbl_resize_lock));
+ lockdep_is_held(&sdata->u.mesh.pathtbl_resize_lock));
}
-static inline struct mesh_table *resize_dereference_mesh_paths(void)
+static inline struct mesh_table *resize_dereference_mesh_paths(
+ struct ieee80211_sub_if_data *sdata)
{
- return resize_dereference_paths(mesh_paths);
+ return resize_dereference_paths(sdata, sdata->u.mesh.mesh_paths);
}
-static inline struct mesh_table *resize_dereference_mpp_paths(void)
+static inline struct mesh_table *resize_dereference_mpp_paths(
+ struct ieee80211_sub_if_data *sdata)
{
- return resize_dereference_paths(mpp_paths);
+ return resize_dereference_paths(sdata, sdata->u.mesh.mpp_paths);
}
/*
bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)];
hlist_for_each_entry_rcu(node, bucket, list) {
mpath = node->mpath;
- if (mpath->sdata == sdata &&
- ether_addr_equal(dst, mpath->dst)) {
+ if (ether_addr_equal(dst, mpath->dst)) {
if (mpath_expired(mpath)) {
spin_lock_bh(&mpath->state_lock);
mpath->flags &= ~MESH_PATH_ACTIVE;
struct mesh_path *
mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst)
{
- return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata);
+ return mpath_lookup(rcu_dereference(sdata->u.mesh.mesh_paths), dst,
+ sdata);
}
struct mesh_path *
mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst)
{
- return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata);
+ return mpath_lookup(rcu_dereference(sdata->u.mesh.mpp_paths), dst,
+ sdata);
}
struct mesh_path *
mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx)
{
- struct mesh_table *tbl = rcu_dereference(mesh_paths);
+ struct mesh_table *tbl = rcu_dereference(sdata->u.mesh.mesh_paths);
struct mpath_node *node;
int i;
int j = 0;
for_each_mesh_entry(tbl, node, i) {
- if (sdata && node->mpath->sdata != sdata)
- continue;
if (j++ == idx) {
if (mpath_expired(node->mpath)) {
spin_lock_bh(&node->mpath->state_lock);
struct mesh_path *
mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx)
{
- struct mesh_table *tbl = rcu_dereference(mpp_paths);
+ struct mesh_table *tbl = rcu_dereference(sdata->u.mesh.mpp_paths);
struct mpath_node *node;
int i;
int j = 0;
for_each_mesh_entry(tbl, node, i) {
- if (sdata && node->mpath->sdata != sdata)
- continue;
if (j++ == idx)
return node->mpath;
}
int err;
rcu_read_lock();
- tbl = rcu_dereference(mesh_paths);
+ tbl = rcu_dereference(mpath->sdata->u.mesh.mesh_paths);
hlist_for_each_entry_rcu(gate, tbl->known_gates, list)
if (gate->mpath == mpath) {
if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0)
return ERR_PTR(-ENOSPC);
- read_lock_bh(&pathtbl_resize_lock);
- tbl = resize_dereference_mesh_paths();
+ read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
+ tbl = resize_dereference_mesh_paths(sdata);
hash_idx = mesh_table_hash(dst, sdata, tbl);
bucket = &tbl->hash_buckets[hash_idx];
hlist_for_each_entry(node, bucket, list) {
mpath = node->mpath;
- if (mpath->sdata == sdata &&
- ether_addr_equal(dst, mpath->dst))
+ if (ether_addr_equal(dst, mpath->dst))
goto found;
}
MEAN_CHAIN_LEN * (tbl->hash_mask + 1))
grow = 1;
- mesh_paths_generation++;
+ sdata->u.mesh.mesh_paths_generation++;
if (grow) {
set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
mpath = new_mpath;
found:
spin_unlock(&tbl->hashwlock[hash_idx]);
- read_unlock_bh(&pathtbl_resize_lock);
+ read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
return mpath;
err_node_alloc:
err_path_alloc:
atomic_dec(&sdata->u.mesh.mpaths);
spin_unlock(&tbl->hashwlock[hash_idx]);
- read_unlock_bh(&pathtbl_resize_lock);
+ read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
return ERR_PTR(err);
}
mesh_table_free(tbl, false);
}
-void mesh_mpath_table_grow(void)
+void mesh_mpath_table_grow(struct ieee80211_sub_if_data *sdata)
{
struct mesh_table *oldtbl, *newtbl;
- write_lock_bh(&pathtbl_resize_lock);
- oldtbl = resize_dereference_mesh_paths();
+ write_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
+ oldtbl = resize_dereference_mesh_paths(sdata);
newtbl = mesh_table_alloc(oldtbl->size_order + 1);
if (!newtbl)
goto out;
__mesh_table_free(newtbl);
goto out;
}
- rcu_assign_pointer(mesh_paths, newtbl);
+ rcu_assign_pointer(sdata->u.mesh.mesh_paths, newtbl);
call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu);
out:
- write_unlock_bh(&pathtbl_resize_lock);
+ write_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
}
-void mesh_mpp_table_grow(void)
+void mesh_mpp_table_grow(struct ieee80211_sub_if_data *sdata)
{
struct mesh_table *oldtbl, *newtbl;
- write_lock_bh(&pathtbl_resize_lock);
- oldtbl = resize_dereference_mpp_paths();
+ write_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
+ oldtbl = resize_dereference_mpp_paths(sdata);
newtbl = mesh_table_alloc(oldtbl->size_order + 1);
if (!newtbl)
goto out;
__mesh_table_free(newtbl);
goto out;
}
- rcu_assign_pointer(mpp_paths, newtbl);
+ rcu_assign_pointer(sdata->u.mesh.mpp_paths, newtbl);
call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu);
out:
- write_unlock_bh(&pathtbl_resize_lock);
+ write_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
}
int mpp_path_add(struct ieee80211_sub_if_data *sdata,
if (!new_node)
goto err_node_alloc;
- read_lock_bh(&pathtbl_resize_lock);
+ read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
memcpy(new_mpath->dst, dst, ETH_ALEN);
memcpy(new_mpath->mpp, mpp, ETH_ALEN);
new_mpath->sdata = sdata;
new_mpath->exp_time = jiffies;
spin_lock_init(&new_mpath->state_lock);
- tbl = resize_dereference_mpp_paths();
+ tbl = resize_dereference_mpp_paths(sdata);
hash_idx = mesh_table_hash(dst, sdata, tbl);
bucket = &tbl->hash_buckets[hash_idx];
err = -EEXIST;
hlist_for_each_entry(node, bucket, list) {
mpath = node->mpath;
- if (mpath->sdata == sdata &&
- ether_addr_equal(dst, mpath->dst))
+ if (ether_addr_equal(dst, mpath->dst))
goto err_exists;
}
grow = 1;
spin_unlock(&tbl->hashwlock[hash_idx]);
- read_unlock_bh(&pathtbl_resize_lock);
+ read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
- mpp_paths_generation++;
+ sdata->u.mesh.mpp_paths_generation++;
if (grow) {
set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
err_exists:
spin_unlock(&tbl->hashwlock[hash_idx]);
- read_unlock_bh(&pathtbl_resize_lock);
+ read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
kfree(new_node);
err_node_alloc:
kfree(new_mpath);
int i;
rcu_read_lock();
- tbl = rcu_dereference(mesh_paths);
+ tbl = rcu_dereference(sdata->u.mesh.mesh_paths);
for_each_mesh_entry(tbl, node, i) {
mpath = node->mpath;
if (rcu_access_pointer(mpath->next_hop) == sta &&
*/
void mesh_path_flush_by_nexthop(struct sta_info *sta)
{
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
struct mesh_table *tbl;
struct mesh_path *mpath;
struct mpath_node *node;
int i;
rcu_read_lock();
- read_lock_bh(&pathtbl_resize_lock);
- tbl = resize_dereference_mesh_paths();
+ read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
+ tbl = resize_dereference_mesh_paths(sdata);
for_each_mesh_entry(tbl, node, i) {
mpath = node->mpath;
if (rcu_access_pointer(mpath->next_hop) == sta) {
spin_unlock(&tbl->hashwlock[i]);
}
}
- read_unlock_bh(&pathtbl_resize_lock);
+ read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
rcu_read_unlock();
}
int i;
rcu_read_lock();
- read_lock_bh(&pathtbl_resize_lock);
- tbl = resize_dereference_mpp_paths();
+ read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
+ tbl = resize_dereference_mpp_paths(sdata);
for_each_mesh_entry(tbl, node, i) {
mpp = node->mpath;
if (ether_addr_equal(mpp->mpp, proxy)) {
spin_unlock(&tbl->hashwlock[i]);
}
}
- read_unlock_bh(&pathtbl_resize_lock);
+ read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
rcu_read_unlock();
}
WARN_ON(!rcu_read_lock_held());
for_each_mesh_entry(tbl, node, i) {
mpath = node->mpath;
- if (mpath->sdata != sdata)
- continue;
spin_lock_bh(&tbl->hashwlock[i]);
__mesh_path_del(tbl, node);
spin_unlock_bh(&tbl->hashwlock[i]);
struct mesh_table *tbl;
rcu_read_lock();
- read_lock_bh(&pathtbl_resize_lock);
- tbl = resize_dereference_mesh_paths();
+ read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
+ tbl = resize_dereference_mesh_paths(sdata);
table_flush_by_iface(tbl, sdata);
- tbl = resize_dereference_mpp_paths();
+ tbl = resize_dereference_mpp_paths(sdata);
table_flush_by_iface(tbl, sdata);
- read_unlock_bh(&pathtbl_resize_lock);
+ read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
rcu_read_unlock();
}
int hash_idx;
int err = 0;
- tbl = resize_dereference_paths(rcu_tbl);
+ tbl = resize_dereference_paths(sdata, rcu_tbl);
hash_idx = mesh_table_hash(addr, sdata, tbl);
bucket = &tbl->hash_buckets[hash_idx];
spin_lock(&tbl->hashwlock[hash_idx]);
hlist_for_each_entry(node, bucket, list) {
mpath = node->mpath;
- if (mpath->sdata == sdata &&
- ether_addr_equal(addr, mpath->dst)) {
+ if (ether_addr_equal(addr, mpath->dst)) {
__mesh_path_del(tbl, node);
goto enddel;
}
/* flush relevant mpp entries first */
mpp_flush_by_proxy(sdata, addr);
- read_lock_bh(&pathtbl_resize_lock);
- err = table_path_del(mesh_paths, sdata, addr);
- mesh_paths_generation++;
- read_unlock_bh(&pathtbl_resize_lock);
+ read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
+ err = table_path_del(sdata->u.mesh.mesh_paths, sdata, addr);
+ sdata->u.mesh.mesh_paths_generation++;
+ read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
return err;
}
{
int err = 0;
- read_lock_bh(&pathtbl_resize_lock);
- err = table_path_del(mpp_paths, sdata, addr);
- mpp_paths_generation++;
- read_unlock_bh(&pathtbl_resize_lock);
+ read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
+ err = table_path_del(sdata->u.mesh.mpp_paths, sdata, addr);
+ sdata->u.mesh.mpp_paths_generation++;
+ read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
return err;
}
struct hlist_head *known_gates;
rcu_read_lock();
- tbl = rcu_dereference(mesh_paths);
+ tbl = rcu_dereference(sdata->u.mesh.mesh_paths);
known_gates = tbl->known_gates;
rcu_read_unlock();
return -EHOSTUNREACH;
hlist_for_each_entry_rcu(gate, known_gates, list) {
- if (gate->mpath->sdata != sdata)
- continue;
-
if (gate->mpath->flags & MESH_PATH_ACTIVE) {
mpath_dbg(sdata, "Forwarding to %pM\n", gate->mpath->dst);
mesh_path_move_to_queue(gate->mpath, from_mpath, copy);
}
}
- hlist_for_each_entry_rcu(gate, known_gates, list)
- if (gate->mpath->sdata == sdata) {
- mpath_dbg(sdata, "Sending to %pM\n", gate->mpath->dst);
- mesh_path_tx_pending(gate->mpath);
- }
+ hlist_for_each_entry_rcu(gate, known_gates, list) {
+ mpath_dbg(sdata, "Sending to %pM\n", gate->mpath->dst);
+ mesh_path_tx_pending(gate->mpath);
+ }
return (from_mpath == mpath) ? -EHOSTUNREACH : 0;
}
return 0;
}
-int mesh_pathtbl_init(void)
+int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata)
{
struct mesh_table *tbl_path, *tbl_mpp;
int ret;
}
INIT_HLIST_HEAD(tbl_mpp->known_gates);
+ rwlock_init(&sdata->u.mesh.pathtbl_resize_lock);
+
/* Need no locking since this is during init */
- RCU_INIT_POINTER(mesh_paths, tbl_path);
- RCU_INIT_POINTER(mpp_paths, tbl_mpp);
+ RCU_INIT_POINTER(sdata->u.mesh.mesh_paths, tbl_path);
+ RCU_INIT_POINTER(sdata->u.mesh.mpp_paths, tbl_mpp);
return 0;
int i;
rcu_read_lock();
- tbl = rcu_dereference(mesh_paths);
+ tbl = rcu_dereference(sdata->u.mesh.mesh_paths);
for_each_mesh_entry(tbl, node, i) {
- if (node->mpath->sdata != sdata)
- continue;
mpath = node->mpath;
if ((!(mpath->flags & MESH_PATH_RESOLVING)) &&
(!(mpath->flags & MESH_PATH_FIXED)) &&
time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
- mesh_path_del(mpath->sdata, mpath->dst);
+ mesh_path_del(sdata, mpath->dst);
}
- tbl = rcu_dereference(mpp_paths);
+ tbl = rcu_dereference(sdata->u.mesh.mpp_paths);
for_each_mesh_entry(tbl, node, i) {
- if (node->mpath->sdata != sdata)
- continue;
mpath = node->mpath;
if ((!(mpath->flags & MESH_PATH_FIXED)) &&
time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
- mpp_path_del(mpath->sdata, mpath->dst);
+ mpp_path_del(sdata, mpath->dst);
}
rcu_read_unlock();
}
-void mesh_pathtbl_unregister(void)
+void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata)
{
/* no need for locking during exit path */
- mesh_table_free(rcu_dereference_protected(mesh_paths, 1), true);
- mesh_table_free(rcu_dereference_protected(mpp_paths, 1), true);
+ mesh_table_free(rcu_dereference_protected(sdata->u.mesh.mesh_paths, 1),
+ true);
+ mesh_table_free(rcu_dereference_protected(sdata->u.mesh.mpp_paths, 1),
+ true);
}