2016-02-03 12:58:45

by Henning Rogge

[permalink] [raw]
Subject: [PATCH v3 0/3] mac80211: add cleanup path for MPP table entries

Currently MPP table entries are only removed from memory when their
802.11s mesh interface goes down. This can make the kernel to remember
a growing list of proxied mac addresses which are not relevant or even
reachable anymore.

This patchset adds two additional cleanup paths for MPP table entries
to remove them when their corresponding mesh node is removed or when
the MPP table entry is not used for MESH_PATH_EXPIRE time.

Henning Rogge (3):
mac80211: Remove MPP table entries with MPath
mac80211: let unused MPP table entries timeout
mac80211: Unify mesh and mpp path removal function

net/mac80211/mesh_pathtbl.c | 102 +++++++++++++++++++++++++++++++++++++++-----
net/mac80211/rx.c | 1 +
net/mac80211/tx.c | 5 ++-
3 files changed, 97 insertions(+), 11 deletions(-)

--
2.5.0



2016-02-04 08:53:08

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 0/3] mac80211: add cleanup path for MPP table entries

On Wed, 2016-02-03 at 22:32 -0500, Bob Copeland wrote:
> On Wed, Feb 03, 2016 at 01:58:35PM +0100, Henning Rogge wrote:
> > Henning Rogge (3):
> >   mac80211: Remove MPP table entries with MPath
> >   mac80211: let unused MPP table entries timeout
> >   mac80211: Unify mesh and mpp path removal function
> >
> >  net/mac80211/mesh_pathtbl.c | 102
> > +++++++++++++++++++++++++++++++++++++++-----
> >  net/mac80211/rx.c           |   1 +
> >  net/mac80211/tx.c           |   5 ++-
> >  3 files changed, 97 insertions(+), 11 deletions(-)
>
> Thanks for the revisions.  For what it's worth, series:
>
> Acked-by: Bob Copeland <[email protected]>

All applied to mac80211-next, thanks.

johannes

2016-02-03 12:58:49

by Henning Rogge

[permalink] [raw]
Subject: [PATCH v3 2/3] mac80211: let unused MPP table entries timeout

Remember the last time when a mpp table entry is used for
rx or tx and remove them after MESH_PATH_EXPIRE time.

Signed-off-by: Henning Rogge <[email protected]>
---
net/mac80211/mesh_pathtbl.c | 51 +++++++++++++++++++++++++++++++++++++++++++++
net/mac80211/rx.c | 1 +
net/mac80211/tx.c | 5 ++++-
3 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index d9424ea..0ab862a 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -942,6 +942,46 @@ enddel:
}

/**
+ * mpp_path_del - delete a mesh proxy path from the table
+ *
+ * @addr: addr address (ETH_ALEN length)
+ * @sdata: local subif
+ *
+ * Returns: 0 if successful
+ */
+static int mpp_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
+{
+ struct mesh_table *tbl;
+ struct mesh_path *mpath;
+ struct mpath_node *node;
+ struct hlist_head *bucket;
+ int hash_idx;
+ int err = 0;
+
+ read_lock_bh(&pathtbl_resize_lock);
+ tbl = resize_dereference_mpp_paths();
+ 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)) {
+ __mesh_path_del(tbl, node);
+ goto enddel;
+ }
+ }
+
+ err = -ENXIO;
+enddel:
+ mesh_paths_generation++;
+ spin_unlock(&tbl->hashwlock[hash_idx]);
+ read_unlock_bh(&pathtbl_resize_lock);
+ return err;
+}
+
+/**
* mesh_path_tx_pending - sends pending frames in a mesh path queue
*
* @mpath: mesh path to activate
@@ -1157,6 +1197,17 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
mesh_path_del(mpath->sdata, mpath->dst);
}
+
+ tbl = rcu_dereference(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);
+ }
+
rcu_read_unlock();
}

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index bc08185..d028581 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2290,6 +2290,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
spin_lock_bh(&mppath->state_lock);
if (!ether_addr_equal(mppath->mpp, mpp_addr))
memcpy(mppath->mpp, mpp_addr, ETH_ALEN);
+ mppath->exp_time = jiffies;
spin_unlock_bh(&mppath->state_lock);
}
rcu_read_unlock();
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3311ce0..932309e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2099,8 +2099,11 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
mpp_lookup = true;
}

- if (mpp_lookup)
+ if (mpp_lookup) {
mppath = mpp_path_lookup(sdata, skb->data);
+ if (mppath)
+ mppath->exp_time = jiffies;
+ }

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


2016-02-04 03:32:54

by Bob Copeland

[permalink] [raw]
Subject: Re: [PATCH v3 0/3] mac80211: add cleanup path for MPP table entries

On Wed, Feb 03, 2016 at 01:58:35PM +0100, Henning Rogge wrote:
> Henning Rogge (3):
> mac80211: Remove MPP table entries with MPath
> mac80211: let unused MPP table entries timeout
> mac80211: Unify mesh and mpp path removal function
>
> net/mac80211/mesh_pathtbl.c | 102 +++++++++++++++++++++++++++++++++++++++-----
> net/mac80211/rx.c | 1 +
> net/mac80211/tx.c | 5 ++-
> 3 files changed, 97 insertions(+), 11 deletions(-)

Thanks for the revisions. For what it's worth, series:

Acked-by: Bob Copeland <[email protected]>

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

2016-02-03 12:58:50

by Henning Rogge

[permalink] [raw]
Subject: [PATCH v3 3/3] mac80211: Unify mesh and mpp path removal function

mpp_path_del() and mesh_path_del() are mostly the same function.
Move common code into a new static function.

Signed-off-by: Henning Rogge <[email protected]>
---
net/mac80211/mesh_pathtbl.c | 77 ++++++++++++++++++++++++---------------------
1 file changed, 41 insertions(+), 36 deletions(-)

diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 0ab862a..f85262d 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -55,16 +55,21 @@ int mpp_paths_generation;
static DEFINE_RWLOCK(pathtbl_resize_lock);


+static inline struct mesh_table *resize_dereference_paths(
+ struct mesh_table __rcu *table)
+{
+ return rcu_dereference_protected(table,
+ lockdep_is_held(&pathtbl_resize_lock));
+}
+
static inline struct mesh_table *resize_dereference_mesh_paths(void)
{
- return rcu_dereference_protected(mesh_paths,
- lockdep_is_held(&pathtbl_resize_lock));
+ return resize_dereference_paths(mesh_paths);
}

static inline struct mesh_table *resize_dereference_mpp_paths(void)
{
- return rcu_dereference_protected(mpp_paths,
- lockdep_is_held(&pathtbl_resize_lock));
+ return resize_dereference_paths(mpp_paths);
}

/*
@@ -899,14 +904,17 @@ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
}

/**
- * mesh_path_del - delete a mesh path from the table
+ * table_path_del - delete a path from the mesh or mpp table
*
- * @addr: dst address (ETH_ALEN length)
+ * @tbl: mesh or mpp path table
* @sdata: local subif
+ * @addr: dst address (ETH_ALEN length)
*
* Returns: 0 if successful
*/
-int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
+static int table_path_del(struct mesh_table __rcu *rcu_tbl,
+ struct ieee80211_sub_if_data *sdata,
+ const u8 *addr)
{
struct mesh_table *tbl;
struct mesh_path *mpath;
@@ -915,11 +923,7 @@ int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
int hash_idx;
int err = 0;

- /* flush relevant mpp entries first */
- mpp_flush_by_proxy(sdata, addr);
-
- read_lock_bh(&pathtbl_resize_lock);
- tbl = resize_dereference_mesh_paths();
+ tbl = resize_dereference_paths(rcu_tbl);
hash_idx = mesh_table_hash(addr, sdata, tbl);
bucket = &tbl->hash_buckets[hash_idx];

@@ -935,9 +939,30 @@ int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)

err = -ENXIO;
enddel:
- mesh_paths_generation++;
spin_unlock(&tbl->hashwlock[hash_idx]);
+ return err;
+}
+
+/**
+ * mesh_path_del - delete a mesh path from the table
+ *
+ * @addr: dst address (ETH_ALEN length)
+ * @sdata: local subif
+ *
+ * Returns: 0 if successful
+ */
+int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
+{
+ int err = 0;
+
+ /* 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);
+
return err;
}

@@ -951,33 +976,13 @@ enddel:
*/
static int mpp_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
{
- struct mesh_table *tbl;
- struct mesh_path *mpath;
- struct mpath_node *node;
- struct hlist_head *bucket;
- int hash_idx;
int err = 0;

read_lock_bh(&pathtbl_resize_lock);
- tbl = resize_dereference_mpp_paths();
- 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)) {
- __mesh_path_del(tbl, node);
- goto enddel;
- }
- }
-
- err = -ENXIO;
-enddel:
- mesh_paths_generation++;
- spin_unlock(&tbl->hashwlock[hash_idx]);
+ err = table_path_del(mpp_paths, sdata, addr);
+ mpp_paths_generation++;
read_unlock_bh(&pathtbl_resize_lock);
+
return err;
}

--
2.5.0


2016-02-03 12:58:47

by Henning Rogge

[permalink] [raw]
Subject: [PATCH v3 1/3] mac80211: Remove MPP table entries with MPath

Make the mesh_path_del() function remove all mpp table entries
that are proxied by the removed mesh path.

Signed-off-by: Henning Rogge <[email protected]>
---
net/mac80211/mesh_pathtbl.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index dadf8dc..d9424ea 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -835,6 +835,29 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
rcu_read_unlock();
}

+static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata,
+ const u8 *proxy)
+{
+ struct mesh_table *tbl;
+ struct mesh_path *mpp;
+ struct mpath_node *node;
+ int i;
+
+ rcu_read_lock();
+ read_lock_bh(&pathtbl_resize_lock);
+ tbl = resize_dereference_mpp_paths();
+ for_each_mesh_entry(tbl, node, i) {
+ mpp = node->mpath;
+ if (ether_addr_equal(mpp->mpp, proxy)) {
+ spin_lock(&tbl->hashwlock[i]);
+ __mesh_path_del(tbl, node);
+ spin_unlock(&tbl->hashwlock[i]);
+ }
+ }
+ read_unlock_bh(&pathtbl_resize_lock);
+ rcu_read_unlock();
+}
+
static void table_flush_by_iface(struct mesh_table *tbl,
struct ieee80211_sub_if_data *sdata)
{
@@ -892,6 +915,9 @@ int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
int hash_idx;
int err = 0;

+ /* flush relevant mpp entries first */
+ mpp_flush_by_proxy(sdata, addr);
+
read_lock_bh(&pathtbl_resize_lock);
tbl = resize_dereference_mesh_paths();
hash_idx = mesh_table_hash(addr, sdata, tbl);
--
2.5.0