From 1933dc0aa3ec2b6bb06452f29929512ac7cf5c8c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 7 Feb 2016 14:29:51 +0000 Subject: [PATCH] mac80211: merge a few mesh fixes Signed-off-by: Felix Fietkau SVN-Revision: 48647 --- ...-Remove-MPP-table-entries-with-MPath.patch | 54 +++++++ ...let-unused-MPP-table-entries-timeout.patch | 104 +++++++++++++ ...y-mesh-and-mpp-path-removal-function.patch | 143 ++++++++++++++++++ 3 files changed, 301 insertions(+) create mode 100644 package/kernel/mac80211/patches/327-mac80211-Remove-MPP-table-entries-with-MPath.patch create mode 100644 package/kernel/mac80211/patches/328-mac80211-let-unused-MPP-table-entries-timeout.patch create mode 100644 package/kernel/mac80211/patches/329-mac80211-Unify-mesh-and-mpp-path-removal-function.patch diff --git a/package/kernel/mac80211/patches/327-mac80211-Remove-MPP-table-entries-with-MPath.patch b/package/kernel/mac80211/patches/327-mac80211-Remove-MPP-table-entries-with-MPath.patch new file mode 100644 index 00000000000..f7f9df946a4 --- /dev/null +++ b/package/kernel/mac80211/patches/327-mac80211-Remove-MPP-table-entries-with-MPath.patch @@ -0,0 +1,54 @@ +From: Henning Rogge +Date: Wed, 3 Feb 2016 13:58:36 +0100 +Subject: [PATCH] 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. + +Acked-by: Bob Copeland +Signed-off-by: Henning Rogge +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/mesh_pathtbl.c ++++ b/net/mac80211/mesh_pathtbl.c +@@ -835,6 +835,29 @@ void mesh_path_flush_by_nexthop(struct s + 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_i + 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); diff --git a/package/kernel/mac80211/patches/328-mac80211-let-unused-MPP-table-entries-timeout.patch b/package/kernel/mac80211/patches/328-mac80211-let-unused-MPP-table-entries-timeout.patch new file mode 100644 index 00000000000..740993c9e02 --- /dev/null +++ b/package/kernel/mac80211/patches/328-mac80211-let-unused-MPP-table-entries-timeout.patch @@ -0,0 +1,104 @@ +From: Henning Rogge +Date: Wed, 3 Feb 2016 13:58:37 +0100 +Subject: [PATCH] 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. + +Acked-by: Bob Copeland +Signed-off-by: Henning Rogge +Signed-off-by: Johannes Berg +--- + +--- 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_s + 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(); + } + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2291,6 +2291,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 + 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(); +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -2171,8 +2171,11 @@ static struct sk_buff *ieee80211_build_h + 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); diff --git a/package/kernel/mac80211/patches/329-mac80211-Unify-mesh-and-mpp-path-removal-function.patch b/package/kernel/mac80211/patches/329-mac80211-Unify-mesh-and-mpp-path-removal-function.patch new file mode 100644 index 00000000000..0c36b1d5687 --- /dev/null +++ b/package/kernel/mac80211/patches/329-mac80211-Unify-mesh-and-mpp-path-removal-function.patch @@ -0,0 +1,143 @@ +From: Henning Rogge +Date: Wed, 3 Feb 2016 13:58:38 +0100 +Subject: [PATCH] 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. + +Acked-by: Bob Copeland +Signed-off-by: Henning Rogge +Signed-off-by: Johannes Berg +--- + +--- 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 iee + } + + /** +- * 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_i + 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_i + + 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; + } +