An companion kernel patch to go with the iw-3.3 patch
(Message-Id: <[email protected]>)

It is made against wireless-testing tree:

commit 485e999d7d258023dc98b7ba7e6aa0ae06cff17b
Merge: e0cfbaa d987569
Author: John W. Linville <[email protected]>
Date:   Fri Aug 17 08:35:13 2012 -0400

The patch can be applied to OpenWrt trunk r33276
with some offsets.

The design of the patch is really ugly to avoid adding
additional cfg80211 calls;
the net/mac80211/mesh_pathtbl.c:mesh_path_lookup_by_idx()
was expanded to loop through mpp_paths and known_gates
lists in addition to the original mesh_paths.

Despite the effort, and quite ironically, the
include/net/cfg80211.h had to be changed to increase
the mpath_info.flag bits (sigh).

--- shinoda

---
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 2f38788..9e5a467 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1789,6 +1789,10 @@ enum nl80211_mpath_flags {
        NL80211_MPATH_FLAG_SN_VALID =   1<<2,
        NL80211_MPATH_FLAG_FIXED =      1<<3,
        NL80211_MPATH_FLAG_RESOLVED =   1<<4,
+       NL80211_MPATH_FLAG_IS_ROOT =    1<<5,
+       NL80211_MPATH_FLAG_IS_GATE =    1<<6,
+       NL80211_MPATH_FLAG_IS_MPPPATH = 1<<7,
+       NL80211_MPATH_FLAG_IS_KNOWN_GATE = 1<<8,
 };
 
 /**
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3d254e1..a79fe15 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -780,7 +780,7 @@ struct mpath_info {
        u32 exptime;
        u32 discovery_timeout;
        u8 discovery_retries;
-       u8 flags;
+       u32 flags;
 
        int generation;
 };
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d41974a..72d4317 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1373,11 +1373,15 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 
*next_hop,
 {
        struct sta_info *next_hop_sta = rcu_dereference(mpath->next_hop);
 
-       if (next_hop_sta)
+       if (mpath->is_mpppath)
+               memcpy(next_hop, mpath->mpp, ETH_ALEN);
+       else if (next_hop_sta)
                memcpy(next_hop, next_hop_sta->sta.addr, ETH_ALEN);
        else
                memset(next_hop, 0, ETH_ALEN);
 
+       memset(pinfo, 0, sizeof(struct mpath_info));
+
        pinfo->generation = mesh_paths_generation;
 
        pinfo->filled = MPATH_INFO_FRAME_QLEN |
@@ -1396,7 +1400,6 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 
*next_hop,
        pinfo->discovery_timeout =
                        jiffies_to_msecs(mpath->discovery_timeout);
        pinfo->discovery_retries = mpath->discovery_retries;
-       pinfo->flags = 0;
        if (mpath->flags & MESH_PATH_ACTIVE)
                pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
        if (mpath->flags & MESH_PATH_RESOLVING)
@@ -1405,10 +1408,16 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 
*next_hop,
                pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID;
        if (mpath->flags & MESH_PATH_FIXED)
                pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
-       if (mpath->flags & MESH_PATH_RESOLVING)
-               pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
-
-       pinfo->flags = mpath->flags;
+       if (mpath->flags & MESH_PATH_RESOLVED)
+               pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED;
+       if (mpath->is_root)
+               pinfo->flags |= NL80211_MPATH_FLAG_IS_ROOT;
+       if (mpath->is_gate)
+               pinfo->flags |= NL80211_MPATH_FLAG_IS_GATE;
+       if (mpath->is_mpppath)
+               pinfo->flags |= NL80211_MPATH_FLAG_IS_MPPPATH;
+       if (mpath->is_known_gate)
+               pinfo->flags |= NL80211_MPATH_FLAG_IS_KNOWN_GATE;
 }
 
 static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
@@ -1423,8 +1432,11 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, 
struct net_device *dev,
        rcu_read_lock();
        mpath = mesh_path_lookup(dst, sdata);
        if (!mpath) {
-               rcu_read_unlock();
-               return -ENOENT;
+               mpath = mpp_path_lookup(dst, sdata);
+               if (!mpath) {
+                       rcu_read_unlock();
+                       return -ENOENT;
+               }
        }
        memcpy(dst, mpath->dst, ETH_ALEN);
        mpath_set_pinfo(mpath, next_hop, pinfo);
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 13fd5b5..fe68140 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -135,6 +135,8 @@ struct mesh_path {
        unsigned long last_preq_to_root;
        bool is_root;
        bool is_gate;
+       bool is_mpppath;
+       bool is_known_gate;
 };
 
 /**
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 075bc53..56ad9e1 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -399,10 +399,43 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct 
ieee80211_sub_if_data
                                node->mpath->flags &= ~MESH_PATH_ACTIVE;
                                spin_unlock_bh(&node->mpath->state_lock);
                        }
+                       node->mpath->is_known_gate = false; // XXX Ugly...
                        return node->mpath;
                }
        }
 
+       tbl = rcu_dereference(mpp_paths);
+
+       for_each_mesh_entry(tbl, p, node, i) {
+               if (sdata && node->mpath->sdata != sdata)
+                       continue;
+               if (j++ == idx) {
+                       // mpp paths do not have expiration?
+                       if (MPATH_EXPIRED(node->mpath)) {
+                               spin_lock_bh(&node->mpath->state_lock);
+                               node->mpath->flags &= ~MESH_PATH_ACTIVE;
+                               spin_unlock_bh(&node->mpath->state_lock);
+                       }
+                       node->mpath->is_known_gate = false; // XXX Ugly...
+                       return node->mpath;
+               }
+       }
+
+       tbl = rcu_dereference(mesh_paths);
+
+    {
+       struct mpath_node *gate;
+       struct hlist_node *n;
+
+       hlist_for_each_entry_rcu(gate, n, tbl->known_gates, list)
+       {
+               if (j++ == idx) {
+                       gate->mpath->is_known_gate = true;
+                       return gate->mpath;
+               }
+       }
+    }
+
        return NULL;
 }
 
@@ -535,6 +568,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data 
*sdata)
        new_mpath->is_root = false;
        new_mpath->sdata = sdata;
        new_mpath->flags = 0;
+       new_mpath->is_mpppath = false;
        skb_queue_head_init(&new_mpath->frame_queue);
        new_node->mpath = new_mpath;
        new_mpath->timer.data = (unsigned long) new_mpath;
@@ -666,6 +700,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct 
ieee80211_sub_if_data *sdata)
        memcpy(new_mpath->mpp, mpp, ETH_ALEN);
        new_mpath->sdata = sdata;
        new_mpath->flags = 0;
+       new_mpath->is_mpppath = true;
        skb_queue_head_init(&new_mpath->frame_queue);
        new_node->mpath = new_mpath;
        init_timer(&new_mpath->timer);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 97026f3..1d0280d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3314,7 +3314,7 @@ static int nl80211_send_mpath(struct sk_buff *msg, u32 
pid, u32 seq,
             nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME,
                         pinfo->exptime)) ||
            ((pinfo->filled & MPATH_INFO_FLAGS) &&
-            nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS,
+            nla_put_u32(msg, NL80211_MPATH_INFO_FLAGS,
                        pinfo->flags)) ||
            ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) &&
             nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
---

_______________________________________________
Devel mailing list
[email protected]
http://lists.open80211s.org/cgi-bin/mailman/listinfo/devel

Reply via email to