aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Huehn <thomas@net.t-labs.tu-berlin.de>2015-03-24 16:09:43 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-04-01 14:44:33 -0400
commit5f919abc76fc3de1e5965ea03c925f7563c7fc15 (patch)
tree8ed67f827d3b66cbfb140c66d8cd2d0f115633a6
parentade6d4a2ec57d258bc181a155288c267dd8cf094 (diff)
mac80211: add standard deviation to Minstrel stats
This patch adds the statistical descriptor "standard deviation" to better describe the current properties of Minstrel and Minstrel-HTs success probability distribution. The standard deviation (SD) is calculated as exponential weighted moving standard deviation (EWMSD) and its current value is added as new column in all rc_stats (in debugfs). Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de> Acked-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/rc80211_minstrel.c19
-rw-r--r--net/mac80211/rc80211_minstrel.h22
-rw-r--r--net/mac80211/rc80211_minstrel_debugfs.c19
-rw-r--r--net/mac80211/rc80211_minstrel_ht_debugfs.c14
4 files changed, 56 insertions, 18 deletions
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index c4a3477812ee..247552a7f6c2 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -153,7 +153,7 @@ minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
153} 153}
154 154
155/* 155/*
156* Recalculate success probabilities and counters for a given rate using EWMA 156* Recalculate statistics and counters of a given rate
157*/ 157*/
158void 158void
159minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) 159minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs)
@@ -161,11 +161,20 @@ minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs)
161 if (unlikely(mrs->attempts > 0)) { 161 if (unlikely(mrs->attempts > 0)) {
162 mrs->sample_skipped = 0; 162 mrs->sample_skipped = 0;
163 mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); 163 mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
164 if (unlikely(!mrs->att_hist)) 164 if (unlikely(!mrs->att_hist)) {
165 mrs->prob_ewma = mrs->cur_prob; 165 mrs->prob_ewma = mrs->cur_prob;
166 else 166 } else {
167 /* update exponential weighted moving variance */
168 mrs->prob_ewmsd = minstrel_ewmsd(mrs->prob_ewmsd,
169 mrs->cur_prob,
170 mrs->prob_ewma,
171 EWMA_LEVEL);
172
173 /*update exponential weighted moving avarage */
167 mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma, 174 mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
168 mrs->cur_prob, EWMA_LEVEL); 175 mrs->cur_prob,
176 EWMA_LEVEL);
177 }
169 mrs->att_hist += mrs->attempts; 178 mrs->att_hist += mrs->attempts;
170 mrs->succ_hist += mrs->success; 179 mrs->succ_hist += mrs->success;
171 } else { 180 } else {
@@ -193,7 +202,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
193 struct minstrel_rate_stats *mrs = &mi->r[i].stats; 202 struct minstrel_rate_stats *mrs = &mi->r[i].stats;
194 struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats; 203 struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats;
195 204
196 /* Update success probabilities per rate */ 205 /* Update statistics of success probability per rate */
197 minstrel_calc_rate_stats(mrs); 206 minstrel_calc_rate_stats(mrs);
198 207
199 /* Sample less often below the 10% chance of success. 208 /* Sample less often below the 10% chance of success.
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 9c85a610b57b..c230bbe93262 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -35,6 +35,24 @@ minstrel_ewma(int old, int new, int weight)
35 return old + incr; 35 return old + incr;
36} 36}
37 37
38/*
39 * Perform EWMSD (Exponentially Weighted Moving Standard Deviation) calculation
40 */
41static inline int
42minstrel_ewmsd(int old_ewmsd, int cur_prob, int prob_ewma, int weight)
43{
44 int diff, incr, tmp_var;
45
46 /* calculate exponential weighted moving variance */
47 diff = MINSTREL_TRUNC((cur_prob - prob_ewma) * 1000000);
48 incr = (EWMA_DIV - weight) * diff / EWMA_DIV;
49 tmp_var = old_ewmsd * old_ewmsd;
50 tmp_var = weight * (tmp_var + diff * incr / 1000000) / EWMA_DIV;
51
52 /* return standard deviation */
53 return (u16) int_sqrt(tmp_var);
54}
55
38struct minstrel_rate_stats { 56struct minstrel_rate_stats {
39 /* current / last sampling period attempts/success counters */ 57 /* current / last sampling period attempts/success counters */
40 u16 attempts, last_attempts; 58 u16 attempts, last_attempts;
@@ -45,9 +63,11 @@ struct minstrel_rate_stats {
45 63
46 /* statistis of packet delivery probability 64 /* statistis of packet delivery probability
47 * cur_prob - current prob within last update intervall 65 * cur_prob - current prob within last update intervall
48 * prob_ewma - exponential weighted moving average of prob */ 66 * prob_ewma - exponential weighted moving average of prob
67 * prob_ewmsd - exp. weighted moving standard deviation of prob */
49 unsigned int cur_prob; 68 unsigned int cur_prob;
50 unsigned int prob_ewma; 69 unsigned int prob_ewma;
70 u16 prob_ewmsd;
51 71
52 /* maximum retry counts */ 72 /* maximum retry counts */
53 u8 retry_count; 73 u8 retry_count;
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index 617b81f72226..1db5f7c3318a 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -85,10 +85,12 @@ minstrel_stats_open(struct inode *inode, struct file *file)
85 file->private_data = ms; 85 file->private_data = ms;
86 p = ms->buf; 86 p = ms->buf;
87 p += sprintf(p, "\n"); 87 p += sprintf(p, "\n");
88 p += sprintf(p, "best __________rate_________ __statistics__ " 88 p += sprintf(p, "best __________rate_________ ______"
89 "________last_______ ______sum-of________\n"); 89 "statistics______ ________last_______ "
90 p += sprintf(p, "rate [name idx airtime max_tp] [ ø(tp) ø(prob)] " 90 "______sum-of________\n");
91 "[prob.|retry|suc|att] [#success | #attempts]\n"); 91 p += sprintf(p, "rate [name idx airtime max_tp] [ ø(tp) ø(prob) "
92 "sd(prob)] [prob.|retry|suc|att] "
93 "[#success | #attempts]\n");
92 94
93 for (i = 0; i < mi->n_rates; i++) { 95 for (i = 0; i < mi->n_rates; i++) {
94 struct minstrel_rate *mr = &mi->r[i]; 96 struct minstrel_rate *mr = &mi->r[i];
@@ -110,11 +112,13 @@ minstrel_stats_open(struct inode *inode, struct file *file)
110 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 112 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
111 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 113 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
112 114
113 p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u %3u" 115 p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
114 " %3u %-3u %9llu %-9llu\n", 116 " %3u.%1u %3u %3u %-3u "
117 "%9llu %-9llu\n",
115 tp_max / 10, tp_max % 10, 118 tp_max / 10, tp_max % 10,
116 tp_avg / 10, tp_avg % 10, 119 tp_avg / 10, tp_avg % 10,
117 eprob / 10, eprob % 10, 120 eprob / 10, eprob % 10,
121 mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
118 prob / 10, prob % 10, 122 prob / 10, prob % 10,
119 mrs->retry_count, 123 mrs->retry_count,
120 mrs->last_success, 124 mrs->last_success,
@@ -176,11 +180,12 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file)
176 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 180 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
177 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 181 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
178 182
179 p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u," 183 p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
180 "%llu,%llu,%d,%d\n", 184 "%llu,%llu,%d,%d\n",
181 tp_max / 10, tp_max % 10, 185 tp_max / 10, tp_max % 10,
182 tp_avg / 10, tp_avg % 10, 186 tp_avg / 10, tp_avg % 10,
183 eprob / 10, eprob % 10, 187 eprob / 10, eprob % 10,
188 mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
184 prob / 10, prob % 10, 189 prob / 10, prob % 10,
185 mrs->retry_count, 190 mrs->retry_count,
186 mrs->last_success, 191 mrs->last_success,
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 135ed39790c0..6822ce0f95e5 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -86,11 +86,13 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
86 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 86 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
87 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 87 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
88 88
89 p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u " 89 p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
90 "%3u %3u %-3u %9llu %-9llu\n", 90 " %3u.%1u %3u %3u %-3u "
91 "%9llu %-9llu\n",
91 tp_max / 10, tp_max % 10, 92 tp_max / 10, tp_max % 10,
92 tp_avg / 10, tp_avg % 10, 93 tp_avg / 10, tp_avg % 10,
93 eprob / 10, eprob % 10, 94 eprob / 10, eprob % 10,
95 mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
94 prob / 10, prob % 10, 96 prob / 10, prob % 10,
95 mrs->retry_count, 97 mrs->retry_count,
96 mrs->last_success, 98 mrs->last_success,
@@ -128,10 +130,10 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
128 130
129 p += sprintf(p, "\n"); 131 p += sprintf(p, "\n");
130 p += sprintf(p, " best ____________rate__________ " 132 p += sprintf(p, " best ____________rate__________ "
131 "__statistics__ ________last_______ " 133 "______statistics______ ________last_______ "
132 "______sum-of________\n"); 134 "______sum-of________\n");
133 p += sprintf(p, "mode guard # rate [name idx airtime max_tp] " 135 p += sprintf(p, "mode guard # rate [name idx airtime max_tp] "
134 "[ ø(tp) ø(prob)] [prob.|retry|suc|att] [#success | " 136 "[ ø(tp) ø(prob) sd(prob)] [prob.|retry|suc|att] [#success | "
135 "#attempts]\n"); 137 "#attempts]\n");
136 138
137 p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p); 139 p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
@@ -229,10 +231,12 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p)
229 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 231 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
230 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 232 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
231 233
232 p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,", 234 p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"
235 "%u,%llu,%llu,",
233 tp_max / 10, tp_max % 10, 236 tp_max / 10, tp_max % 10,
234 tp_avg / 10, tp_avg % 10, 237 tp_avg / 10, tp_avg % 10,
235 eprob / 10, eprob % 10, 238 eprob / 10, eprob % 10,
239 mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
236 prob / 10, prob % 10, 240 prob / 10, prob % 10,
237 mrs->retry_count, 241 mrs->retry_count,
238 mrs->last_success, 242 mrs->last_success,