Commit d2a079fd authored by Chun-Yeow Yeoh's avatar Chun-Yeow Yeoh Committed by John W. Linville

mac80211: fix the RANN propagation issues

This patch is intended to solve the follwing issues in RANN propagation:
[1] The interval in propagated RANN should be based on the interval of received RANN.
[2] The aggregated path metric for propagated RANN is as received plus own link metric
    towards the transmitting mesh STA (not root mesh STA).
[3] The comparison of path metric for RANN with same sequence number should be done
    before deciding whether to propagate or not.
Signed-off-by: default avatarChun-Yeow Yeoh <yeohchunyeow@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 30899cc6
...@@ -86,6 +86,7 @@ enum mesh_deferred_task_flags { ...@@ -86,6 +86,7 @@ enum mesh_deferred_task_flags {
* mpath itself. No need to take this lock when adding or removing * mpath itself. No need to take this lock when adding or removing
* an mpath to a hash bucket on a path table. * an mpath to a hash bucket on a path table.
* @rann_snd_addr: the RANN sender address * @rann_snd_addr: the RANN sender address
* @rann_metric: the aggregated path metric towards the root node
* @is_root: the destination station of this path is a root node * @is_root: the destination station of this path is a root node
* @is_gate: the destination station of this path is a mesh gate * @is_gate: the destination station of this path is a mesh gate
* *
...@@ -112,6 +113,7 @@ struct mesh_path { ...@@ -112,6 +113,7 @@ struct mesh_path {
enum mesh_path_flags flags; enum mesh_path_flags flags;
spinlock_t state_lock; spinlock_t state_lock;
u8 rann_snd_addr[ETH_ALEN]; u8 rann_snd_addr[ETH_ALEN];
u32 rann_metric;
bool is_root; bool is_root;
bool is_gate; bool is_gate;
}; };
......
...@@ -86,8 +86,8 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae) ...@@ -86,8 +86,8 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
#define PERR_IE_TARGET_RCODE(x) u16_field_get(x, 13, 0) #define PERR_IE_TARGET_RCODE(x) u16_field_get(x, 13, 0)
#define MSEC_TO_TU(x) (x*1000/1024) #define MSEC_TO_TU(x) (x*1000/1024)
#define SN_GT(x, y) ((long) (y) - (long) (x) < 0) #define SN_GT(x, y) ((s32)(y - x) < 0)
#define SN_LT(x, y) ((long) (x) - (long) (y) < 0) #define SN_LT(x, y) ((s32)(x - y) < 0)
#define net_traversal_jiffies(s) \ #define net_traversal_jiffies(s) \
msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
...@@ -732,11 +732,12 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -732,11 +732,12 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
struct ieee80211_rann_ie *rann) struct ieee80211_rann_ie *rann)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
struct mesh_path *mpath; struct mesh_path *mpath;
u8 ttl, flags, hopcount; u8 ttl, flags, hopcount;
u8 *orig_addr; u8 *orig_addr;
u32 orig_sn, metric; u32 orig_sn, metric, metric_txsta, interval;
u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
bool root_is_gate; bool root_is_gate;
ttl = rann->rann_ttl; ttl = rann->rann_ttl;
...@@ -749,6 +750,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -749,6 +750,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
root_is_gate = !!(flags & RANN_FLAG_IS_GATE); root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
orig_addr = rann->rann_addr; orig_addr = rann->rann_addr;
orig_sn = le32_to_cpu(rann->rann_seq); orig_sn = le32_to_cpu(rann->rann_seq);
interval = le32_to_cpu(rann->rann_interval);
hopcount = rann->rann_hopcount; hopcount = rann->rann_hopcount;
hopcount++; hopcount++;
metric = le32_to_cpu(rann->rann_metric); metric = le32_to_cpu(rann->rann_metric);
...@@ -761,6 +763,14 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -761,6 +763,14 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
orig_addr, mgmt->sa, root_is_gate); orig_addr, mgmt->sa, root_is_gate);
rcu_read_lock(); rcu_read_lock();
sta = sta_info_get(sdata, mgmt->sa);
if (!sta) {
rcu_read_unlock();
return;
}
metric_txsta = airtime_link_metric_get(local, sta);
mpath = mesh_path_lookup(orig_addr, sdata); mpath = mesh_path_lookup(orig_addr, sdata);
if (!mpath) { if (!mpath) {
mesh_path_add(orig_addr, sdata); mesh_path_add(orig_addr, sdata);
...@@ -780,14 +790,16 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -780,14 +790,16 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
} }
if (mpath->sn < orig_sn && ifmsh->mshcfg.dot11MeshForwarding) { if ((SN_LT(mpath->sn, orig_sn) || (mpath->sn == orig_sn &&
metric < mpath->rann_metric)) && ifmsh->mshcfg.dot11MeshForwarding) {
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
cpu_to_le32(orig_sn), cpu_to_le32(orig_sn),
0, NULL, 0, broadcast_addr, 0, NULL, 0, broadcast_addr,
hopcount, ttl, cpu_to_le32(interval), hopcount, ttl, cpu_to_le32(interval),
cpu_to_le32(metric + mpath->metric), cpu_to_le32(metric + metric_txsta),
0, sdata); 0, sdata);
mpath->sn = orig_sn; mpath->sn = orig_sn;
mpath->rann_metric = metric + metric_txsta;
} }
/* Using individually addressed PREQ for root node */ /* Using individually addressed PREQ for root node */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment