diff options
author | Thomas Huehn <thomas@net.t-labs.tu-berlin.de> | 2015-03-24 16:09:36 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2015-04-01 14:41:43 -0400 |
commit | 6d4885177929b1d978babe24d61ece687782c303 (patch) | |
tree | 6a38f04f3245c4bb570ea61f812e624f55c1a4bc /net | |
parent | 9c00bb7210e5bc0691c93b05a0edfab0e93b3ec9 (diff) |
mac80211: add new Minstrel statistic output via csv
This patch adds a new debugfs file "rc_stats_csv" to output Minstrels
statistics in a common csv format that is easy to parse.
Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
Signed-off-by: Stefan Venz <ikstream86@gmail.com>
Acked-by: Felix Fietkau <nbd@openwrt.org>
[remove printing current time of day]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/rc80211_minstrel.h | 6 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_debugfs.c | 90 |
2 files changed, 82 insertions, 14 deletions
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 410efe620c57..9613e7392c7d 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h | |||
@@ -13,7 +13,6 @@ | |||
13 | #define EWMA_DIV 128 | 13 | #define EWMA_DIV 128 |
14 | #define SAMPLE_COLUMNS 10 /* number of columns in sample table */ | 14 | #define SAMPLE_COLUMNS 10 /* number of columns in sample table */ |
15 | 15 | ||
16 | |||
17 | /* scaled fraction values */ | 16 | /* scaled fraction values */ |
18 | #define MINSTREL_SCALE 16 | 17 | #define MINSTREL_SCALE 16 |
19 | #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) | 18 | #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) |
@@ -24,7 +23,7 @@ | |||
24 | 23 | ||
25 | /* | 24 | /* |
26 | * Perform EWMA (Exponentially Weighted Moving Average) calculation | 25 | * Perform EWMA (Exponentially Weighted Moving Average) calculation |
27 | */ | 26 | */ |
28 | static inline int | 27 | static inline int |
29 | minstrel_ewma(int old, int new, int weight) | 28 | minstrel_ewma(int old, int new, int weight) |
30 | { | 29 | { |
@@ -95,6 +94,7 @@ struct minstrel_sta_info { | |||
95 | 94 | ||
96 | #ifdef CONFIG_MAC80211_DEBUGFS | 95 | #ifdef CONFIG_MAC80211_DEBUGFS |
97 | struct dentry *dbg_stats; | 96 | struct dentry *dbg_stats; |
97 | struct dentry *dbg_stats_csv; | ||
98 | #endif | 98 | #endif |
99 | }; | 99 | }; |
100 | 100 | ||
@@ -121,7 +121,6 @@ struct minstrel_priv { | |||
121 | u32 fixed_rate_idx; | 121 | u32 fixed_rate_idx; |
122 | struct dentry *dbg_fixed_rate; | 122 | struct dentry *dbg_fixed_rate; |
123 | #endif | 123 | #endif |
124 | |||
125 | }; | 124 | }; |
126 | 125 | ||
127 | struct minstrel_debugfs_info { | 126 | struct minstrel_debugfs_info { |
@@ -135,6 +134,7 @@ void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); | |||
135 | 134 | ||
136 | /* debugfs */ | 135 | /* debugfs */ |
137 | int minstrel_stats_open(struct inode *inode, struct file *file); | 136 | int minstrel_stats_open(struct inode *inode, struct file *file); |
137 | int minstrel_stats_csv_open(struct inode *inode, struct file *file); | ||
138 | ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos); | 138 | ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos); |
139 | int minstrel_stats_release(struct inode *inode, struct file *file); | 139 | int minstrel_stats_release(struct inode *inode, struct file *file); |
140 | 140 | ||
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index 2d70081a77eb..97d118dab5e2 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c | |||
@@ -54,6 +54,22 @@ | |||
54 | #include <net/mac80211.h> | 54 | #include <net/mac80211.h> |
55 | #include "rc80211_minstrel.h" | 55 | #include "rc80211_minstrel.h" |
56 | 56 | ||
57 | ssize_t | ||
58 | minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) | ||
59 | { | ||
60 | struct minstrel_debugfs_info *ms; | ||
61 | |||
62 | ms = file->private_data; | ||
63 | return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); | ||
64 | } | ||
65 | |||
66 | int | ||
67 | minstrel_stats_release(struct inode *inode, struct file *file) | ||
68 | { | ||
69 | kfree(file->private_data); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
57 | int | 73 | int |
58 | minstrel_stats_open(struct inode *inode, struct file *file) | 74 | minstrel_stats_open(struct inode *inode, struct file *file) |
59 | { | 75 | { |
@@ -115,25 +131,72 @@ minstrel_stats_open(struct inode *inode, struct file *file) | |||
115 | return 0; | 131 | return 0; |
116 | } | 132 | } |
117 | 133 | ||
118 | ssize_t | 134 | static const struct file_operations minstrel_stat_fops = { |
119 | minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) | 135 | .owner = THIS_MODULE, |
136 | .open = minstrel_stats_open, | ||
137 | .read = minstrel_stats_read, | ||
138 | .release = minstrel_stats_release, | ||
139 | .llseek = default_llseek, | ||
140 | }; | ||
141 | |||
142 | int | ||
143 | minstrel_stats_csv_open(struct inode *inode, struct file *file) | ||
120 | { | 144 | { |
145 | struct minstrel_sta_info *mi = inode->i_private; | ||
121 | struct minstrel_debugfs_info *ms; | 146 | struct minstrel_debugfs_info *ms; |
147 | unsigned int i, tp, prob, eprob; | ||
148 | char *p; | ||
122 | 149 | ||
123 | ms = file->private_data; | 150 | ms = kmalloc(2048, GFP_KERNEL); |
124 | return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); | 151 | if (!ms) |
125 | } | 152 | return -ENOMEM; |
153 | |||
154 | file->private_data = ms; | ||
155 | p = ms->buf; | ||
156 | |||
157 | for (i = 0; i < mi->n_rates; i++) { | ||
158 | struct minstrel_rate *mr = &mi->r[i]; | ||
159 | struct minstrel_rate_stats *mrs = &mi->r[i].stats; | ||
160 | |||
161 | p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : "")); | ||
162 | p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : "")); | ||
163 | p += sprintf(p, "%s" ,((i == mi->max_tp_rate[2]) ? "C" : "")); | ||
164 | p += sprintf(p, "%s" ,((i == mi->max_tp_rate[3]) ? "D" : "")); | ||
165 | p += sprintf(p, "%s" ,((i == mi->max_prob_rate) ? "P" : "")); | ||
166 | |||
167 | p += sprintf(p, ",%u%s", mr->bitrate / 2, | ||
168 | (mr->bitrate & 1 ? ".5," : ",")); | ||
169 | p += sprintf(p, "%u,", i); | ||
170 | p += sprintf(p, "%u,",mr->perfect_tx_time); | ||
171 | |||
172 | tp = MINSTREL_TRUNC(mrs->cur_tp / 10); | ||
173 | prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); | ||
174 | eprob = MINSTREL_TRUNC(mrs->probability * 1000); | ||
175 | |||
176 | p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u," | ||
177 | "%llu,%llu,%d,%d\n", | ||
178 | tp / 10, tp % 10, | ||
179 | eprob / 10, eprob % 10, | ||
180 | prob / 10, prob % 10, | ||
181 | mrs->retry_count, | ||
182 | mrs->last_success, | ||
183 | mrs->last_attempts, | ||
184 | (unsigned long long)mrs->succ_hist, | ||
185 | (unsigned long long)mrs->att_hist, | ||
186 | mi->total_packets - mi->sample_packets, | ||
187 | mi->sample_packets); | ||
188 | |||
189 | } | ||
190 | ms->len = p - ms->buf; | ||
191 | |||
192 | WARN_ON(ms->len + sizeof(*ms) > 2048); | ||
126 | 193 | ||
127 | int | ||
128 | minstrel_stats_release(struct inode *inode, struct file *file) | ||
129 | { | ||
130 | kfree(file->private_data); | ||
131 | return 0; | 194 | return 0; |
132 | } | 195 | } |
133 | 196 | ||
134 | static const struct file_operations minstrel_stat_fops = { | 197 | static const struct file_operations minstrel_stat_csv_fops = { |
135 | .owner = THIS_MODULE, | 198 | .owner = THIS_MODULE, |
136 | .open = minstrel_stats_open, | 199 | .open = minstrel_stats_csv_open, |
137 | .read = minstrel_stats_read, | 200 | .read = minstrel_stats_read, |
138 | .release = minstrel_stats_release, | 201 | .release = minstrel_stats_release, |
139 | .llseek = default_llseek, | 202 | .llseek = default_llseek, |
@@ -146,6 +209,9 @@ minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) | |||
146 | 209 | ||
147 | mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi, | 210 | mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi, |
148 | &minstrel_stat_fops); | 211 | &minstrel_stat_fops); |
212 | |||
213 | mi->dbg_stats_csv = debugfs_create_file("rc_stats_csv", S_IRUGO, dir, | ||
214 | mi, &minstrel_stat_csv_fops); | ||
149 | } | 215 | } |
150 | 216 | ||
151 | void | 217 | void |
@@ -154,4 +220,6 @@ minstrel_remove_sta_debugfs(void *priv, void *priv_sta) | |||
154 | struct minstrel_sta_info *mi = priv_sta; | 220 | struct minstrel_sta_info *mi = priv_sta; |
155 | 221 | ||
156 | debugfs_remove(mi->dbg_stats); | 222 | debugfs_remove(mi->dbg_stats); |
223 | |||
224 | debugfs_remove(mi->dbg_stats_csv); | ||
157 | } | 225 | } |