mac80211: let unused MPP table entries timeout
authorHenning Rogge <hrogge@gmail.com>
Wed, 3 Feb 2016 12:58:37 +0000 (13:58 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 24 Feb 2016 08:04:35 +0000 (09:04 +0100)
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>
net/mac80211/mesh_pathtbl.c
net/mac80211/rx.c
net/mac80211/tx.c

index 40ed206b0f60a531342f4b27c62ee3ce091ade8a..29e50407507a04391ca3fc8517bcdee9ade91cd2 100644 (file)
@@ -940,6 +940,46 @@ enddel:
        return err;
 }
 
+/**
+ * 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
  *
@@ -1154,6 +1194,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();
 }
 
index 44192143ebdf0c3fe7b257e033931998aa671292..91279576f4a716d00cfd810e5d6db18306520c1c 100644 (file)
@@ -2311,6 +2311,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();
index a5aa275d043455098d6caf3225b6c775dd2d5a1a..7bb67fa9f4d26ee5acf28b411b8558f4420f40c0 100644 (file)
@@ -2173,8 +2173,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);