|
@@ -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 MSEC_TO_TU(x) (x*1000/1024)
|
|
|
-#define SN_GT(x, y) ((long) (y) - (long) (x) < 0)
|
|
|
-#define SN_LT(x, y) ((long) (x) - (long) (y) < 0)
|
|
|
+#define SN_GT(x, y) ((s32)(y - x) < 0)
|
|
|
+#define SN_LT(x, y) ((s32)(x - y) < 0)
|
|
|
|
|
|
#define net_traversal_jiffies(s) \
|
|
|
msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
|
|
@@ -732,11 +732,12 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
|
|
|
struct ieee80211_rann_ie *rann)
|
|
|
{
|
|
|
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
|
|
+ struct ieee80211_local *local = sdata->local;
|
|
|
+ struct sta_info *sta;
|
|
|
struct mesh_path *mpath;
|
|
|
u8 ttl, flags, hopcount;
|
|
|
u8 *orig_addr;
|
|
|
- u32 orig_sn, metric;
|
|
|
- u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
|
|
|
+ u32 orig_sn, metric, metric_txsta, interval;
|
|
|
bool root_is_gate;
|
|
|
|
|
|
ttl = rann->rann_ttl;
|
|
@@ -749,6 +750,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
|
|
|
root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
|
|
|
orig_addr = rann->rann_addr;
|
|
|
orig_sn = le32_to_cpu(rann->rann_seq);
|
|
|
+ interval = le32_to_cpu(rann->rann_interval);
|
|
|
hopcount = rann->rann_hopcount;
|
|
|
hopcount++;
|
|
|
metric = le32_to_cpu(rann->rann_metric);
|
|
@@ -761,6 +763,14 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
|
|
|
orig_addr, mgmt->sa, root_is_gate);
|
|
|
|
|
|
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);
|
|
|
if (!mpath) {
|
|
|
mesh_path_add(orig_addr, 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);
|
|
|
}
|
|
|
|
|
|
- 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,
|
|
|
cpu_to_le32(orig_sn),
|
|
|
0, NULL, 0, broadcast_addr,
|
|
|
hopcount, ttl, cpu_to_le32(interval),
|
|
|
- cpu_to_le32(metric + mpath->metric),
|
|
|
+ cpu_to_le32(metric + metric_txsta),
|
|
|
0, sdata);
|
|
|
mpath->sn = orig_sn;
|
|
|
+ mpath->rann_metric = metric + metric_txsta;
|
|
|
}
|
|
|
|
|
|
/* Using individually addressed PREQ for root node */
|