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
