2014-05-22 15:06:28

by Henning Rogge

[permalink] [raw]
Subject: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

From: Henning Rogge <[email protected]>

This patch is a preparation for exporting the MPP data of the 802.11s
implementation via netlink to userspace. It unifies the content of the
mesh_paths and mpp_paths tables in mesh_pathtbl.c without changing
the behavior of the code.

Signed-off-by: Henning Rogge <[email protected]>
---
net/mac80211/cfg.c | 6 +-
net/mac80211/mesh.c | 3 -
net/mac80211/mesh.h | 18 ++--
net/mac80211/mesh_hwmp.c | 30 +++---
net/mac80211/mesh_pathtbl.c | 235 +++++++++++---------------------------------
net/mac80211/rx.c | 4 +-
net/mac80211/tx.c | 5 +-
7 files changed, 92 insertions(+), 209 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index aaa59d7..a443b06 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1637,7 +1637,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
return -ENOENT;
}

- mpath = mesh_path_add(sdata, dst);
+ mpath = mesh_path_add(sdata, dst, NULL);
if (IS_ERR(mpath)) {
rcu_read_unlock();
return PTR_ERR(mpath);
@@ -1679,7 +1679,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,
return -ENOENT;
}

- mpath = mesh_path_lookup(sdata, dst);
+ mpath = mesh_path_lookup(sdata, dst, false);
if (!mpath) {
rcu_read_unlock();
return -ENOENT;
@@ -1743,7 +1743,7 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);

rcu_read_lock();
- mpath = mesh_path_lookup(sdata, dst);
+ mpath = mesh_path_lookup(sdata, dst, false);
if (!mpath) {
rcu_read_unlock();
return -ENOENT;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index f70e9cd..14b5a77 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1283,9 +1283,6 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
mesh_mpath_table_grow();

- if (test_and_clear_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags))
- mesh_mpp_table_grow();
-
if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
ieee80211_mesh_housekeeping(sdata);

diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index f39a19f..7b1a854 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -43,6 +43,7 @@ enum mesh_path_flags {
MESH_PATH_FIXED = BIT(3),
MESH_PATH_RESOLVED = BIT(4),
MESH_PATH_REQ_QUEUED = BIT(5),
+ MESH_PATH_PROXIED = BIT(6),
};

/**
@@ -63,7 +64,6 @@ enum mesh_path_flags {
enum mesh_deferred_task_flags {
MESH_WORK_HOUSEKEEPING,
MESH_WORK_GROW_MPATH_TABLE,
- MESH_WORK_GROW_MPP_TABLE,
MESH_WORK_ROOT,
MESH_WORK_DRIFT_ADJUST,
MESH_WORK_MBSS_CHANGED,
@@ -263,11 +263,7 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata);
struct mesh_path *mesh_path_lookup(struct ieee80211_sub_if_data *sdata,
- const u8 *dst);
-struct mesh_path *mpp_path_lookup(struct ieee80211_sub_if_data *sdata,
- const u8 *dst);
-int mpp_path_add(struct ieee80211_sub_if_data *sdata,
- const u8 *dst, const u8 *mpp);
+ const u8 *dst, bool is_proxied);
struct mesh_path *
mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx);
void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
@@ -275,7 +271,8 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len);
struct mesh_path *
-mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst);
+mesh_path_add(struct ieee80211_sub_if_data *sdata,
+ const u8 *dst, const u8 *mpp);

int mesh_path_add_gate(struct mesh_path *mpath);
int mesh_path_send_to_gates(struct mesh_path *mpath);
@@ -298,7 +295,6 @@ void mesh_sta_cleanup(struct sta_info *sta);
/* Private interfaces */
/* Mesh tables */
void mesh_mpath_table_grow(void);
-void mesh_mpp_table_grow(void);
/* Mesh paths */
int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
u8 ttl, const u8 *target, u32 target_sn,
@@ -355,11 +351,17 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP;
}

+static inline bool is_mesh_path_proxied(const struct mesh_path *mpath)
+{
+ return !!(mpath->flags & MESH_PATH_PROXIED);
+}
+
void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);

void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata);
void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata);
void ieee80211s_stop(void);
+
#else
static inline void
ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index f951468..57c088e 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -429,7 +429,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
process = false;
fresh_info = false;
} else {
- mpath = mesh_path_lookup(sdata, orig_addr);
+ mpath = mesh_path_lookup(sdata, orig_addr, false);
if (mpath) {
spin_lock_bh(&mpath->state_lock);
if (mpath->flags & MESH_PATH_FIXED)
@@ -444,7 +444,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
}
}
} else {
- mpath = mesh_path_add(sdata, orig_addr);
+ mpath = mesh_path_add(sdata, orig_addr, NULL);
if (IS_ERR(mpath)) {
rcu_read_unlock();
return 0;
@@ -476,7 +476,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
else {
fresh_info = true;

- mpath = mesh_path_lookup(sdata, ta);
+ mpath = mesh_path_lookup(sdata, ta, false);
if (mpath) {
spin_lock_bh(&mpath->state_lock);
if ((mpath->flags & MESH_PATH_FIXED) ||
@@ -484,7 +484,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
(last_hop_metric > mpath->metric)))
fresh_info = false;
} else {
- mpath = mesh_path_add(sdata, ta);
+ mpath = mesh_path_add(sdata, ta, NULL);
if (IS_ERR(mpath)) {
rcu_read_unlock();
return 0;
@@ -550,7 +550,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
} else if (is_broadcast_ether_addr(target_addr) &&
(target_flags & IEEE80211_PREQ_TO_FLAG)) {
rcu_read_lock();
- mpath = mesh_path_lookup(sdata, orig_addr);
+ mpath = mesh_path_lookup(sdata, orig_addr, false);
if (mpath) {
if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
reply = true;
@@ -565,7 +565,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock();
} else {
rcu_read_lock();
- mpath = mesh_path_lookup(sdata, target_addr);
+ mpath = mesh_path_lookup(sdata, target_addr, false);
if (mpath) {
if ((!(mpath->flags & MESH_PATH_SN_VALID)) ||
SN_LT(mpath->sn, target_sn)) {
@@ -672,7 +672,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
}

rcu_read_lock();
- mpath = mesh_path_lookup(sdata, orig_addr);
+ mpath = mesh_path_lookup(sdata, orig_addr, false);
if (mpath)
spin_lock_bh(&mpath->state_lock);
else
@@ -728,7 +728,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
target_rcode = PERR_IE_TARGET_RCODE(perr_elem);

rcu_read_lock();
- mpath = mesh_path_lookup(sdata, target_addr);
+ mpath = mesh_path_lookup(sdata, target_addr, false);
if (mpath) {
struct sta_info *sta;

@@ -793,9 +793,9 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,

metric_txsta = airtime_link_metric_get(local, sta);

- mpath = mesh_path_lookup(sdata, orig_addr);
+ mpath = mesh_path_lookup(sdata, orig_addr, false);
if (!mpath) {
- mpath = mesh_path_add(sdata, orig_addr);
+ mpath = mesh_path_add(sdata, orig_addr, NULL);
if (IS_ERR(mpath)) {
rcu_read_unlock();
sdata->u.mesh.mshstats.dropped_frames_no_route++;
@@ -994,7 +994,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);

rcu_read_lock();
- mpath = mesh_path_lookup(sdata, preq_node->dst);
+ mpath = mesh_path_lookup(sdata, preq_node->dst, false);
if (!mpath)
goto enddiscovery;

@@ -1082,9 +1082,9 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
goto endlookup;

/* no nexthop found, start resolving */
- mpath = mesh_path_lookup(sdata, target_addr);
+ mpath = mesh_path_lookup(sdata, target_addr, false);
if (!mpath) {
- mpath = mesh_path_add(sdata, target_addr);
+ mpath = mesh_path_add(sdata, target_addr, NULL);
if (IS_ERR(mpath)) {
mesh_path_discard_frame(sdata, skb);
err = PTR_ERR(mpath);
@@ -1130,7 +1130,7 @@ int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata,
int err = -ENOENT;

rcu_read_lock();
- mpath = mesh_path_lookup(sdata, target_addr);
+ mpath = mesh_path_lookup(sdata, target_addr, false);

if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE))
goto endlookup;
@@ -1177,7 +1177,7 @@ void mesh_path_timer(unsigned long data)
spin_unlock_bh(&mpath->state_lock);
mesh_queue_preq(mpath, 0);
} else {
- mpath->flags = 0;
+ mpath->flags &= ~MESH_PATH_PROXIED;
mpath->exp_time = jiffies;
spin_unlock_bh(&mpath->state_lock);
if (!mpath->is_gate && mesh_gate_num(sdata) > 0) {
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 7d050ed..adf2d98 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -41,7 +41,6 @@ struct mpath_node {
};

static struct mesh_table __rcu *mesh_paths;
-static struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */

int mesh_paths_generation;

@@ -60,12 +59,6 @@ static inline struct mesh_table *resize_dereference_mesh_paths(void)
lockdep_is_held(&pathtbl_resize_lock));
}

-static inline struct mesh_table *resize_dereference_mpp_paths(void)
-{
- return rcu_dereference_protected(mpp_paths,
- lockdep_is_held(&pathtbl_resize_lock));
-}
-
/*
* CAREFUL -- "tbl" must not be an expression,
* in particular not an rcu_dereference(), since
@@ -328,18 +321,31 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath,
spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags);
}

-
-static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
- struct ieee80211_sub_if_data *sdata)
+/**
+ * mesh_path_lookup - look up a path in the mesh path table
+ * @sdata: local subif
+ * @dst: hardware address (ETH_ALEN length) of destination
+ * @is_proxied: true to lookup mpp entries, false otherwise
+ * Returns: pointer to the mesh path structure, or NULL if not found
+ *
+ * Locking: must be called within a read rcu section.
+ */
+struct mesh_path *
+mesh_path_lookup(struct ieee80211_sub_if_data *sdata,
+ const u8 *dst, bool is_proxied)
{
+ struct mesh_table *tbl;
struct mesh_path *mpath;
struct hlist_head *bucket;
struct mpath_node *node;

+ tbl = rcu_dereference(mesh_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 &&
+ is_mesh_path_proxied(mpath) == is_proxied &&
ether_addr_equal(dst, mpath->dst)) {
if (mpath_expired(mpath)) {
spin_lock_bh(&mpath->state_lock);
@@ -353,28 +359,6 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
}

/**
- * mesh_path_lookup - look up a path in the mesh path table
- * @sdata: local subif
- * @dst: hardware address (ETH_ALEN length) of destination
- *
- * Returns: pointer to the mesh path structure, or NULL if not found
- *
- * Locking: must be called within a read rcu section.
- */
-struct mesh_path *
-mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst)
-{
- return mpath_lookup(rcu_dereference(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);
-}
-
-
-/**
* mesh_path_lookup_by_idx - look up a path in the mesh path table by its index
* @idx: index
* @sdata: local subif, or NULL for all entries
@@ -386,14 +370,18 @@ mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst)
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;
struct mpath_node *node;
int i;
int j = 0;

+ tbl = rcu_dereference(mesh_paths);
+
for_each_mesh_entry(tbl, node, i) {
if (sdata && node->mpath->sdata != sdata)
continue;
+ if (is_mesh_path_proxied(node->mpath))
+ continue;
if (j++ == idx) {
if (mpath_expired(node->mpath)) {
spin_lock_bh(&node->mpath->state_lock);
@@ -486,15 +474,16 @@ int mesh_gate_num(struct ieee80211_sub_if_data *sdata)

/**
* mesh_path_add - allocate and add a new path to the mesh path table
- * @dst: destination address of the path (ETH_ALEN length)
* @sdata: local subif
+ * @dst: destination address of the path (ETH_ALEN length)
+ * @mpp: path proxy address or NULL if dst is mesh node (ETH_ALEN length)
*
- * Returns: 0 on success
+ * Returns: pointer to mesh_path
*
* State: the initial state of the new path is set to 0
*/
struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
- const u8 *dst)
+ const u8 *dst, const u8 *mpp)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local;
@@ -513,10 +502,12 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
if (is_multicast_ether_addr(dst))
return ERR_PTR(-ENOTSUPP);

- if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0)
+ if (!mpp &&
+ 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();

hash_idx = mesh_table_hash(dst, sdata, tbl);
@@ -527,6 +518,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
hlist_for_each_entry(node, bucket, list) {
mpath = node->mpath;
if (mpath->sdata == sdata &&
+ is_mesh_path_proxied(mpath) == (mpp != NULL) &&
ether_addr_equal(dst, mpath->dst))
goto found;
}
@@ -536,32 +528,37 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
if (!new_mpath)
goto err_path_alloc;

- new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
+ new_node = kzalloc(sizeof(struct mpath_node), GFP_ATOMIC);
if (!new_node)
goto err_node_alloc;

memcpy(new_mpath->dst, dst, ETH_ALEN);
- eth_broadcast_addr(new_mpath->rann_snd_addr);
- new_mpath->is_root = false;
+ if (mpp) {
+ memcpy(new_mpath->mpp, mpp, ETH_ALEN);
+ new_mpath->flags = MESH_PATH_PROXIED;
+ } else {
+ eth_broadcast_addr(new_mpath->rann_snd_addr);
+ new_mpath->timer.data = (unsigned long) new_mpath;
+ new_mpath->timer.function = mesh_path_timer;
+ }
new_mpath->sdata = sdata;
- new_mpath->flags = 0;
skb_queue_head_init(&new_mpath->frame_queue);
new_node->mpath = new_mpath;
- new_mpath->timer.data = (unsigned long) new_mpath;
- new_mpath->timer.function = mesh_path_timer;
new_mpath->exp_time = jiffies;
- spin_lock_init(&new_mpath->state_lock);
init_timer(&new_mpath->timer);

+ spin_lock_init(&new_mpath->state_lock);
+
hlist_add_head_rcu(&new_node->list, bucket);
if (atomic_inc_return(&tbl->entries) >=
tbl->mean_chain_len * (tbl->hash_mask + 1))
grow = 1;

- mesh_paths_generation++;
+ if (!mpp)
+ mesh_paths_generation++;

if (grow) {
- set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
+ set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
ieee80211_queue_work(&local->hw, &sdata->work);
}
mpath = new_mpath;
@@ -573,7 +570,8 @@ found:
err_node_alloc:
kfree(new_mpath);
err_path_alloc:
- atomic_dec(&sdata->u.mesh.mpaths);
+ if (!mpp)
+ atomic_dec(&sdata->u.mesh.mpaths);
spin_unlock(&tbl->hashwlock[hash_idx]);
read_unlock_bh(&pathtbl_resize_lock);
return ERR_PTR(err);
@@ -607,104 +605,6 @@ void mesh_mpath_table_grow(void)
write_unlock_bh(&pathtbl_resize_lock);
}

-void mesh_mpp_table_grow(void)
-{
- struct mesh_table *oldtbl, *newtbl;
-
- write_lock_bh(&pathtbl_resize_lock);
- oldtbl = resize_dereference_mpp_paths();
- newtbl = mesh_table_alloc(oldtbl->size_order + 1);
- if (!newtbl)
- goto out;
- if (mesh_table_grow(oldtbl, newtbl) < 0) {
- __mesh_table_free(newtbl);
- goto out;
- }
- rcu_assign_pointer(mpp_paths, newtbl);
- call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu);
-
- out:
- write_unlock_bh(&pathtbl_resize_lock);
-}
-
-int mpp_path_add(struct ieee80211_sub_if_data *sdata,
- const u8 *dst, const u8 *mpp)
-{
- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- struct ieee80211_local *local = sdata->local;
- struct mesh_table *tbl;
- struct mesh_path *mpath, *new_mpath;
- struct mpath_node *node, *new_node;
- struct hlist_head *bucket;
- int grow = 0;
- int err = 0;
- u32 hash_idx;
-
- if (ether_addr_equal(dst, sdata->vif.addr))
- /* never add ourselves as neighbours */
- return -ENOTSUPP;
-
- if (is_multicast_ether_addr(dst))
- return -ENOTSUPP;
-
- err = -ENOMEM;
- new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
- if (!new_mpath)
- goto err_path_alloc;
-
- new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
- if (!new_node)
- goto err_node_alloc;
-
- read_lock_bh(&pathtbl_resize_lock);
- memcpy(new_mpath->dst, dst, ETH_ALEN);
- memcpy(new_mpath->mpp, mpp, ETH_ALEN);
- new_mpath->sdata = sdata;
- new_mpath->flags = 0;
- skb_queue_head_init(&new_mpath->frame_queue);
- new_node->mpath = new_mpath;
- init_timer(&new_mpath->timer);
- new_mpath->exp_time = jiffies;
- spin_lock_init(&new_mpath->state_lock);
-
- tbl = resize_dereference_mpp_paths();
-
- hash_idx = mesh_table_hash(dst, sdata, tbl);
- bucket = &tbl->hash_buckets[hash_idx];
-
- spin_lock(&tbl->hashwlock[hash_idx]);
-
- err = -EEXIST;
- hlist_for_each_entry(node, bucket, list) {
- mpath = node->mpath;
- if (mpath->sdata == sdata &&
- ether_addr_equal(dst, mpath->dst))
- goto err_exists;
- }
-
- hlist_add_head_rcu(&new_node->list, bucket);
- if (atomic_inc_return(&tbl->entries) >=
- tbl->mean_chain_len * (tbl->hash_mask + 1))
- grow = 1;
-
- spin_unlock(&tbl->hashwlock[hash_idx]);
- read_unlock_bh(&pathtbl_resize_lock);
- if (grow) {
- set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
- ieee80211_queue_work(&local->hw, &sdata->work);
- }
- return 0;
-
-err_exists:
- spin_unlock(&tbl->hashwlock[hash_idx]);
- read_unlock_bh(&pathtbl_resize_lock);
- kfree(new_node);
-err_node_alloc:
- kfree(new_mpath);
-err_path_alloc:
- return err;
-}
-

/**
* mesh_plink_broken - deactivates paths and sends perr when a link breaks
@@ -727,6 +627,8 @@ void mesh_plink_broken(struct sta_info *sta)
tbl = rcu_dereference(mesh_paths);
for_each_mesh_entry(tbl, node, i) {
mpath = node->mpath;
+ if (mpath->flags & MESH_PATH_PROXIED)
+ continue;
if (rcu_dereference(mpath->next_hop) == sta &&
mpath->flags & MESH_PATH_ACTIVE &&
!(mpath->flags & MESH_PATH_FIXED)) {
@@ -792,6 +694,8 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
tbl = resize_dereference_mesh_paths();
for_each_mesh_entry(tbl, node, i) {
mpath = node->mpath;
+ if (mpath->flags & MESH_PATH_PROXIED)
+ continue;
if (rcu_dereference(mpath->next_hop) == sta) {
spin_lock(&tbl->hashwlock[i]);
__mesh_path_del(tbl, node);
@@ -802,14 +706,16 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
rcu_read_unlock();
}

-static void table_flush_by_iface(struct mesh_table *tbl,
- struct ieee80211_sub_if_data *sdata)
+static void table_flush_by_iface(struct ieee80211_sub_if_data *sdata)
{
+ struct mesh_table *tbl;
struct mesh_path *mpath;
struct mpath_node *node;
int i;

WARN_ON(!rcu_read_lock_held());
+
+ tbl = resize_dereference_mesh_paths();
for_each_mesh_entry(tbl, node, i) {
mpath = node->mpath;
if (mpath->sdata != sdata)
@@ -830,14 +736,9 @@ static void table_flush_by_iface(struct mesh_table *tbl,
*/
void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
{
- struct mesh_table *tbl;
-
rcu_read_lock();
read_lock_bh(&pathtbl_resize_lock);
- tbl = resize_dereference_mesh_paths();
- table_flush_by_iface(tbl, sdata);
- tbl = resize_dereference_mpp_paths();
- table_flush_by_iface(tbl, sdata);
+ table_flush_by_iface(sdata);
read_unlock_bh(&pathtbl_resize_lock);
rcu_read_unlock();
}
@@ -868,6 +769,7 @@ int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
hlist_for_each_entry(node, bucket, list) {
mpath = node->mpath;
if (mpath->sdata == sdata &&
+ !(mpath->flags & MESH_PATH_PROXIED) &&
ether_addr_equal(addr, mpath->dst)) {
__mesh_path_del(tbl, node);
goto enddel;
@@ -1035,7 +937,7 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl)

int mesh_pathtbl_init(void)
{
- struct mesh_table *tbl_path, *tbl_mpp;
+ struct mesh_table *tbl_path;
int ret;

tbl_path = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
@@ -1051,30 +953,11 @@ int mesh_pathtbl_init(void)
}
INIT_HLIST_HEAD(tbl_path->known_gates);

-
- tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
- if (!tbl_mpp) {
- ret = -ENOMEM;
- goto free_path;
- }
- tbl_mpp->free_node = &mesh_path_node_free;
- tbl_mpp->copy_node = &mesh_path_node_copy;
- tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN;
- tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC);
- if (!tbl_mpp->known_gates) {
- ret = -ENOMEM;
- goto free_mpp;
- }
- INIT_HLIST_HEAD(tbl_mpp->known_gates);
-
/* Need no locking since this is during init */
RCU_INIT_POINTER(mesh_paths, tbl_path);
- RCU_INIT_POINTER(mpp_paths, tbl_mpp);

return 0;

-free_mpp:
- mesh_table_free(tbl_mpp, true);
free_path:
mesh_table_free(tbl_path, true);
return ret;
@@ -1090,9 +973,10 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
rcu_read_lock();
tbl = rcu_dereference(mesh_paths);
for_each_mesh_entry(tbl, node, i) {
- if (node->mpath->sdata != sdata)
- continue;
mpath = node->mpath;
+ if (mpath->sdata != sdata ||
+ (mpath->flags & MESH_PATH_PROXIED))
+ continue;
if ((!(mpath->flags & MESH_PATH_RESOLVING)) &&
(!(mpath->flags & MESH_PATH_FIXED)) &&
time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
@@ -1105,5 +989,4 @@ void mesh_pathtbl_unregister(void)
{
/* 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);
}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 216c45b..6b354d5 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2103,9 +2103,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
}

rcu_read_lock();
- mppath = mpp_path_lookup(sdata, proxied_addr);
+ mppath = mesh_path_lookup(sdata, proxied_addr, true);
if (!mppath) {
- mpp_path_add(sdata, proxied_addr, mpp_addr);
+ mesh_path_add(sdata, proxied_addr, mpp_addr);
} else {
spin_lock_bh(&mppath->state_lock);
if (!ether_addr_equal(mppath->mpp, mpp_addr))
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 19d36d4..06474ff 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1887,7 +1887,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
struct sta_info *next_hop;
bool mpp_lookup = true;

- mpath = mesh_path_lookup(sdata, skb->data);
+ mpath = mesh_path_lookup(sdata, skb->data, false);
if (mpath) {
mpp_lookup = false;
next_hop = rcu_dereference(mpath->next_hop);
@@ -1898,7 +1898,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
}

if (mpp_lookup)
- mppath = mpp_path_lookup(sdata, skb->data);
+ mppath = mesh_path_lookup(sdata,
+ skb->data, true);

if (mppath && mpath)
mesh_path_del(mpath->sdata, mpath->dst);
--
1.9.0




2014-05-26 09:37:49

by Henning Rogge

[permalink] [raw]
Subject: Re: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

Hi,

I think this would require to know the mac addresses of the remote
nodes... but maybe I will look into changing the timeout value.

Henning Rogge

On Mon, May 26, 2014 at 8:47 AM, Yeoh Chun-Yeow <[email protected]> wrote:
> For disable HWMP, in additional to disable frame forwarding and set
> mesh TTL to 1, you can force specific mpath using "iw mesh0 mpath set
> <MACx> next_hop <MACx>". In this case, you will disable the path
> refresh.
>
> ----
> Chun-Yeow
>
> On Sat, May 24, 2014 at 4:57 AM, Bob Copeland <[email protected]> wrote:
>> On Fri, May 23, 2014 at 12:52:57PM +0200, Henning Rogge wrote:
>>> Hi,
>>>
>>> I will have another look at the codebase next week, there was a lot of
>>> similar code for both tables that could be simplified without throwing
>>> them together.
>>>
>>> The feeling I get here is that four new nl80211 commands
>>> (set/get/del/dump mpp_paths) are the right way to export these values?
>>
>> That approach would be fine by me. Thanks for working on this!
>>
>> --
>> Bob Copeland %% http://www.bobcopeland.com

2014-05-23 20:57:22

by Bob Copeland

[permalink] [raw]
Subject: Re: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

On Fri, May 23, 2014 at 12:52:57PM +0200, Henning Rogge wrote:
> Hi,
>
> I will have another look at the codebase next week, there was a lot of
> similar code for both tables that could be simplified without throwing
> them together.
>
> The feeling I get here is that four new nl80211 commands
> (set/get/del/dump mpp_paths) are the right way to export these values?

That approach would be fine by me. Thanks for working on this!

--
Bob Copeland %% http://www.bobcopeland.com

2014-05-22 15:21:36

by Henning Rogge

[permalink] [raw]
Subject: Re: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

Ups...

I thought I had found all this "stupid whitespace mistakes, I will
remove them in the next version of the patch... but I wanted a comment
if this is a good direction to go before we discuss how to change the
netlink interface to export the data of the former mpp_paths table.

Henning Rogge

On Thu, May 22, 2014 at 5:15 PM, Johannes Berg
<[email protected]> wrote:
> On Thu, 2014-05-22 at 17:06 +0200, Henning Rogge wrote:
>> From: Henning Rogge <[email protected]>
>>
>> This patch is a preparation for exporting the MPP data of the 802.11s
>> implementation via netlink to userspace. It unifies the content of the
>> mesh_paths and mpp_paths tables in mesh_pathtbl.c without changing
>> the behavior of the code.
>
> Code removal always *seems* good, but I can't really say much about
> this :-)
>
>> void ieee80211s_stop(void);
>> +
>> #else
>
> This I'd rather avoid though.
>
> johannes
>

2014-05-22 15:25:45

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

On Thu, 2014-05-22 at 17:21 +0200, Henning Rogge wrote:
> Ups...
>
> I thought I had found all this "stupid whitespace mistakes, I will
> remove them in the next version of the patch...

:)

> but I wanted a comment
> if this is a good direction to go before we discuss how to change the
> netlink interface to export the data of the former mpp_paths table.

No idea, really. However, I'm not sure why the two are related? The
netlink API could just iterate two tables as well.

johannes


2014-05-22 19:31:31

by Henning Rogge

[permalink] [raw]
Subject: Re: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

I first had planned to just throw them together... but it didn't
worked out and I assume that there is some time where you can have two
entries with the same destination, one of them a normal path
(request), the other one the mapped destination.

Henning Rogge

On Thu, May 22, 2014 at 9:27 PM, Bob Copeland <[email protected]> wrote:
> On Thu, May 22, 2014 at 05:06:21PM +0200, Henning Rogge wrote:
>> From: Henning Rogge <[email protected]>
>>
>> This patch is a preparation for exporting the MPP data of the 802.11s
>> implementation via netlink to userspace. It unifies the content of the
>> mesh_paths and mpp_paths tables in mesh_pathtbl.c without changing
>> the behavior of the code.
>>
>> Signed-off-by: Henning Rogge <[email protected]>
>
> I think I fall on the side of your earlier assessment that they
> hold different things and should stay in different tables, even though
> there are 200 lines of identical code here. Maybe some bits could
> be shared without sharing the data and changing the API?
>
>> -static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
>> - struct ieee80211_sub_if_data *sdata)
>> +/**
>> + * mesh_path_lookup - look up a path in the mesh path table
>> + * @sdata: local subif
>> + * @dst: hardware address (ETH_ALEN length) of destination
>> + * @is_proxied: true to lookup mpp entries, false otherwise
>
> Also, I don't like adding random boolean variables to water down what
> this function does. It means when looking at the caller you have to go
> back to the definition to see just what is going on here.
>
> We do mpp_path_lookup exactly twice so it seems weird to have to
> change all of the mpath_lookup callers too.
>
> --
> Bob Copeland %% http://www.bobcopeland.com

2014-05-22 15:16:11

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

On Thu, 2014-05-22 at 17:06 +0200, Henning Rogge wrote:
> From: Henning Rogge <[email protected]>
>
> This patch is a preparation for exporting the MPP data of the 802.11s
> implementation via netlink to userspace. It unifies the content of the
> mesh_paths and mpp_paths tables in mesh_pathtbl.c without changing
> the behavior of the code.

Code removal always *seems* good, but I can't really say much about
this :-)

> void ieee80211s_stop(void);
> +
> #else

This I'd rather avoid though.

johannes


2014-05-22 19:27:37

by Bob Copeland

[permalink] [raw]
Subject: Re: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

On Thu, May 22, 2014 at 05:06:21PM +0200, Henning Rogge wrote:
> From: Henning Rogge <[email protected]>
>
> This patch is a preparation for exporting the MPP data of the 802.11s
> implementation via netlink to userspace. It unifies the content of the
> mesh_paths and mpp_paths tables in mesh_pathtbl.c without changing
> the behavior of the code.
>
> Signed-off-by: Henning Rogge <[email protected]>

I think I fall on the side of your earlier assessment that they
hold different things and should stay in different tables, even though
there are 200 lines of identical code here. Maybe some bits could
be shared without sharing the data and changing the API?

> -static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
> - struct ieee80211_sub_if_data *sdata)
> +/**
> + * mesh_path_lookup - look up a path in the mesh path table
> + * @sdata: local subif
> + * @dst: hardware address (ETH_ALEN length) of destination
> + * @is_proxied: true to lookup mpp entries, false otherwise

Also, I don't like adding random boolean variables to water down what
this function does. It means when looking at the caller you have to go
back to the definition to see just what is going on here.

We do mpp_path_lookup exactly twice so it seems weird to have to
change all of the mpath_lookup callers too.

--
Bob Copeland %% http://www.bobcopeland.com

2014-05-26 10:26:15

by Chun-Yeow Yeoh

[permalink] [raw]
Subject: Re: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

Yes, mpath set is only valid after peering. So you will have the MAC
address then.

----
Chun-Yeow

On Mon, May 26, 2014 at 5:37 PM, Henning Rogge <[email protected]> wrote:
> Hi,
>
> I think this would require to know the mac addresses of the remote
> nodes... but maybe I will look into changing the timeout value.
>
> Henning Rogge
>
> On Mon, May 26, 2014 at 8:47 AM, Yeoh Chun-Yeow <[email protected]> wrote:
>> For disable HWMP, in additional to disable frame forwarding and set
>> mesh TTL to 1, you can force specific mpath using "iw mesh0 mpath set
>> <MACx> next_hop <MACx>". In this case, you will disable the path
>> refresh.
>>
>> ----
>> Chun-Yeow
>>
>> On Sat, May 24, 2014 at 4:57 AM, Bob Copeland <[email protected]> wrote:
>>> On Fri, May 23, 2014 at 12:52:57PM +0200, Henning Rogge wrote:
>>>> Hi,
>>>>
>>>> I will have another look at the codebase next week, there was a lot of
>>>> similar code for both tables that could be simplified without throwing
>>>> them together.
>>>>
>>>> The feeling I get here is that four new nl80211 commands
>>>> (set/get/del/dump mpp_paths) are the right way to export these values?
>>>
>>> That approach would be fine by me. Thanks for working on this!
>>>
>>> --
>>> Bob Copeland %% http://www.bobcopeland.com

2014-05-23 10:53:17

by Henning Rogge

[permalink] [raw]
Subject: Re: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

Hi,

I will have another look at the codebase next week, there was a lot of
similar code for both tables that could be simplified without throwing
them together.

The feeling I get here is that four new nl80211 commands
(set/get/del/dump mpp_paths) are the right way to export these values?

Henning Rogge

On Fri, May 23, 2014 at 11:08 AM, Yeoh Chun-Yeow <[email protected]> wrote:
> Ya, there is a possibility that a mesh node is leaving its MBSS and
> joining another new MBSS just behind its original MBSS or vice versa.
>
> By the way, I just wondering whether it would be much faster in path
> resolving towards destination behind MBSS if we keep two tables
> separately. In typical case, assuming with one or two mesh gates
> providing the internet connectivity, we will have large mesh path
> table but smaller mpp path table.
>
> ---
> Chun-Yeow
>
> On Fri, May 23, 2014 at 3:31 AM, Henning Rogge <[email protected]> wrote:
>> I first had planned to just throw them together... but it didn't
>> worked out and I assume that there is some time where you can have two
>> entries with the same destination, one of them a normal path
>> (request), the other one the mapped destination.
>>
>> Henning Rogge
>>
>> On Thu, May 22, 2014 at 9:27 PM, Bob Copeland <[email protected]> wrote:
>>> On Thu, May 22, 2014 at 05:06:21PM +0200, Henning Rogge wrote:
>>>> From: Henning Rogge <[email protected]>
>>>>
>>>> This patch is a preparation for exporting the MPP data of the 802.11s
>>>> implementation via netlink to userspace. It unifies the content of the
>>>> mesh_paths and mpp_paths tables in mesh_pathtbl.c without changing
>>>> the behavior of the code.
>>>>
>>>> Signed-off-by: Henning Rogge <[email protected]>
>>>
>>> I think I fall on the side of your earlier assessment that they
>>> hold different things and should stay in different tables, even though
>>> there are 200 lines of identical code here. Maybe some bits could
>>> be shared without sharing the data and changing the API?
>>>
>>>> -static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
>>>> - struct ieee80211_sub_if_data *sdata)
>>>> +/**
>>>> + * mesh_path_lookup - look up a path in the mesh path table
>>>> + * @sdata: local subif
>>>> + * @dst: hardware address (ETH_ALEN length) of destination
>>>> + * @is_proxied: true to lookup mpp entries, false otherwise
>>>
>>> Also, I don't like adding random boolean variables to water down what
>>> this function does. It means when looking at the caller you have to go
>>> back to the definition to see just what is going on here.
>>>
>>> We do mpp_path_lookup exactly twice so it seems weird to have to
>>> change all of the mpath_lookup callers too.
>>>
>>> --
>>> Bob Copeland %% http://www.bobcopeland.com

2014-05-23 09:08:20

by Chun-Yeow Yeoh

[permalink] [raw]
Subject: Re: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

Ya, there is a possibility that a mesh node is leaving its MBSS and
joining another new MBSS just behind its original MBSS or vice versa.

By the way, I just wondering whether it would be much faster in path
resolving towards destination behind MBSS if we keep two tables
separately. In typical case, assuming with one or two mesh gates
providing the internet connectivity, we will have large mesh path
table but smaller mpp path table.

---
Chun-Yeow

On Fri, May 23, 2014 at 3:31 AM, Henning Rogge <[email protected]> wrote:
> I first had planned to just throw them together... but it didn't
> worked out and I assume that there is some time where you can have two
> entries with the same destination, one of them a normal path
> (request), the other one the mapped destination.
>
> Henning Rogge
>
> On Thu, May 22, 2014 at 9:27 PM, Bob Copeland <[email protected]> wrote:
>> On Thu, May 22, 2014 at 05:06:21PM +0200, Henning Rogge wrote:
>>> From: Henning Rogge <[email protected]>
>>>
>>> This patch is a preparation for exporting the MPP data of the 802.11s
>>> implementation via netlink to userspace. It unifies the content of the
>>> mesh_paths and mpp_paths tables in mesh_pathtbl.c without changing
>>> the behavior of the code.
>>>
>>> Signed-off-by: Henning Rogge <[email protected]>
>>
>> I think I fall on the side of your earlier assessment that they
>> hold different things and should stay in different tables, even though
>> there are 200 lines of identical code here. Maybe some bits could
>> be shared without sharing the data and changing the API?
>>
>>> -static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
>>> - struct ieee80211_sub_if_data *sdata)
>>> +/**
>>> + * mesh_path_lookup - look up a path in the mesh path table
>>> + * @sdata: local subif
>>> + * @dst: hardware address (ETH_ALEN length) of destination
>>> + * @is_proxied: true to lookup mpp entries, false otherwise
>>
>> Also, I don't like adding random boolean variables to water down what
>> this function does. It means when looking at the caller you have to go
>> back to the definition to see just what is going on here.
>>
>> We do mpp_path_lookup exactly twice so it seems weird to have to
>> change all of the mpath_lookup callers too.
>>
>> --
>> Bob Copeland %% http://www.bobcopeland.com

2014-05-26 06:47:21

by Chun-Yeow Yeoh

[permalink] [raw]
Subject: Re: [RFC Patch] Unify mpp/mesh_path handling for Mac 802.11s

For disable HWMP, in additional to disable frame forwarding and set
mesh TTL to 1, you can force specific mpath using "iw mesh0 mpath set
<MACx> next_hop <MACx>". In this case, you will disable the path
refresh.

----
Chun-Yeow

On Sat, May 24, 2014 at 4:57 AM, Bob Copeland <[email protected]> wrote:
> On Fri, May 23, 2014 at 12:52:57PM +0200, Henning Rogge wrote:
>> Hi,
>>
>> I will have another look at the codebase next week, there was a lot of
>> similar code for both tables that could be simplified without throwing
>> them together.
>>
>> The feeling I get here is that four new nl80211 commands
>> (set/get/del/dump mpp_paths) are the right way to export these values?
>
> That approach would be fine by me. Thanks for working on this!
>
> --
> Bob Copeland %% http://www.bobcopeland.com