mac80211: merge a few mesh fixes
authorFelix Fietkau <nbd@openwrt.org>
Sun, 7 Feb 2016 14:29:51 +0000 (14:29 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 7 Feb 2016 14:29:51 +0000 (14:29 +0000)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 48647

package/kernel/mac80211/patches/327-mac80211-Remove-MPP-table-entries-with-MPath.patch [new file with mode: 0644]
package/kernel/mac80211/patches/328-mac80211-let-unused-MPP-table-entries-timeout.patch [new file with mode: 0644]
package/kernel/mac80211/patches/329-mac80211-Unify-mesh-and-mpp-path-removal-function.patch [new file with mode: 0644]

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 (file)
index 0000000..f7f9df9
--- /dev/null
@@ -0,0 +1,54 @@
+From: Henning Rogge <hrogge@gmail.com>
+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 <me@bobcopeland.com>
+Signed-off-by: Henning Rogge <henning.rogge@fkie.fraunhofer.de>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- 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 (file)
index 0000000..740993c
--- /dev/null
@@ -0,0 +1,104 @@
+From: Henning Rogge <hrogge@gmail.com>
+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 <me@bobcopeland.com>
+Signed-off-by: Henning Rogge <henning.rogge@fkie.fraunhofer.de>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- 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 (file)
index 0000000..0c36b1d
--- /dev/null
@@ -0,0 +1,143 @@
+From: Henning Rogge <hrogge@gmail.com>
+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 <me@bobcopeland.com>
+Signed-off-by: Henning Rogge <henning.rogge@fkie.fraunhofer.de>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- 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;
+ }