Commit 3eb0928f authored by Manoharan, Rajkumar's avatar Manoharan, Rajkumar Committed by Johannes Berg

mac80211: use DECLARE_EWMA for mesh_fail_avg

As moving average is not considering fractional part, it will
get stuck at the same level after certain state. For example,
with current values, it can get stuck at 96. Fortunately the
current threshold 95%, but if it were increased to 96 or more
mesh paths would never be deactivated. Fix failure average
movement by using EWMA helpers, which does take into account
fractional parts.
Signed-off-by: default avatarRajkumar Manoharan <rmanohar@qca.qualcomm.com>
[johannes: pick a larger EWMA factor for more precision with
 the limited range that we will feed into it, adjust to new API]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 8d70eeb8
...@@ -307,10 +307,11 @@ void ieee80211s_update_metric(struct ieee80211_local *local, ...@@ -307,10 +307,11 @@ void ieee80211s_update_metric(struct ieee80211_local *local,
failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK); failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
/* moving average, scaled to 100 */ /* moving average, scaled to 100.
sta->mesh->fail_avg = * feed failure as 100 and success as 0
((80 * sta->mesh->fail_avg + 5) / 100 + 20 * failed); */
if (sta->mesh->fail_avg > 95) ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, failed * 100);
if (ewma_mesh_fail_avg_read(&sta->mesh->fail_avg) > 95)
mesh_plink_broken(sta); mesh_plink_broken(sta);
} }
...@@ -325,6 +326,8 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, ...@@ -325,6 +326,8 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
int rate, err; int rate, err;
u32 tx_time, estimated_retx; u32 tx_time, estimated_retx;
u64 result; u64 result;
unsigned long fail_avg =
ewma_mesh_fail_avg_read(&sta->mesh->fail_avg);
/* Try to get rate based on HW/SW RC algorithm. /* Try to get rate based on HW/SW RC algorithm.
* Rate is returned in units of Kbps, correct this * Rate is returned in units of Kbps, correct this
...@@ -336,7 +339,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, ...@@ -336,7 +339,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
if (rate) { if (rate) {
err = 0; err = 0;
} else { } else {
if (sta->mesh->fail_avg >= 100) if (fail_avg >= 100)
return MAX_METRIC; return MAX_METRIC;
sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo); sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
...@@ -344,7 +347,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, ...@@ -344,7 +347,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
if (WARN_ON(!rate)) if (WARN_ON(!rate))
return MAX_METRIC; return MAX_METRIC;
err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100; err = (fail_avg << ARITH_SHIFT) / 100;
} }
/* bitrate is in units of 100 Kbps, while we need rate in units of /* bitrate is in units of 100 Kbps, while we need rate in units of
...@@ -484,6 +487,9 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, ...@@ -484,6 +487,9 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
? mpath->exp_time : exp_time; ? mpath->exp_time : exp_time;
mesh_path_activate(mpath); mesh_path_activate(mpath);
spin_unlock_bh(&mpath->state_lock); spin_unlock_bh(&mpath->state_lock);
ewma_mesh_fail_avg_init(&sta->mesh->fail_avg);
/* init it at a low value - 0 start is tricky */
ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1);
mesh_path_tx_pending(mpath); mesh_path_tx_pending(mpath);
/* draft says preq_id should be saved to, but there does /* draft says preq_id should be saved to, but there does
* not seem to be any use for it, skipping by now * not seem to be any use for it, skipping by now
...@@ -522,6 +528,9 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, ...@@ -522,6 +528,9 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
? mpath->exp_time : exp_time; ? mpath->exp_time : exp_time;
mesh_path_activate(mpath); mesh_path_activate(mpath);
spin_unlock_bh(&mpath->state_lock); spin_unlock_bh(&mpath->state_lock);
ewma_mesh_fail_avg_init(&sta->mesh->fail_avg);
/* init it at a low value - 0 start is tricky */
ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1);
mesh_path_tx_pending(mpath); mesh_path_tx_pending(mpath);
} else } else
spin_unlock_bh(&mpath->state_lock); spin_unlock_bh(&mpath->state_lock);
......
...@@ -829,6 +829,9 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop) ...@@ -829,6 +829,9 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop)
mpath->flags = MESH_PATH_FIXED | MESH_PATH_SN_VALID; mpath->flags = MESH_PATH_FIXED | MESH_PATH_SN_VALID;
mesh_path_activate(mpath); mesh_path_activate(mpath);
spin_unlock_bh(&mpath->state_lock); spin_unlock_bh(&mpath->state_lock);
ewma_mesh_fail_avg_init(&next_hop->mesh->fail_avg);
/* init it at a low value - 0 start is tricky */
ewma_mesh_fail_avg_add(&next_hop->mesh->fail_avg, 1);
mesh_path_tx_pending(mpath); mesh_path_tx_pending(mpath);
} }
......
...@@ -324,6 +324,9 @@ struct ieee80211_fast_rx { ...@@ -324,6 +324,9 @@ struct ieee80211_fast_rx {
struct rcu_head rcu_head; struct rcu_head rcu_head;
}; };
/* we use only values in the range 0-100, so pick a large precision */
DECLARE_EWMA(mesh_fail_avg, 20, 8)
/** /**
* struct mesh_sta - mesh STA information * struct mesh_sta - mesh STA information
* @plink_lock: serialize access to plink fields * @plink_lock: serialize access to plink fields
...@@ -369,7 +372,7 @@ struct mesh_sta { ...@@ -369,7 +372,7 @@ struct mesh_sta {
enum nl80211_mesh_power_mode nonpeer_pm; enum nl80211_mesh_power_mode nonpeer_pm;
/* moving percentage of failed MSDUs */ /* moving percentage of failed MSDUs */
unsigned int fail_avg; struct ewma_mesh_fail_avg fail_avg;
}; };
DECLARE_EWMA(signal, 10, 8) DECLARE_EWMA(signal, 10, 8)
......
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