diff options
author | Thomas Huehn <thomas@net.t-labs.tu-berlin.de> | 2015-03-24 16:09:43 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2015-04-01 14:44:33 -0400 |
commit | 5f919abc76fc3de1e5965ea03c925f7563c7fc15 (patch) | |
tree | 8ed67f827d3b66cbfb140c66d8cd2d0f115633a6 | |
parent | ade6d4a2ec57d258bc181a155288c267dd8cf094 (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.c | 19 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.h | 22 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_debugfs.c | 19 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht_debugfs.c | 14 |
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 | */ |
158 | void | 158 | void |
159 | minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) | 159 | minstrel_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 | */ | ||
41 | static inline int | ||
42 | minstrel_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 | |||
38 | struct minstrel_rate_stats { | 56 | struct 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, |