Commit 2bdaf386 authored by Bob Copeland's avatar Bob Copeland Committed by Johannes Berg

mac80211: mesh: move path tables into if_mesh

The mesh path and mesh gate hashtables are global, containing
all of the mpaths for every mesh interface, but the paths are
all tied logically to a single interface.  The common case is
just a single mesh interface, so optimize for that by moving
the global hashtable into the per-interface struct.

Doing so allows us to drop sdata pointer comparisons inside
the lookups and also saves a few bytes of BSS and data.
Signed-off-by: default avatarBob Copeland <me@bobcopeland.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 12880d16
...@@ -1499,7 +1499,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, ...@@ -1499,7 +1499,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
memset(pinfo, 0, sizeof(*pinfo)); memset(pinfo, 0, sizeof(*pinfo));
pinfo->generation = mesh_paths_generation; pinfo->generation = mpath->sdata->u.mesh.mesh_paths_generation;
pinfo->filled = MPATH_INFO_FRAME_QLEN | pinfo->filled = MPATH_INFO_FRAME_QLEN |
MPATH_INFO_SN | MPATH_INFO_SN |
...@@ -1577,7 +1577,7 @@ static void mpp_set_pinfo(struct mesh_path *mpath, u8 *mpp, ...@@ -1577,7 +1577,7 @@ static void mpp_set_pinfo(struct mesh_path *mpath, u8 *mpp,
memset(pinfo, 0, sizeof(*pinfo)); memset(pinfo, 0, sizeof(*pinfo));
memcpy(mpp, mpath->mpp, ETH_ALEN); memcpy(mpp, mpath->mpp, ETH_ALEN);
pinfo->generation = mpp_paths_generation; pinfo->generation = mpath->sdata->u.mesh.mpp_paths_generation;
} }
static int ieee80211_get_mpp(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_get_mpp(struct wiphy *wiphy, struct net_device *dev,
......
...@@ -696,6 +696,18 @@ struct ieee80211_if_mesh { ...@@ -696,6 +696,18 @@ struct ieee80211_if_mesh {
/* offset from skb->data while building IE */ /* offset from skb->data while building IE */
int meshconf_offset; int meshconf_offset;
struct mesh_table __rcu *mesh_paths;
struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */
int mesh_paths_generation;
int mpp_paths_generation;
/* Protects assignment of the mesh_paths/mpp_paths table
* pointer for resize against reading it for add/delete
* of individual paths. Pure readers (lookups) just use
* RCU.
*/
rwlock_t pathtbl_resize_lock;
}; };
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
......
...@@ -25,7 +25,6 @@ bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) ...@@ -25,7 +25,6 @@ bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
void ieee80211s_init(void) void ieee80211s_init(void)
{ {
mesh_pathtbl_init();
mesh_allocated = 1; mesh_allocated = 1;
rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry), rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry),
0, 0, NULL); 0, 0, NULL);
...@@ -35,7 +34,6 @@ void ieee80211s_stop(void) ...@@ -35,7 +34,6 @@ void ieee80211s_stop(void)
{ {
if (!mesh_allocated) if (!mesh_allocated)
return; return;
mesh_pathtbl_unregister();
kmem_cache_destroy(rm_cache); kmem_cache_destroy(rm_cache);
} }
...@@ -902,6 +900,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) ...@@ -902,6 +900,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
/* flush STAs and mpaths on this iface */ /* flush STAs and mpaths on this iface */
sta_info_flush(sdata); sta_info_flush(sdata);
mesh_path_flush_by_iface(sdata); mesh_path_flush_by_iface(sdata);
mesh_pathtbl_unregister(sdata);
/* free all potentially still buffered group-addressed frames */ /* free all potentially still buffered group-addressed frames */
local->total_ps_buffered -= skb_queue_len(&ifmsh->ps.bc_buf); local->total_ps_buffered -= skb_queue_len(&ifmsh->ps.bc_buf);
...@@ -1349,10 +1348,10 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) ...@@ -1349,10 +1348,10 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
mesh_path_start_discovery(sdata); mesh_path_start_discovery(sdata);
if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
mesh_mpath_table_grow(); mesh_mpath_table_grow(sdata);
if (test_and_clear_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags)) if (test_and_clear_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags))
mesh_mpp_table_grow(); mesh_mpp_table_grow(sdata);
if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
ieee80211_mesh_housekeeping(sdata); ieee80211_mesh_housekeeping(sdata);
...@@ -1388,6 +1387,9 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) ...@@ -1388,6 +1387,9 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
/* Allocate all mesh structures when creating the first mesh interface. */ /* Allocate all mesh structures when creating the first mesh interface. */
if (!mesh_allocated) if (!mesh_allocated)
ieee80211s_init(); ieee80211s_init();
mesh_pathtbl_init(sdata);
setup_timer(&ifmsh->mesh_path_timer, setup_timer(&ifmsh->mesh_path_timer,
ieee80211_mesh_path_timer, ieee80211_mesh_path_timer,
(unsigned long) sdata); (unsigned long) sdata);
......
...@@ -300,8 +300,8 @@ void mesh_sta_cleanup(struct sta_info *sta); ...@@ -300,8 +300,8 @@ void mesh_sta_cleanup(struct sta_info *sta);
/* Private interfaces */ /* Private interfaces */
/* Mesh tables */ /* Mesh tables */
void mesh_mpath_table_grow(void); void mesh_mpath_table_grow(struct ieee80211_sub_if_data *sdata);
void mesh_mpp_table_grow(void); void mesh_mpp_table_grow(struct ieee80211_sub_if_data *sdata);
/* Mesh paths */ /* Mesh paths */
int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
u8 ttl, const u8 *target, u32 target_sn, u8 ttl, const u8 *target, u32 target_sn,
...@@ -309,8 +309,8 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, ...@@ -309,8 +309,8 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta);
void mesh_path_flush_pending(struct mesh_path *mpath); void mesh_path_flush_pending(struct mesh_path *mpath);
void mesh_path_tx_pending(struct mesh_path *mpath); void mesh_path_tx_pending(struct mesh_path *mpath);
int mesh_pathtbl_init(void); int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata);
void mesh_pathtbl_unregister(void); void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata);
int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr); int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr);
void mesh_path_timer(unsigned long data); void mesh_path_timer(unsigned long data);
void mesh_path_flush_by_nexthop(struct sta_info *sta); void mesh_path_flush_by_nexthop(struct sta_info *sta);
...@@ -319,8 +319,6 @@ void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, ...@@ -319,8 +319,6 @@ void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata,
void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
extern int mesh_paths_generation;
extern int mpp_paths_generation;
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
static inline static inline
......
...@@ -40,36 +40,24 @@ struct mpath_node { ...@@ -40,36 +40,24 @@ struct mpath_node {
struct mesh_path *mpath; 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( static inline struct mesh_table *resize_dereference_paths(
struct ieee80211_sub_if_data *sdata,
struct mesh_table __rcu *table) struct mesh_table __rcu *table)
{ {
return rcu_dereference_protected(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);
} }
/* /*
...@@ -346,8 +334,7 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, ...@@ -346,8 +334,7 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)];
hlist_for_each_entry_rcu(node, bucket, list) { hlist_for_each_entry_rcu(node, bucket, list) {
mpath = node->mpath; mpath = node->mpath;
if (mpath->sdata == sdata && if (ether_addr_equal(dst, mpath->dst)) {
ether_addr_equal(dst, mpath->dst)) {
if (mpath_expired(mpath)) { if (mpath_expired(mpath)) {
spin_lock_bh(&mpath->state_lock); spin_lock_bh(&mpath->state_lock);
mpath->flags &= ~MESH_PATH_ACTIVE; mpath->flags &= ~MESH_PATH_ACTIVE;
...@@ -371,13 +358,15 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, ...@@ -371,13 +358,15 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
struct mesh_path * struct mesh_path *
mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) 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 * struct mesh_path *
mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) 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);
} }
...@@ -393,14 +382,12 @@ mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) ...@@ -393,14 +382,12 @@ mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst)
struct mesh_path * struct mesh_path *
mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) 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; struct mpath_node *node;
int i; int i;
int j = 0; int j = 0;
for_each_mesh_entry(tbl, node, i) { for_each_mesh_entry(tbl, node, i) {
if (sdata && node->mpath->sdata != sdata)
continue;
if (j++ == idx) { if (j++ == idx) {
if (mpath_expired(node->mpath)) { if (mpath_expired(node->mpath)) {
spin_lock_bh(&node->mpath->state_lock); spin_lock_bh(&node->mpath->state_lock);
...@@ -426,14 +413,12 @@ mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) ...@@ -426,14 +413,12 @@ mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx)
struct mesh_path * struct mesh_path *
mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) 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; struct mpath_node *node;
int i; int i;
int j = 0; int j = 0;
for_each_mesh_entry(tbl, node, i) { for_each_mesh_entry(tbl, node, i) {
if (sdata && node->mpath->sdata != sdata)
continue;
if (j++ == idx) if (j++ == idx)
return node->mpath; return node->mpath;
} }
...@@ -452,7 +437,7 @@ int mesh_path_add_gate(struct mesh_path *mpath) ...@@ -452,7 +437,7 @@ int mesh_path_add_gate(struct mesh_path *mpath)
int err; int err;
rcu_read_lock(); 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) hlist_for_each_entry_rcu(gate, tbl->known_gates, list)
if (gate->mpath == mpath) { if (gate->mpath == mpath) {
...@@ -550,8 +535,8 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, ...@@ -550,8 +535,8 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0)
return ERR_PTR(-ENOSPC); return ERR_PTR(-ENOSPC);
read_lock_bh(&pathtbl_resize_lock); read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
tbl = resize_dereference_mesh_paths(); tbl = resize_dereference_mesh_paths(sdata);
hash_idx = mesh_table_hash(dst, sdata, tbl); hash_idx = mesh_table_hash(dst, sdata, tbl);
bucket = &tbl->hash_buckets[hash_idx]; bucket = &tbl->hash_buckets[hash_idx];
...@@ -560,8 +545,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, ...@@ -560,8 +545,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
hlist_for_each_entry(node, bucket, list) { hlist_for_each_entry(node, bucket, list) {
mpath = node->mpath; mpath = node->mpath;
if (mpath->sdata == sdata && if (ether_addr_equal(dst, mpath->dst))
ether_addr_equal(dst, mpath->dst))
goto found; goto found;
} }
...@@ -592,7 +576,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, ...@@ -592,7 +576,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
MEAN_CHAIN_LEN * (tbl->hash_mask + 1)) MEAN_CHAIN_LEN * (tbl->hash_mask + 1))
grow = 1; grow = 1;
mesh_paths_generation++; sdata->u.mesh.mesh_paths_generation++;
if (grow) { if (grow) {
set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
...@@ -601,7 +585,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, ...@@ -601,7 +585,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
mpath = new_mpath; mpath = new_mpath;
found: found:
spin_unlock(&tbl->hashwlock[hash_idx]); spin_unlock(&tbl->hashwlock[hash_idx]);
read_unlock_bh(&pathtbl_resize_lock); read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
return mpath; return mpath;
err_node_alloc: err_node_alloc:
...@@ -609,7 +593,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, ...@@ -609,7 +593,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
err_path_alloc: err_path_alloc:
atomic_dec(&sdata->u.mesh.mpaths); atomic_dec(&sdata->u.mesh.mpaths);
spin_unlock(&tbl->hashwlock[hash_idx]); 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); return ERR_PTR(err);
} }
...@@ -620,12 +604,12 @@ static void mesh_table_free_rcu(struct rcu_head *rcu) ...@@ -620,12 +604,12 @@ static void mesh_table_free_rcu(struct rcu_head *rcu)
mesh_table_free(tbl, false); 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; struct mesh_table *oldtbl, *newtbl;
write_lock_bh(&pathtbl_resize_lock); write_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
oldtbl = resize_dereference_mesh_paths(); oldtbl = resize_dereference_mesh_paths(sdata);
newtbl = mesh_table_alloc(oldtbl->size_order + 1); newtbl = mesh_table_alloc(oldtbl->size_order + 1);
if (!newtbl) if (!newtbl)
goto out; goto out;
...@@ -633,20 +617,20 @@ void mesh_mpath_table_grow(void) ...@@ -633,20 +617,20 @@ void mesh_mpath_table_grow(void)
__mesh_table_free(newtbl); __mesh_table_free(newtbl);
goto out; 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); call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu);
out: 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; struct mesh_table *oldtbl, *newtbl;
write_lock_bh(&pathtbl_resize_lock); write_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
oldtbl = resize_dereference_mpp_paths(); oldtbl = resize_dereference_mpp_paths(sdata);
newtbl = mesh_table_alloc(oldtbl->size_order + 1); newtbl = mesh_table_alloc(oldtbl->size_order + 1);
if (!newtbl) if (!newtbl)
goto out; goto out;
...@@ -654,11 +638,11 @@ void mesh_mpp_table_grow(void) ...@@ -654,11 +638,11 @@ void mesh_mpp_table_grow(void)
__mesh_table_free(newtbl); __mesh_table_free(newtbl);
goto out; 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); call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu);
out: 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, int mpp_path_add(struct ieee80211_sub_if_data *sdata,
...@@ -690,7 +674,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, ...@@ -690,7 +674,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata,
if (!new_node) if (!new_node)
goto err_node_alloc; 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->dst, dst, ETH_ALEN);
memcpy(new_mpath->mpp, mpp, ETH_ALEN); memcpy(new_mpath->mpp, mpp, ETH_ALEN);
new_mpath->sdata = sdata; new_mpath->sdata = sdata;
...@@ -701,7 +685,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, ...@@ -701,7 +685,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata,
new_mpath->exp_time = jiffies; new_mpath->exp_time = jiffies;
spin_lock_init(&new_mpath->state_lock); 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); hash_idx = mesh_table_hash(dst, sdata, tbl);
bucket = &tbl->hash_buckets[hash_idx]; bucket = &tbl->hash_buckets[hash_idx];
...@@ -711,8 +695,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, ...@@ -711,8 +695,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata,
err = -EEXIST; err = -EEXIST;
hlist_for_each_entry(node, bucket, list) { hlist_for_each_entry(node, bucket, list) {
mpath = node->mpath; mpath = node->mpath;
if (mpath->sdata == sdata && if (ether_addr_equal(dst, mpath->dst))
ether_addr_equal(dst, mpath->dst))
goto err_exists; goto err_exists;
} }
...@@ -722,9 +705,9 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, ...@@ -722,9 +705,9 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata,
grow = 1; grow = 1;
spin_unlock(&tbl->hashwlock[hash_idx]); 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) { if (grow) {
set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags); set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
...@@ -734,7 +717,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, ...@@ -734,7 +717,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata,
err_exists: err_exists:
spin_unlock(&tbl->hashwlock[hash_idx]); spin_unlock(&tbl->hashwlock[hash_idx]);
read_unlock_bh(&pathtbl_resize_lock); read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
kfree(new_node); kfree(new_node);
err_node_alloc: err_node_alloc:
kfree(new_mpath); kfree(new_mpath);
...@@ -761,7 +744,7 @@ void mesh_plink_broken(struct sta_info *sta) ...@@ -761,7 +744,7 @@ void mesh_plink_broken(struct sta_info *sta)
int i; int i;
rcu_read_lock(); rcu_read_lock();
tbl = rcu_dereference(mesh_paths); tbl = rcu_dereference(sdata->u.mesh.mesh_paths);
for_each_mesh_entry(tbl, node, i) { for_each_mesh_entry(tbl, node, i) {
mpath = node->mpath; mpath = node->mpath;
if (rcu_access_pointer(mpath->next_hop) == sta && if (rcu_access_pointer(mpath->next_hop) == sta &&
...@@ -819,14 +802,15 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) ...@@ -819,14 +802,15 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node)
*/ */
void mesh_path_flush_by_nexthop(struct sta_info *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_table *tbl;
struct mesh_path *mpath; struct mesh_path *mpath;
struct mpath_node *node; struct mpath_node *node;
int i; int i;
rcu_read_lock(); rcu_read_lock();
read_lock_bh(&pathtbl_resize_lock); read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
tbl = resize_dereference_mesh_paths(); tbl = resize_dereference_mesh_paths(sdata);
for_each_mesh_entry(tbl, node, i) { for_each_mesh_entry(tbl, node, i) {
mpath = node->mpath; mpath = node->mpath;
if (rcu_access_pointer(mpath->next_hop) == sta) { if (rcu_access_pointer(mpath->next_hop) == sta) {
...@@ -835,7 +819,7 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta) ...@@ -835,7 +819,7 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
spin_unlock(&tbl->hashwlock[i]); spin_unlock(&tbl->hashwlock[i]);
} }
} }
read_unlock_bh(&pathtbl_resize_lock); read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -848,8 +832,8 @@ static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata, ...@@ -848,8 +832,8 @@ static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata,
int i; int i;
rcu_read_lock(); rcu_read_lock();
read_lock_bh(&pathtbl_resize_lock); read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
tbl = resize_dereference_mpp_paths(); tbl = resize_dereference_mpp_paths(sdata);
for_each_mesh_entry(tbl, node, i) { for_each_mesh_entry(tbl, node, i) {
mpp = node->mpath; mpp = node->mpath;
if (ether_addr_equal(mpp->mpp, proxy)) { if (ether_addr_equal(mpp->mpp, proxy)) {
...@@ -858,7 +842,7 @@ static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata, ...@@ -858,7 +842,7 @@ static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata,
spin_unlock(&tbl->hashwlock[i]); spin_unlock(&tbl->hashwlock[i]);
} }
} }
read_unlock_bh(&pathtbl_resize_lock); read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -872,8 +856,6 @@ static void table_flush_by_iface(struct mesh_table *tbl, ...@@ -872,8 +856,6 @@ static void table_flush_by_iface(struct mesh_table *tbl,
WARN_ON(!rcu_read_lock_held()); WARN_ON(!rcu_read_lock_held());
for_each_mesh_entry(tbl, node, i) { for_each_mesh_entry(tbl, node, i) {
mpath = node->mpath; mpath = node->mpath;
if (mpath->sdata != sdata)
continue;
spin_lock_bh(&tbl->hashwlock[i]); spin_lock_bh(&tbl->hashwlock[i]);
__mesh_path_del(tbl, node); __mesh_path_del(tbl, node);
spin_unlock_bh(&tbl->hashwlock[i]); spin_unlock_bh(&tbl->hashwlock[i]);
...@@ -893,12 +875,12 @@ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) ...@@ -893,12 +875,12 @@ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
struct mesh_table *tbl; struct mesh_table *tbl;
rcu_read_lock(); rcu_read_lock();
read_lock_bh(&pathtbl_resize_lock); read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
tbl = resize_dereference_mesh_paths(); tbl = resize_dereference_mesh_paths(sdata);
table_flush_by_iface(tbl, sdata); table_flush_by_iface(tbl, sdata);
tbl = resize_dereference_mpp_paths(); tbl = resize_dereference_mpp_paths(sdata);
table_flush_by_iface(tbl, 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(); rcu_read_unlock();
} }
...@@ -922,15 +904,14 @@ static int table_path_del(struct mesh_table __rcu *rcu_tbl, ...@@ -922,15 +904,14 @@ static int table_path_del(struct mesh_table __rcu *rcu_tbl,
int hash_idx; int hash_idx;
int err = 0; int err = 0;
tbl = resize_dereference_paths(rcu_tbl); tbl = resize_dereference_paths(sdata, rcu_tbl);
hash_idx = mesh_table_hash(addr, sdata, tbl); hash_idx = mesh_table_hash(addr, sdata, tbl);
bucket = &tbl->hash_buckets[hash_idx]; bucket = &tbl->hash_buckets[hash_idx];
spin_lock(&tbl->hashwlock[hash_idx]); spin_lock(&tbl->hashwlock[hash_idx]);
hlist_for_each_entry(node, bucket, list) { hlist_for_each_entry(node, bucket, list) {
mpath = node->mpath; mpath = node->mpath;
if (mpath->sdata == sdata && if (ether_addr_equal(addr, mpath->dst)) {
ether_addr_equal(addr, mpath->dst)) {
__mesh_path_del(tbl, node); __mesh_path_del(tbl, node);
goto enddel; goto enddel;
} }
...@@ -957,10 +938,10 @@ int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr) ...@@ -957,10 +938,10 @@ int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
/* flush relevant mpp entries first */ /* flush relevant mpp entries first */
mpp_flush_by_proxy(sdata, addr); mpp_flush_by_proxy(sdata, addr);
read_lock_bh(&pathtbl_resize_lock); read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
err = table_path_del(mesh_paths, sdata, addr); err = table_path_del(sdata->u.mesh.mesh_paths, sdata, addr);
mesh_paths_generation++; sdata->u.mesh.mesh_paths_generation++;
read_unlock_bh(&pathtbl_resize_lock); read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
return err; return err;
} }
...@@ -977,10 +958,10 @@ static int mpp_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr) ...@@ -977,10 +958,10 @@ static int mpp_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
{ {
int err = 0; int err = 0;
read_lock_bh(&pathtbl_resize_lock); read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock);
err = table_path_del(mpp_paths, sdata, addr); err = table_path_del(sdata->u.mesh.mpp_paths, sdata, addr);
mpp_paths_generation++; sdata->u.mesh.mpp_paths_generation++;
read_unlock_bh(&pathtbl_resize_lock); read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock);
return err; return err;
} }
...@@ -1020,7 +1001,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) ...@@ -1020,7 +1001,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath)
struct hlist_head *known_gates; struct hlist_head *known_gates;
rcu_read_lock(); rcu_read_lock();
tbl = rcu_dereference(mesh_paths); tbl = rcu_dereference(sdata->u.mesh.mesh_paths);
known_gates = tbl->known_gates; known_gates = tbl->known_gates;
rcu_read_unlock(); rcu_read_unlock();
...@@ -1028,9 +1009,6 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) ...@@ -1028,9 +1009,6 @@ int mesh_path_send_to_gates(struct mesh_path *mpath)
return -EHOSTUNREACH; return -EHOSTUNREACH;
hlist_for_each_entry_rcu(gate, known_gates, list) { hlist_for_each_entry_rcu(gate, known_gates, list) {
if (gate->mpath->sdata != sdata)
continue;
if (gate->mpath->flags & MESH_PATH_ACTIVE) { if (gate->mpath->flags & MESH_PATH_ACTIVE) {
mpath_dbg(sdata, "Forwarding to %pM\n", gate->mpath->dst); mpath_dbg(sdata, "Forwarding to %pM\n", gate->mpath->dst);
mesh_path_move_to_queue(gate->mpath, from_mpath, copy); mesh_path_move_to_queue(gate->mpath, from_mpath, copy);
...@@ -1043,11 +1021,10 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) ...@@ -1043,11 +1021,10 @@ int mesh_path_send_to_gates(struct mesh_path *mpath)
} }
} }
hlist_for_each_entry_rcu(gate, known_gates, list) hlist_for_each_entry_rcu(gate, known_gates, list) {
if (gate->mpath->sdata == sdata) { mpath_dbg(sdata, "Sending to %pM\n", gate->mpath->dst);
mpath_dbg(sdata, "Sending to %pM\n", gate->mpath->dst); mesh_path_tx_pending(gate->mpath);
mesh_path_tx_pending(gate->mpath); }
}
return (from_mpath == mpath) ? -EHOSTUNREACH : 0; return (from_mpath == mpath) ? -EHOSTUNREACH : 0;
} }
...@@ -1136,7 +1113,7 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) ...@@ -1136,7 +1113,7 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl)
return 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; struct mesh_table *tbl_path, *tbl_mpp;
int ret; int ret;
...@@ -1168,9 +1145,11 @@ int mesh_pathtbl_init(void) ...@@ -1168,9 +1145,11 @@ int mesh_pathtbl_init(void)
} }
INIT_HLIST_HEAD(tbl_mpp->known_gates); INIT_HLIST_HEAD(tbl_mpp->known_gates);
rwlock_init(&sdata->u.mesh.pathtbl_resize_lock);
/* Need no locking since this is during init */ /* Need no locking since this is during init */
RCU_INIT_POINTER(mesh_paths, tbl_path); RCU_INIT_POINTER(sdata->u.mesh.mesh_paths, tbl_path);
RCU_INIT_POINTER(mpp_paths, tbl_mpp); RCU_INIT_POINTER(sdata->u.mesh.mpp_paths, tbl_mpp);
return 0; return 0;
...@@ -1189,33 +1168,31 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) ...@@ -1189,33 +1168,31 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
int i; int i;
rcu_read_lock(); rcu_read_lock();
tbl = rcu_dereference(mesh_paths); tbl = rcu_dereference(sdata->u.mesh.mesh_paths);
for_each_mesh_entry(tbl, node, i) { for_each_mesh_entry(tbl, node, i) {
if (node->mpath->sdata != sdata)
continue;
mpath = node->mpath; mpath = node->mpath;
if ((!(mpath->flags & MESH_PATH_RESOLVING)) && if ((!(mpath->flags & MESH_PATH_RESOLVING)) &&
(!(mpath->flags & MESH_PATH_FIXED)) && (!(mpath->flags & MESH_PATH_FIXED)) &&
time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) 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) { for_each_mesh_entry(tbl, node, i) {
if (node->mpath->sdata != sdata)
continue;
mpath = node->mpath; mpath = node->mpath;
if ((!(mpath->flags & MESH_PATH_FIXED)) && if ((!(mpath->flags & MESH_PATH_FIXED)) &&
time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) 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(); 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 */ /* no need for locking during exit path */
mesh_table_free(rcu_dereference_protected(mesh_paths, 1), true); mesh_table_free(rcu_dereference_protected(sdata->u.mesh.mesh_paths, 1),
mesh_table_free(rcu_dereference_protected(mpp_paths, 1), true); true);
mesh_table_free(rcu_dereference_protected(sdata->u.mesh.mpp_paths, 1),
true);
} }
...@@ -2212,7 +2212,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, ...@@ -2212,7 +2212,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
} }
if (mppath && mpath) if (mppath && mpath)
mesh_path_del(mpath->sdata, mpath->dst); mesh_path_del(sdata, mpath->dst);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment