All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics
@ 2015-02-13 14:57 Thomas Huehn
  2015-02-13 14:57 ` [PATCH v2 01/10] mac80211: enhance readability of Minstrels rc_stats output Thomas Huehn
                   ` (11 more replies)
  0 siblings, 12 replies; 17+ messages in thread
From: Thomas Huehn @ 2015-02-13 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, nbd, thomas

This patch series adds several improvements to the readability, the
output format of rc_stats and the calculated statistics of Minstrel
and Minstrel-HT. Variable names got more consistent and functions
got unified between both rate control algorithms.

Greetings Thomas

---
Changes in v2:
- fix define MACRO from CPTCFG_* into CONFIG_*
- change standard deviation symbol sigma into "sd"

[PATCH v2 01/10] mac80211: enhance readability of Minstrels rc_stats
[PATCH v2 02/10] mac80211: enhance readability of Minstrel-HTs
[PATCH v2 03/10] mac80211: add new Minstrel statistic output via csv
[PATCH v2 04/10] mac80211: add new Minstrel-HT statistic output via
[PATCH v2 05/10] mac80211: unify Minstrel & Minstrel-HTs calculation
[PATCH v2 06/10] mac80211: improve Minstrel variable & function
[PATCH v2 07/10] mac80211: restructure per-rate throughput
[PATCH v2 08/10] mac80211: add max. lossless throughput per rate to
[PATCH v2 09/10] mac80211: reduce calculation costs of EWMA
[PATCH v2 10/10] mac80211: add standard deviation to Minstrels

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 01/10] mac80211: enhance readability of Minstrels rc_stats output
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
@ 2015-02-13 14:57 ` Thomas Huehn
  2015-02-13 14:57 ` [PATCH v2 02/10] mac80211: enhance readability of Minstrel-HTs " Thomas Huehn
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Thomas Huehn @ 2015-02-13 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, nbd, thomas

This patch restructures the rc_stats debugfs table of Minstrel in
order to achieve better human readability. A new layout of the
statistics and a new header is added. In addition to the old layout
there are two new columns of information added:
idx	- representing the rate index of each rate in mac80211 which
	  can be used to set specific rates as fixed rate via debugfs
airtime - the tx-time in micro seconds that a 1200 Byte packet
	  takes to be transmitted over the air at the given rate

The old layout of rc_stats:

    rate      tpt  eprob *prob ret  *ok(*cum)        ok(      cum)
 DP 1          0.9  93.5 100.0   1    0(   0)         2(        2)
    2          0.4  40.0 100.0   0    0(   0)         4(        10)
    5.5        0.0   0.0   0.0   0    0(   0)         0(        0)
...

is changed into this new layout:

best   _______rate_____    __statistics__    ________last_______    ______sum-of________
rate  [name idx tx-time]  [ ø(tp) ø(prob)]  [prob.|retry|suc|att]  [#success | #attempts]
 DP   1     0     9738      0.9    93.5     100.0   1     1 1             2   2
      2     1     4922      0.4    40.0     100.0   1     0 0             4   10
      5.5   2     1858      0.0     0.0       0.0   2     0 0             0   0
...

Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
Signed-off-by: Stefan Venz <ikstream86@gmail.com>
---
 net/mac80211/rc80211_minstrel_debugfs.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index 2acab1b..2d70081 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -68,8 +68,12 @@ minstrel_stats_open(struct inode *inode, struct file *file)
 
 	file->private_data = ms;
 	p = ms->buf;
-	p += sprintf(p, "rate          tpt eprob *prob"
-			"  *ok(*cum)        ok(      cum)\n");
+	p += sprintf(p, "\n");
+	p += sprintf(p, "best   _______rate_____    __statistics__    "
+			"________last_______    ______sum-of________\n");
+	p += sprintf(p, "rate  [name idx airtime]  [ ø(tp) ø(prob)]  "
+			"[prob.|retry|suc|att]  [#success | #attempts]\n");
+
 	for (i = 0; i < mi->n_rates; i++) {
 		struct minstrel_rate *mr = &mi->r[i];
 		struct minstrel_rate_stats *mrs = &mi->r[i].stats;
@@ -79,18 +83,22 @@ minstrel_stats_open(struct inode *inode, struct file *file)
 		*(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' ';
 		*(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' ';
 		*(p++) = (i == mi->max_prob_rate) ? 'P' : ' ';
-		p += sprintf(p, "%3u%s", mr->bitrate / 2,
+
+		p += sprintf(p, " %3u%s ", mr->bitrate / 2,
 				(mr->bitrate & 1 ? ".5" : "  "));
+		p += sprintf(p, "%3u  ", i);
+		p += sprintf(p, "%6u  ", mr->perfect_tx_time);
 
 		tp = MINSTREL_TRUNC(mrs->cur_tp / 10);
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->probability * 1000);
 
-		p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u"
-				" %4u(%4u) %9llu(%9llu)\n",
+		p += sprintf(p, " %4u.%1u   %3u.%1u     %3u.%1u %3u"
+				"   %3u %-3u   %9llu   %-9llu\n",
 				tp / 10, tp % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
+				mrs->retry_count,
 				mrs->last_success,
 				mrs->last_attempts,
 				(unsigned long long)mrs->succ_hist,
-- 
2.2.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 02/10] mac80211: enhance readability of Minstrel-HTs rc_stats output
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
  2015-02-13 14:57 ` [PATCH v2 01/10] mac80211: enhance readability of Minstrels rc_stats output Thomas Huehn
@ 2015-02-13 14:57 ` Thomas Huehn
  2015-02-13 14:57 ` [PATCH v2 03/10] mac80211: add new Minstrel statistic output via csv Thomas Huehn
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Thomas Huehn @ 2015-02-13 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, nbd, thomas

This patch restructures the rc_stats debugfs table of Minstrel-HT in
order to achieve better human readability. A new layout of the
statistics and a new header is added. In addition to the old layout
there are two new columns of information added:
idx	- representing the rate index of each rate in mac80211 which
	  can be used to set specific rates as fixed rate via debugfs
airtime	- the tx-time in micro seconds that a 1200 Byte packet
	  takes to be transmitted over the air at the given rate

The old layout of rc_stats:

type           rate      tpt eprob *prob ret  *ok(*cum)        ok(      cum)
HT20/LGI       MCS0      5.6 100.0 100.0   1    0(   0)         1(        1)
HT20/LGI   B   MCS1     10.5 100.0 100.0   0    0(   0)         1(        1)
HT20/LGI  A    MCS2     14.8 100.0 100.0   0    0(   0)         1(        1)
...

is changed into this new layout:

            best   ________rate______    __statistics__    ________last_______    ______sum-of________
mode guard #  rate  [name   idx airtime]  [ ø(tp) ø(prob)]  [prob.|retry|suc|att]  [#success | #attempts]
HT20  LGI  1         MCS0     0    1480      0.0      0.0      0.0   1     0 0             0   0
HT20  LGI  1     B   MCS1     1     740     10.5    100.0    100.0   0     0 0             1   1
HT20  LGI  1    A    MCS2     2     496     14.8    100.0    100.0   0     0 0             1   1
...

Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
Signed-off-by: Stefan Venz <ikstream86@gmail.com>
---
 net/mac80211/rc80211_minstrel_ht_debugfs.c | 49 +++++++++++++++++++++---------
 1 file changed, 34 insertions(+), 15 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 20c676b..7fc690f 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -19,7 +19,7 @@ static char *
 minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
 {
 	const struct mcs_group *mg;
-	unsigned int j, tp, prob, eprob;
+	unsigned int j, tp, prob, eprob, tx_time;
 	char htmode = '2';
 	char gimode = 'L';
 	u32 gflags;
@@ -45,12 +45,19 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
 		if (!(mi->groups[i].supported & BIT(j)))
 			continue;
 
-		if (gflags & IEEE80211_TX_RC_MCS)
-			p += sprintf(p, " HT%c0/%cGI ", htmode, gimode);
-		else if (gflags & IEEE80211_TX_RC_VHT_MCS)
-			p += sprintf(p, "VHT%c0/%cGI ", htmode, gimode);
-		else
-			p += sprintf(p, " CCK/%cP   ", j < 4 ? 'L' : 'S');
+		if (gflags & IEEE80211_TX_RC_MCS) {
+			p += sprintf(p, "HT%c0  ", htmode);
+			p += sprintf(p, "%cGI  ", gimode);
+			p += sprintf(p, "%d  ", mg->streams);
+		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
+			p += sprintf(p, "VHT%c0 ", htmode);
+			p += sprintf(p, "%cGI ", gimode);
+			p += sprintf(p, "%d  ", mg->streams);
+		} else {
+			p += sprintf(p, "CCK    ");
+			p += sprintf(p, "%cP  ", j < 4 ? 'L' : 'S');
+			p += sprintf(p, "1 ");
+		}
 
 		*(p++) = (idx == mi->max_tp_rate[0]) ? 'A' : ' ';
 		*(p++) = (idx == mi->max_tp_rate[1]) ? 'B' : ' ';
@@ -59,21 +66,27 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
 		*(p++) = (idx == mi->max_prob_rate) ? 'P' : ' ';
 
 		if (gflags & IEEE80211_TX_RC_MCS) {
-			p += sprintf(p, " MCS%-2u ", (mg->streams - 1) * 8 + j);
+			p += sprintf(p, "  MCS%-2u", (mg->streams - 1) * 8 + j);
 		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
-			p += sprintf(p, " MCS%-1u/%1u", j, mg->streams);
+			p += sprintf(p, "  MCS%-1u/%1u", j, mg->streams);
 		} else {
 			int r = bitrates[j % 4];
 
-			p += sprintf(p, " %2u.%1uM ", r / 10, r % 10);
+			p += sprintf(p, "   %2u.%1uM", r / 10, r % 10);
 		}
 
+		p += sprintf(p, "  %3u  ", idx);
+
+		/* tx_time[rate(i)] in usec */
+		tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
+		p += sprintf(p, "%6u   ", tx_time);
+
 		tp = mr->cur_tp / 10;
 		prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mr->probability * 1000);
 
-		p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u "
-				"%3u %4u(%4u) %9llu(%9llu)\n",
+		p += sprintf(p, "%4u.%1u   %3u.%1u     %3u.%1u "
+				"%3u   %3u %-3u   %9llu   %-9llu\n",
 				tp / 10, tp % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
@@ -110,8 +123,14 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
 
 	file->private_data = ms;
 	p = ms->buf;
-	p += sprintf(p, " type           rate      tpt eprob *prob "
-			"ret  *ok(*cum)        ok(      cum)\n");
+
+	p += sprintf(p, "\n");
+	p += sprintf(p, "              best   ________rate______    "
+			"__statistics__    ________last_______    "
+			"______sum-of________\n");
+	p += sprintf(p, "mode guard #  rate  [name   idx airtime]  [ ø(tp) "
+			"ø(prob)]  [prob.|retry|suc|att]  [#success | "
+			"#attempts]\n");
 
 	p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
 	for (i = 0; i < MINSTREL_CCK_GROUP; i++)
@@ -123,7 +142,7 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
 			"lookaround %d\n",
 			max(0, (int) mi->total_packets - (int) mi->sample_packets),
 			mi->sample_packets);
-	p += sprintf(p, "Average A-MPDU length: %d.%d\n",
+	p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d\n",
 		MINSTREL_TRUNC(mi->avg_ampdu_len),
 		MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
 	ms->len = p - ms->buf;
-- 
2.2.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 03/10] mac80211: add new Minstrel statistic output via csv
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
  2015-02-13 14:57 ` [PATCH v2 01/10] mac80211: enhance readability of Minstrels rc_stats output Thomas Huehn
  2015-02-13 14:57 ` [PATCH v2 02/10] mac80211: enhance readability of Minstrel-HTs " Thomas Huehn
@ 2015-02-13 14:57 ` Thomas Huehn
  2015-03-17  8:16   ` Felix Fietkau
  2015-02-13 14:57 ` [PATCH v2 04/10] mac80211: add new Minstrel-HT " Thomas Huehn
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 17+ messages in thread
From: Thomas Huehn @ 2015-02-13 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, nbd, thomas

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>
---
 net/mac80211/rc80211_minstrel.h            |  6 +-
 net/mac80211/rc80211_minstrel_debugfs.c    | 95 ++++++++++++++++++++++++++----
 net/mac80211/rc80211_minstrel_ht_debugfs.c |  2 +-
 3 files changed, 88 insertions(+), 15 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 410efe6..9613e73 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -13,7 +13,6 @@
 #define EWMA_DIV	128
 #define SAMPLE_COLUMNS	10	/* number of columns in sample table */
 
-
 /* scaled fraction values */
 #define MINSTREL_SCALE  16
 #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
@@ -24,7 +23,7 @@
 
 /*
  * Perform EWMA (Exponentially Weighted Moving Average) calculation
-  */
+ */
 static inline int
 minstrel_ewma(int old, int new, int weight)
 {
@@ -95,6 +94,7 @@ struct minstrel_sta_info {
 
 #ifdef CONFIG_MAC80211_DEBUGFS
 	struct dentry *dbg_stats;
+	struct dentry *dbg_stats_csv;
 #endif
 };
 
@@ -121,7 +121,6 @@ struct minstrel_priv {
 	u32 fixed_rate_idx;
 	struct dentry *dbg_fixed_rate;
 #endif
-
 };
 
 struct minstrel_debugfs_info {
@@ -135,6 +134,7 @@ void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
 
 /* debugfs */
 int minstrel_stats_open(struct inode *inode, struct file *file);
+int minstrel_stats_csv_open(struct inode *inode, struct file *file);
 ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos);
 int minstrel_stats_release(struct inode *inode, struct file *file);
 
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index 2d70081..ab15ca6 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -54,6 +54,22 @@
 #include <net/mac80211.h>
 #include "rc80211_minstrel.h"
 
+ssize_t
+minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
+{
+	struct minstrel_debugfs_info *ms;
+
+	ms = file->private_data;
+	return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
+}
+
+int
+minstrel_stats_release(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	return 0;
+}
+
 int
 minstrel_stats_open(struct inode *inode, struct file *file)
 {
@@ -115,25 +131,76 @@ minstrel_stats_open(struct inode *inode, struct file *file)
 	return 0;
 }
 
-ssize_t
-minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
+static const struct file_operations minstrel_stat_fops = {
+	.owner = THIS_MODULE,
+	.open = minstrel_stats_open,
+	.read = minstrel_stats_read,
+	.release = minstrel_stats_release,
+	.llseek = default_llseek,
+};
+
+int
+minstrel_stats_csv_open(struct inode *inode, struct file *file)
 {
+	struct minstrel_sta_info *mi = inode->i_private;
 	struct minstrel_debugfs_info *ms;
+	struct timeval tv;
+	unsigned int i, tp, prob, eprob;
+	char *p;
 
-	ms = file->private_data;
-	return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
-}
+	ms = kmalloc(2048, GFP_KERNEL);
+	if (!ms)
+		return -ENOMEM;
+
+	file->private_data = ms;
+	p = ms->buf;
+
+	do_gettimeofday(&tv);
+
+	for (i = 0; i < mi->n_rates; i++) {
+		struct minstrel_rate *mr = &mi->r[i];
+		struct minstrel_rate_stats *mrs = &mi->r[i].stats;
+
+		p += sprintf(p, "%ld.%.6ld,", tv.tv_sec, tv.tv_usec);
+		p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A," : ","));
+		p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B," : ","));
+		p += sprintf(p, "%s" ,((i == mi->max_tp_rate[2]) ? "C," : ","));
+		p += sprintf(p, "%s" ,((i == mi->max_tp_rate[3]) ? "D," : ","));
+		p += sprintf(p, "%s" ,((i == mi->max_prob_rate) ? "P," : ","));
+
+		p += sprintf(p, "%u%s", mr->bitrate / 2,
+				(mr->bitrate & 1 ? ".5," : ","));
+		p += sprintf(p, "%u,", i);
+		p += sprintf(p, "%u,",mr->perfect_tx_time);
+
+		tp = MINSTREL_TRUNC(mrs->cur_tp / 10);
+		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
+		eprob = MINSTREL_TRUNC(mrs->probability * 1000);
+
+		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,"
+				"%llu,%llu,%d,%d\n",
+				tp / 10, tp % 10,
+				eprob / 10, eprob % 10,
+				prob / 10, prob % 10,
+				mrs->retry_count,
+				mrs->last_success,
+				mrs->last_attempts,
+				(unsigned long long)mrs->succ_hist,
+				(unsigned long long)mrs->att_hist,
+				mi->total_packets - mi->sample_packets,
+				mi->sample_packets);
+
+	}
+	ms->len = p - ms->buf;
+
+	WARN_ON(ms->len + sizeof(*ms) > 2048);
 
-int
-minstrel_stats_release(struct inode *inode, struct file *file)
-{
-	kfree(file->private_data);
 	return 0;
 }
 
-static const struct file_operations minstrel_stat_fops = {
+static const struct file_operations minstrel_stat_csv_fops = {
 	.owner = THIS_MODULE,
-	.open = minstrel_stats_open,
+	.open = minstrel_stats_csv_open,
 	.read = minstrel_stats_read,
 	.release = minstrel_stats_release,
 	.llseek = default_llseek,
@@ -146,6 +213,9 @@ minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
 
 	mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi,
 			&minstrel_stat_fops);
+
+	mi->dbg_stats_csv = debugfs_create_file("rc_stats_csv", S_IRUGO, dir,
+			mi, &minstrel_stat_csv_fops);
 }
 
 void
@@ -154,4 +224,7 @@ minstrel_remove_sta_debugfs(void *priv, void *priv_sta)
 	struct minstrel_sta_info *mi = priv_sta;
 
 	debugfs_remove(mi->dbg_stats);
+
+	debugfs_remove(mi->dbg_stats_csv);
 }
+
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 7fc690f..b300513 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -112,7 +112,7 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
 
 	if (!msp->is_ht) {
 		inode->i_private = &msp->legacy;
-		ret = minstrel_stats_open(inode, file);
+		ret = minstrel_stats_csv_open(inode, file);
 		inode->i_private = msp;
 		return ret;
 	}
-- 
2.2.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 04/10] mac80211: add new Minstrel-HT statistic output via csv
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
                   ` (2 preceding siblings ...)
  2015-02-13 14:57 ` [PATCH v2 03/10] mac80211: add new Minstrel statistic output via csv Thomas Huehn
@ 2015-02-13 14:57 ` Thomas Huehn
  2015-03-17  8:18   ` Felix Fietkau
  2015-02-13 14:57 ` [PATCH v2 05/10] mac80211: unify Minstrel & Minstrel-HTs calculation of rate statistics Thomas Huehn
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 17+ messages in thread
From: Thomas Huehn @ 2015-02-13 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, nbd, thomas

This patch adds a new debugfs file "rc_stats_csv" to output
Minstrel-HTs 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>
---
 net/mac80211/rc80211_minstrel_ht.h         |   1 +
 net/mac80211/rc80211_minstrel_ht_debugfs.c | 145 ++++++++++++++++++++++++++++-
 2 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index f2217d6..3cc30e8 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -112,6 +112,7 @@ struct minstrel_ht_sta_priv {
 	};
 #ifdef CONFIG_MAC80211_DEBUGFS
 	struct dentry *dbg_stats;
+	struct dentry *dbg_stats_csv;
 #endif
 	void *ratelist;
 	void *sample_table;
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index b300513..ae05780 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -107,8 +107,8 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
 	struct minstrel_ht_sta *mi = &msp->ht;
 	struct minstrel_debugfs_info *ms;
 	unsigned int i;
-	char *p;
 	int ret;
+	char *p;
 
 	if (!msp->is_ht) {
 		inode->i_private = &msp->legacy;
@@ -146,7 +146,6 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
 		MINSTREL_TRUNC(mi->avg_ampdu_len),
 		MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
 	ms->len = p - ms->buf;
-
 	WARN_ON(ms->len + sizeof(*ms) > 32768);
 
 	return nonseekable_open(inode, file);
@@ -160,6 +159,145 @@ static const struct file_operations minstrel_ht_stat_fops = {
 	.llseek = no_llseek,
 };
 
+static char *
+minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p,
+			    struct timeval tv)
+{
+	const struct mcs_group *mg;
+	unsigned int j, tp, prob, eprob, tx_time;
+	char htmode = '2';
+	char gimode = 'L';
+	u32 gflags;
+
+	if (!mi->groups[i].supported)
+		return p;
+
+	mg = &minstrel_mcs_groups[i];
+	gflags = mg->flags;
+
+	if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		htmode = '4';
+	else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+		htmode = '8';
+	if (gflags & IEEE80211_TX_RC_SHORT_GI)
+		gimode = 'S';
+
+	for (j = 0; j < MCS_GROUP_RATES; j++) {
+		struct minstrel_rate_stats *mr = &mi->groups[i].rates[j];
+		static const int bitrates[4] = { 10, 20, 55, 110 };
+		int idx = i * MCS_GROUP_RATES + j;
+
+		if (!(mi->groups[i].supported & BIT(j)))
+			continue;
+
+		p += sprintf(p, "%ld.%.6ld,", tv.tv_sec, tv.tv_usec);
+
+		if (gflags & IEEE80211_TX_RC_MCS) {
+			p += sprintf(p, "HT%c0,", htmode);
+			p += sprintf(p, "%cGI,", gimode);
+			p += sprintf(p, "%d,", mg->streams);
+		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
+			p += sprintf(p, "VHT%c0,", htmode);
+			p += sprintf(p, "%cGI,", gimode);
+			p += sprintf(p, "%d,", mg->streams);
+		} else {
+			p += sprintf(p, "CCK,");
+			p += sprintf(p, "%cP,", j < 4 ? 'L' : 'S');
+			p += sprintf(p, "1,");
+		}
+
+		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[0]) ? "A," : ","));
+		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[1]) ? "B," : ","));
+		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[2]) ? "C," : ","));
+		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[3]) ? "D," : ","));
+		p += sprintf(p, "%s" ,((idx == mi->max_prob_rate) ? "P," : ","));
+
+		if (gflags & IEEE80211_TX_RC_MCS) {
+			p += sprintf(p, "MCS%-2u,", (mg->streams - 1) * 8 + j);
+		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
+			p += sprintf(p, "MCS%-1u/%1u,", j, mg->streams);
+		} else {
+			int r = bitrates[j % 4];
+			p += sprintf(p, "%2u.%1uM,", r / 10, r % 10);
+		}
+
+		p += sprintf(p, "%u,", idx);
+		tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
+		p += sprintf(p, "%u,", tx_time);
+
+		tp = mr->cur_tp / 10;
+		prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
+		eprob = MINSTREL_TRUNC(mr->probability * 1000);
+
+		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,",
+				tp / 10, tp % 10,
+				eprob / 10, eprob % 10,
+				prob / 10, prob % 10,
+				mr->retry_count,
+				mr->last_success,
+				mr->last_attempts,
+				(unsigned long long)mr->succ_hist,
+				(unsigned long long)mr->att_hist);
+		p += sprintf(p, "%d,%d,%d.%d\n",
+				max(0, (int) mi->total_packets -
+				(int) mi->sample_packets),
+				mi->sample_packets,
+				MINSTREL_TRUNC(mi->avg_ampdu_len),
+				MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
+	}
+
+	return p;
+}
+
+static int
+minstrel_ht_stats_csv_open(struct inode *inode, struct file *file)
+{
+	struct minstrel_ht_sta_priv *msp = inode->i_private;
+	struct minstrel_ht_sta *mi = &msp->ht;
+	struct minstrel_debugfs_info *ms;
+	struct timeval tv;
+	unsigned int i;
+	int ret;
+	char *p;
+
+	do_gettimeofday(&tv);
+
+	if (!msp->is_ht) {
+		inode->i_private = &msp->legacy;
+		ret = minstrel_stats_open(inode, file);
+		inode->i_private = msp;
+		return ret;
+	}
+
+	ms = kmalloc(32768, GFP_KERNEL);
+
+	if (!ms)
+		return -ENOMEM;
+
+	file->private_data = ms;
+
+	p = ms->buf;
+
+	p = minstrel_ht_stats_csv_dump(mi, MINSTREL_CCK_GROUP, p, tv);
+	for (i = 0; i < MINSTREL_CCK_GROUP; i++)
+		p = minstrel_ht_stats_csv_dump(mi, i, p, tv);
+	for (i++; i < ARRAY_SIZE(mi->groups); i++)
+		p = minstrel_ht_stats_csv_dump(mi, i, p, tv);
+
+	ms->len = p - ms->buf;
+	WARN_ON(ms->len + sizeof(*ms) > 32768);
+
+	return nonseekable_open(inode, file);
+}
+
+static const struct file_operations minstrel_ht_stat_csv_fops = {
+	.owner = THIS_MODULE,
+	.open = minstrel_ht_stats_csv_open,
+	.read = minstrel_stats_read,
+	.release = minstrel_stats_release,
+	.llseek = no_llseek,
+};
+
 void
 minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
 {
@@ -167,6 +305,8 @@ minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
 
 	msp->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, msp,
 			&minstrel_ht_stat_fops);
+	msp->dbg_stats_csv = debugfs_create_file("rc_stats_csv", S_IRUGO,
+			     dir, msp, &minstrel_ht_stat_csv_fops);
 }
 
 void
@@ -175,4 +315,5 @@ minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta)
 	struct minstrel_ht_sta_priv *msp = priv_sta;
 
 	debugfs_remove(msp->dbg_stats);
+	debugfs_remove(msp->dbg_stats_csv);
 }
-- 
2.2.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 05/10] mac80211: unify Minstrel & Minstrel-HTs calculation of rate statistics
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
                   ` (3 preceding siblings ...)
  2015-02-13 14:57 ` [PATCH v2 04/10] mac80211: add new Minstrel-HT " Thomas Huehn
@ 2015-02-13 14:57 ` Thomas Huehn
  2015-02-13 14:57 ` [PATCH v2 06/10] mac80211: improve Minstrel variable & function naming Thomas Huehn
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Thomas Huehn @ 2015-02-13 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, nbd, thomas

This patch unifies the calculation of Minstrels and Minstrel-HTs
per-rate statistic. The new common function minstrel_calc_rate_stats()
is called when a statistic update is performed.

Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
---
 net/mac80211/rc80211_minstrel.c    | 44 ++++++++++++++++++++++++--------------
 net/mac80211/rc80211_minstrel.h    |  3 +++
 net/mac80211/rc80211_minstrel_ht.c | 28 +-----------------------
 3 files changed, 32 insertions(+), 43 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 7c86a00..4858e67 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -127,6 +127,32 @@ minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 	rate_control_set_rates(mp->hw, mi->sta, ratetbl);
 }
 
+/*
+* Recalculate success probabilities and counters for a given rate using EWMA
+*/
+void
+minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs)
+{
+	if (unlikely(mrs->attempts > 0)) {
+		mrs->sample_skipped = 0;
+		mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
+		if (unlikely(!mrs->att_hist))
+			mrs->probability = mrs->cur_prob;
+		else
+			mrs->probability = minstrel_ewma(mrs->probability,
+						     mrs->cur_prob, EWMA_LEVEL);
+		mrs->att_hist += mrs->attempts;
+		mrs->succ_hist += mrs->success;
+	} else {
+		mrs->sample_skipped++;
+	}
+
+	mrs->last_success = mrs->success;
+	mrs->last_attempts = mrs->attempts;
+	mrs->success = 0;
+	mrs->attempts = 0;
+}
+
 static void
 minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 {
@@ -146,22 +172,8 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 		if (!usecs)
 			usecs = 1000000;
 
-		if (unlikely(mrs->attempts > 0)) {
-			mrs->sample_skipped = 0;
-			mrs->cur_prob = MINSTREL_FRAC(mrs->success,
-						      mrs->attempts);
-			mrs->succ_hist += mrs->success;
-			mrs->att_hist += mrs->attempts;
-			mrs->probability = minstrel_ewma(mrs->probability,
-							 mrs->cur_prob,
-							 EWMA_LEVEL);
-		} else
-			mrs->sample_skipped++;
-
-		mrs->last_success = mrs->success;
-		mrs->last_attempts = mrs->attempts;
-		mrs->success = 0;
-		mrs->attempts = 0;
+		/* Update success probabilities per rate */
+		minstrel_calc_rate_stats(mrs);
 
 		/* Update throughput per rate, reset thr. below 10% success */
 		if (mrs->probability < MINSTREL_FRAC(10, 100))
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 9613e73..728144c 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -132,6 +132,9 @@ extern const struct rate_control_ops mac80211_minstrel;
 void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
 void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
 
+/* Recalculate success probabilities and counters for a given rate using EWMA */
+void minstrel_calc_rate_stats(struct minstrel_rate_stats *mr);
+
 /* debugfs */
 int minstrel_stats_open(struct inode *inode, struct file *file);
 int minstrel_stats_csv_open(struct inode *inode, struct file *file);
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 80452cf..381d089 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -311,32 +311,6 @@ minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
 	return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES];
 }
 
-
-/*
- * Recalculate success probabilities and counters for a rate using EWMA
- */
-static void
-minstrel_calc_rate_ewma(struct minstrel_rate_stats *mr)
-{
-	if (unlikely(mr->attempts > 0)) {
-		mr->sample_skipped = 0;
-		mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts);
-		if (!mr->att_hist)
-			mr->probability = mr->cur_prob;
-		else
-			mr->probability = minstrel_ewma(mr->probability,
-				mr->cur_prob, EWMA_LEVEL);
-		mr->att_hist += mr->attempts;
-		mr->succ_hist += mr->success;
-	} else {
-		mr->sample_skipped++;
-	}
-	mr->last_success = mr->success;
-	mr->last_attempts = mr->attempts;
-	mr->success = 0;
-	mr->attempts = 0;
-}
-
 /*
  * Calculate throughput based on the average A-MPDU length, taking into account
  * the expected number of retransmissions and their expected length
@@ -565,7 +539,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 
 			mr = &mg->rates[i];
 			mr->retry_updated = false;
-			minstrel_calc_rate_ewma(mr);
+			minstrel_calc_rate_stats(mr);
 			minstrel_ht_calc_tp(mi, group, i);
 
 			if (!mr->cur_tp)
-- 
2.2.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 06/10] mac80211: improve Minstrel variable & function naming
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
                   ` (4 preceding siblings ...)
  2015-02-13 14:57 ` [PATCH v2 05/10] mac80211: unify Minstrel & Minstrel-HTs calculation of rate statistics Thomas Huehn
@ 2015-02-13 14:57 ` Thomas Huehn
  2015-02-13 14:57 ` [PATCH v2 07/10] mac80211: restructure per-rate throughput calculation into function Thomas Huehn
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Thomas Huehn @ 2015-02-13 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, nbd, thomas

This patch ensures a consistent usage of variable names for type
"minstrel_rate_stats" to be used as "mrs" and from type minstrel_rate
as "mr" across both Minstrel & Minstrel-HT. In addition some
variable and function names got changed to more meaningful ones.

Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
---
 net/mac80211/rc80211_minstrel.c            |  26 +++----
 net/mac80211/rc80211_minstrel.h            |  13 ++--
 net/mac80211/rc80211_minstrel_debugfs.c    |   4 +-
 net/mac80211/rc80211_minstrel_ht.c         | 112 ++++++++++++++---------------
 net/mac80211/rc80211_minstrel_ht.h         |   2 +-
 net/mac80211/rc80211_minstrel_ht_debugfs.c |  36 +++++-----
 6 files changed, 98 insertions(+), 95 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 4858e67..89db6cf 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -137,9 +137,9 @@ minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs)
 		mrs->sample_skipped = 0;
 		mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
 		if (unlikely(!mrs->att_hist))
-			mrs->probability = mrs->cur_prob;
+			mrs->prob_ewma = mrs->cur_prob;
 		else
-			mrs->probability = minstrel_ewma(mrs->probability,
+			mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
 						     mrs->cur_prob, EWMA_LEVEL);
 		mrs->att_hist += mrs->attempts;
 		mrs->succ_hist += mrs->success;
@@ -176,15 +176,15 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 		minstrel_calc_rate_stats(mrs);
 
 		/* Update throughput per rate, reset thr. below 10% success */
-		if (mrs->probability < MINSTREL_FRAC(10, 100))
+		if (mrs->prob_ewma < MINSTREL_FRAC(10, 100))
 			mrs->cur_tp = 0;
 		else
-			mrs->cur_tp = mrs->probability * (1000000 / usecs);
+			mrs->cur_tp = mrs->prob_ewma * (1000000 / usecs);
 
 		/* Sample less often below the 10% chance of success.
 		 * Sample less often above the 95% chance of success. */
-		if (mrs->probability > MINSTREL_FRAC(95, 100) ||
-		    mrs->probability < MINSTREL_FRAC(10, 100)) {
+		if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) ||
+		    mrs->prob_ewma < MINSTREL_FRAC(10, 100)) {
 			mr->adjusted_retry_count = mrs->retry_count >> 1;
 			if (mr->adjusted_retry_count > 2)
 				mr->adjusted_retry_count = 2;
@@ -204,11 +204,11 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 		 * choose the maximum throughput rate as max_prob_rate
 		 * (2) if all success probabilities < 95%, the rate with
 		 * highest success probability is chosen as max_prob_rate */
-		if (mrs->probability >= MINSTREL_FRAC(95, 100)) {
+		if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) {
 			if (mrs->cur_tp >= mi->r[tmp_prob_rate].stats.cur_tp)
 				tmp_prob_rate = i;
 		} else {
-			if (mrs->probability >= mi->r[tmp_prob_rate].stats.probability)
+			if (mrs->prob_ewma >= mi->r[tmp_prob_rate].stats.prob_ewma)
 				tmp_prob_rate = i;
 		}
 	}
@@ -227,7 +227,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 #endif
 
 	/* Reset update timer */
-	mi->stats_update = jiffies;
+	mi->last_stats_update = jiffies;
 
 	minstrel_update_rates(mp, mi);
 }
@@ -265,7 +265,7 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
 	if (mi->sample_deferred > 0)
 		mi->sample_deferred--;
 
-	if (time_after(jiffies, mi->stats_update +
+	if (time_after(jiffies, mi->last_stats_update +
 				(mp->update_interval * HZ) / 1000))
 		minstrel_update_stats(mp, mi);
 }
@@ -397,7 +397,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
 	 * has a probability of >95%, we shouldn't be attempting
 	 * to use it, as this only wastes precious airtime */
 	if (!mrr_capable &&
-	   (mi->r[ndx].stats.probability > MINSTREL_FRAC(95, 100)))
+	   (mi->r[ndx].stats.prob_ewma > MINSTREL_FRAC(95, 100)))
 		return;
 
 	mi->prev_sample = true;
@@ -531,7 +531,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
 	}
 
 	mi->n_rates = n;
-	mi->stats_update = jiffies;
+	mi->last_stats_update = jiffies;
 
 	init_sample_table(mi);
 	minstrel_update_rates(mp, mi);
@@ -565,7 +565,7 @@ minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
 	if (!mi->sample_table)
 		goto error1;
 
-	mi->stats_update = jiffies;
+	mi->last_stats_update = jiffies;
 	return mi;
 
 error1:
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 728144c..58f2870 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -38,11 +38,14 @@ struct minstrel_rate_stats {
 	/* total attempts/success counters */
 	u64 att_hist, succ_hist;
 
-	/* current throughput */
+	/* current EWMA of rate throughput */
 	unsigned int cur_tp;
 
-	/* packet delivery probabilities */
-	unsigned int cur_prob, probability;
+	/* statistis of packet delivery probability
+	 *  cur_prob  - current prob within last update intervall
+	 *  prob_ewma - exponential weighted moving average of prob */
+	unsigned int cur_prob;
+	unsigned int prob_ewma;
 
 	/* maximum retry counts */
 	u8 retry_count;
@@ -70,7 +73,7 @@ struct minstrel_rate {
 struct minstrel_sta_info {
 	struct ieee80211_sta *sta;
 
-	unsigned long stats_update;
+	unsigned long last_stats_update;
 	unsigned int sp_ack_dur;
 	unsigned int rate_avg;
 
@@ -133,7 +136,7 @@ void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
 void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
 
 /* Recalculate success probabilities and counters for a given rate using EWMA */
-void minstrel_calc_rate_stats(struct minstrel_rate_stats *mr);
+void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);
 
 /* debugfs */
 int minstrel_stats_open(struct inode *inode, struct file *file);
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index ab15ca6..c0a04e1 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -107,7 +107,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
 
 		tp = MINSTREL_TRUNC(mrs->cur_tp / 10);
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
-		eprob = MINSTREL_TRUNC(mrs->probability * 1000);
+		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
 		p += sprintf(p, " %4u.%1u   %3u.%1u     %3u.%1u %3u"
 				"   %3u %-3u   %9llu   %-9llu\n",
@@ -175,7 +175,7 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file)
 
 		tp = MINSTREL_TRUNC(mrs->cur_tp / 10);
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
-		eprob = MINSTREL_TRUNC(mrs->probability * 1000);
+		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
 		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,"
 				"%llu,%llu,%d,%d\n",
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 381d089..6b07686 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -318,16 +318,16 @@ minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
 static void
 minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
 {
-	struct minstrel_rate_stats *mr;
+	struct minstrel_rate_stats *mrs;
 	unsigned int nsecs = 0;
-	unsigned int tp;
-	unsigned int prob;
+	unsigned int tmp_prob_ewma;
 
-	mr = &mi->groups[group].rates[rate];
-	prob = mr->probability;
+	mrs = &mi->groups[group].rates[rate];
+	tmp_prob_ewma = mrs->prob_ewma;
 
-	if (prob < MINSTREL_FRAC(1, 10)) {
-		mr->cur_tp = 0;
+	/* do not account throughput if sucess prob is below 10% */
+	if (mrs->prob_ewma < MINSTREL_FRAC(10, 100)) {
+		mrs->cur_tp = 0;
 		return;
 	}
 
@@ -335,8 +335,8 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
 	 * For the throughput calculation, limit the probability value to 90% to
 	 * account for collision related packet error rate fluctuation
 	 */
-	if (prob > MINSTREL_FRAC(9, 10))
-		prob = MINSTREL_FRAC(9, 10);
+	if (mrs->prob_ewma > MINSTREL_FRAC(90, 100))
+		tmp_prob_ewma = MINSTREL_FRAC(90, 100);
 
 	if (group != MINSTREL_CCK_GROUP)
 		nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
@@ -344,8 +344,7 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
 	nsecs += minstrel_mcs_groups[group].duration[rate];
 
 	/* prob is scaled - see MINSTREL_FRAC above */
-	tp = 1000000 * ((prob * 1000) / nsecs);
-	mr->cur_tp = MINSTREL_TRUNC(tp);
+	mrs->cur_tp = MINSTREL_TRUNC(1000000 * ((tmp_prob_ewma * 1000) / nsecs));
 }
 
 /*
@@ -366,13 +365,13 @@ minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u16 index,
 	cur_group = index / MCS_GROUP_RATES;
 	cur_idx = index  % MCS_GROUP_RATES;
 	cur_thr = mi->groups[cur_group].rates[cur_idx].cur_tp;
-	cur_prob = mi->groups[cur_group].rates[cur_idx].probability;
+	cur_prob = mi->groups[cur_group].rates[cur_idx].prob_ewma;
 
 	do {
 		tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
 		tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
 		tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
-		tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability;
+		tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
 		if (cur_thr < tmp_thr ||
 		    (cur_thr == tmp_thr && cur_prob <= tmp_prob))
 			break;
@@ -394,16 +393,16 @@ static void
 minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
 {
 	struct minstrel_mcs_group_data *mg;
-	struct minstrel_rate_stats *mr;
+	struct minstrel_rate_stats *mrs;
 	int tmp_group, tmp_idx, tmp_tp, tmp_prob, max_tp_group;
 
 	mg = &mi->groups[index / MCS_GROUP_RATES];
-	mr = &mg->rates[index % MCS_GROUP_RATES];
+	mrs = &mg->rates[index % MCS_GROUP_RATES];
 
 	tmp_group = mi->max_prob_rate / MCS_GROUP_RATES;
 	tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES;
 	tmp_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
-	tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability;
+	tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
 
 	/* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from
 	 * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */
@@ -412,15 +411,15 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
 	    (max_tp_group != MINSTREL_CCK_GROUP))
 		return;
 
-	if (mr->probability > MINSTREL_FRAC(75, 100)) {
-		if (mr->cur_tp > tmp_tp)
+	if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) {
+		if (mrs->cur_tp > tmp_tp)
 			mi->max_prob_rate = index;
-		if (mr->cur_tp > mg->rates[mg->max_group_prob_rate].cur_tp)
+		if (mrs->cur_tp > mg->rates[mg->max_group_prob_rate].cur_tp)
 			mg->max_group_prob_rate = index;
 	} else {
-		if (mr->probability > tmp_prob)
+		if (mrs->prob_ewma > tmp_prob)
 			mi->max_prob_rate = index;
-		if (mr->probability > mg->rates[mg->max_group_prob_rate].probability)
+		if (mrs->prob_ewma > mg->rates[mg->max_group_prob_rate].prob_ewma)
 			mg->max_group_prob_rate = index;
 	}
 }
@@ -465,7 +464,7 @@ static inline void
 minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
 {
 	struct minstrel_mcs_group_data *mg;
-	struct minstrel_rate_stats *mr;
+	struct minstrel_rate_stats *mrs;
 	int tmp_max_streams, group;
 	int tmp_tp = 0;
 
@@ -475,11 +474,11 @@ minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
 		mg = &mi->groups[group];
 		if (!mg->supported || group == MINSTREL_CCK_GROUP)
 			continue;
-		mr = minstrel_get_ratestats(mi, mg->max_group_prob_rate);
-		if (tmp_tp < mr->cur_tp &&
+		mrs = minstrel_get_ratestats(mi, mg->max_group_prob_rate);
+		if (tmp_tp < mrs->cur_tp &&
 		   (minstrel_mcs_groups[group].streams < tmp_max_streams)) {
 				mi->max_prob_rate = mg->max_group_prob_rate;
-				tmp_tp = mr->cur_tp;
+				tmp_tp = mrs->cur_tp;
 		}
 	}
 }
@@ -497,7 +496,7 @@ static void
 minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 {
 	struct minstrel_mcs_group_data *mg;
-	struct minstrel_rate_stats *mr;
+	struct minstrel_rate_stats *mrs;
 	int group, i, j;
 	u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES];
 	u16 tmp_cck_tp_rate[MAX_THR_RATES], index;
@@ -537,12 +536,12 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 
 			index = MCS_GROUP_RATES * group + i;
 
-			mr = &mg->rates[i];
-			mr->retry_updated = false;
-			minstrel_calc_rate_stats(mr);
+			mrs = &mg->rates[i];
+			mrs->retry_updated = false;
+			minstrel_calc_rate_stats(mrs);
 			minstrel_ht_calc_tp(mi, group, i);
 
-			if (!mr->cur_tp)
+			if (!mrs->cur_tp)
 				continue;
 
 			/* Find max throughput rate set */
@@ -586,7 +585,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 #endif
 
 	/* Reset update timer */
-	mi->stats_update = jiffies;
+	mi->last_stats_update = jiffies;
 }
 
 static bool
@@ -609,7 +608,7 @@ minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct ieee80211_tx_rate *rat
 }
 
 static void
-minstrel_next_sample_idx(struct minstrel_ht_sta *mi)
+minstrel_set_next_sample_idx(struct minstrel_ht_sta *mi)
 {
 	struct minstrel_mcs_group_data *mg;
 
@@ -750,7 +749,8 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
 		update = true;
 	}
 
-	if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
+	if (time_after(jiffies, mi->last_stats_update +
+				(mp->update_interval / 2 * HZ) / 1000)) {
 		update = true;
 		minstrel_ht_update_stats(mp, mi);
 	}
@@ -763,7 +763,7 @@ static void
 minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
                          int index)
 {
-	struct minstrel_rate_stats *mr;
+	struct minstrel_rate_stats *mrs;
 	const struct mcs_group *group;
 	unsigned int tx_time, tx_time_rtscts, tx_time_data;
 	unsigned int cw = mp->cw_min;
@@ -772,16 +772,16 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
 	unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len);
 	unsigned int overhead = 0, overhead_rtscts = 0;
 
-	mr = minstrel_get_ratestats(mi, index);
-	if (mr->probability < MINSTREL_FRAC(1, 10)) {
-		mr->retry_count = 1;
-		mr->retry_count_rtscts = 1;
+	mrs = minstrel_get_ratestats(mi, index);
+	if (mrs->prob_ewma < MINSTREL_FRAC(1, 10)) {
+		mrs->retry_count = 1;
+		mrs->retry_count_rtscts = 1;
 		return;
 	}
 
-	mr->retry_count = 2;
-	mr->retry_count_rtscts = 2;
-	mr->retry_updated = true;
+	mrs->retry_count = 2;
+	mrs->retry_count_rtscts = 2;
+	mrs->retry_updated = true;
 
 	group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
 	tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000;
@@ -812,9 +812,9 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
 		tx_time_rtscts += ctime + overhead_rtscts + tx_time_data;
 
 		if (tx_time_rtscts < mp->segment_size)
-			mr->retry_count_rtscts++;
+			mrs->retry_count_rtscts++;
 	} while ((tx_time < mp->segment_size) &&
-	         (++mr->retry_count < mp->max_retry));
+	         (++mrs->retry_count < mp->max_retry));
 }
 
 
@@ -823,22 +823,22 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
                      struct ieee80211_sta_rates *ratetbl, int offset, int index)
 {
 	const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
-	struct minstrel_rate_stats *mr;
+	struct minstrel_rate_stats *mrs;
 	u8 idx;
 	u16 flags = group->flags;
 
-	mr = minstrel_get_ratestats(mi, index);
-	if (!mr->retry_updated)
+	mrs = minstrel_get_ratestats(mi, index);
+	if (!mrs->retry_updated)
 		minstrel_calc_retransmit(mp, mi, index);
 
-	if (mr->probability < MINSTREL_FRAC(20, 100) || !mr->retry_count) {
+	if (mrs->prob_ewma < MINSTREL_FRAC(20, 100) || !mrs->retry_count) {
 		ratetbl->rate[offset].count = 2;
 		ratetbl->rate[offset].count_rts = 2;
 		ratetbl->rate[offset].count_cts = 2;
 	} else {
-		ratetbl->rate[offset].count = mr->retry_count;
-		ratetbl->rate[offset].count_cts = mr->retry_count;
-		ratetbl->rate[offset].count_rts = mr->retry_count_rtscts;
+		ratetbl->rate[offset].count = mrs->retry_count;
+		ratetbl->rate[offset].count_cts = mrs->retry_count;
+		ratetbl->rate[offset].count_rts = mrs->retry_count_rtscts;
 	}
 
 	if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP)
@@ -896,7 +896,7 @@ minstrel_get_duration(int index)
 static int
 minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 {
-	struct minstrel_rate_stats *mr;
+	struct minstrel_rate_stats *mrs;
 	struct minstrel_mcs_group_data *mg;
 	unsigned int sample_dur, sample_group, cur_max_tp_streams;
 	int sample_idx = 0;
@@ -912,12 +912,12 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 	sample_group = mi->sample_group;
 	mg = &mi->groups[sample_group];
 	sample_idx = sample_table[mg->column][mg->index];
-	minstrel_next_sample_idx(mi);
+	minstrel_set_next_sample_idx(mi);
 
 	if (!(mg->supported & BIT(sample_idx)))
 		return -1;
 
-	mr = &mg->rates[sample_idx];
+	mrs = &mg->rates[sample_idx];
 	sample_idx += sample_group * MCS_GROUP_RATES;
 
 	/*
@@ -934,7 +934,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 	 * Do not sample if the probability is already higher than 95%
 	 * to avoid wasting airtime.
 	 */
-	if (mr->probability > MINSTREL_FRAC(95, 100))
+	if (mrs->prob_ewma > MINSTREL_FRAC(95, 100))
 		return -1;
 
 	/*
@@ -949,7 +949,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 	    (cur_max_tp_streams - 1 <
 	     minstrel_mcs_groups[sample_group].streams ||
 	     sample_dur >= minstrel_get_duration(mi->max_prob_rate))) {
-		if (mr->sample_skipped < 20)
+		if (mrs->sample_skipped < 20)
 			return -1;
 
 		if (mi->sample_slow++ > 2)
@@ -1103,7 +1103,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
 	memset(mi, 0, sizeof(*mi));
 
 	mi->sta = sta;
-	mi->stats_update = jiffies;
+	mi->last_stats_update = jiffies;
 
 	ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1, 0);
 	mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1, 0);
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index 3cc30e8..fa21a82 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -78,7 +78,7 @@ struct minstrel_ht_sta {
 	u16 max_prob_rate;
 
 	/* time of last status update */
-	unsigned long stats_update;
+	unsigned long last_stats_update;
 
 	/* overhead time in usec for each frame */
 	unsigned int overhead;
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index ae05780..5529add 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -38,7 +38,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
 		gimode = 'S';
 
 	for (j = 0; j < MCS_GROUP_RATES; j++) {
-		struct minstrel_rate_stats *mr = &mi->groups[i].rates[j];
+		struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
 		static const int bitrates[4] = { 10, 20, 55, 110 };
 		int idx = i * MCS_GROUP_RATES + j;
 
@@ -81,20 +81,20 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
 		tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
 		p += sprintf(p, "%6u   ", tx_time);
 
-		tp = mr->cur_tp / 10;
-		prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
-		eprob = MINSTREL_TRUNC(mr->probability * 1000);
+		tp = mrs->cur_tp / 10;
+		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
+		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
 		p += sprintf(p, "%4u.%1u   %3u.%1u     %3u.%1u "
 				"%3u   %3u %-3u   %9llu   %-9llu\n",
 				tp / 10, tp % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
-				mr->retry_count,
-				mr->last_success,
-				mr->last_attempts,
-				(unsigned long long)mr->succ_hist,
-				(unsigned long long)mr->att_hist);
+				mrs->retry_count,
+				mrs->last_success,
+				mrs->last_attempts,
+				(unsigned long long)mrs->succ_hist,
+				(unsigned long long)mrs->att_hist);
 	}
 
 	return p;
@@ -183,7 +183,7 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p,
 		gimode = 'S';
 
 	for (j = 0; j < MCS_GROUP_RATES; j++) {
-		struct minstrel_rate_stats *mr = &mi->groups[i].rates[j];
+		struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
 		static const int bitrates[4] = { 10, 20, 55, 110 };
 		int idx = i * MCS_GROUP_RATES + j;
 
@@ -225,19 +225,19 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p,
 		tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
 		p += sprintf(p, "%u,", tx_time);
 
-		tp = mr->cur_tp / 10;
-		prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
-		eprob = MINSTREL_TRUNC(mr->probability * 1000);
+		tp = mrs->cur_tp / 10;
+		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
+		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
 		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,",
 				tp / 10, tp % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
-				mr->retry_count,
-				mr->last_success,
-				mr->last_attempts,
-				(unsigned long long)mr->succ_hist,
-				(unsigned long long)mr->att_hist);
+				mrs->retry_count,
+				mrs->last_success,
+				mrs->last_attempts,
+				(unsigned long long)mrs->succ_hist,
+				(unsigned long long)mrs->att_hist);
 		p += sprintf(p, "%d,%d,%d.%d\n",
 				max(0, (int) mi->total_packets -
 				(int) mi->sample_packets),
-- 
2.2.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 07/10] mac80211: restructure per-rate throughput calculation into function
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
                   ` (5 preceding siblings ...)
  2015-02-13 14:57 ` [PATCH v2 06/10] mac80211: improve Minstrel variable & function naming Thomas Huehn
@ 2015-02-13 14:57 ` Thomas Huehn
  2015-03-17  8:24   ` Felix Fietkau
  2015-02-13 14:57 ` [PATCH v2 08/10] mac80211: add max. lossless throughput per rate to rc_stats Thomas Huehn
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 17+ messages in thread
From: Thomas Huehn @ 2015-02-13 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, nbd, thomas

This patch moves Minstrels and Minstrel-HTs per-rate throughput
calculation (EWMA(thr)) into a dedicated function to be called.
Therefore the variable "unsigned int cur_tp" within struct
"minstrel_rate_stats" becomes obsolete.  and is removed to free
up its space.

Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
---
 net/mac80211/rc80211_minstrel.c            | 46 +++++++++++------
 net/mac80211/rc80211_minstrel.h            |  4 +-
 net/mac80211/rc80211_minstrel_debugfs.c    | 12 ++---
 net/mac80211/rc80211_minstrel_ht.c         | 79 ++++++++++++++++++------------
 net/mac80211/rc80211_minstrel_ht.h         |  1 +
 net/mac80211/rc80211_minstrel_ht_debugfs.c | 12 ++---
 6 files changed, 94 insertions(+), 60 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 89db6cf..28de2f7a 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -69,13 +69,34 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
 	return i;
 }
 
+/* return current EMWA throughput */
+int minstrel_get_tp_avg(struct minstrel_rate *mr)
+{
+	int tp_avg, usecs;
+
+	usecs = mr->perfect_tx_time;
+	if (!usecs)
+		usecs = 1000000;
+
+	/* reset thr. below 10% success */
+	if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100))
+		tp_avg = 0;
+	else
+		tp_avg = MINSTREL_TRUNC(mr->stats.prob_ewma * (100000 / usecs));
+
+	return tp_avg;
+}
+
+
+
 /* find & sort topmost throughput rates */
 static inline void
 minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
 {
 	int j = MAX_THR_RATES;
 
-	while (j > 0 && mi->r[i].stats.cur_tp > mi->r[tp_list[j - 1]].stats.cur_tp)
+	while (j > 0 && (minstrel_get_tp_avg(&mi->r[i]) >
+				minstrel_get_tp_avg(&mi->r[tp_list[j - 1]])))
 		j--;
 	if (j < MAX_THR_RATES - 1)
 		memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1));
@@ -158,8 +179,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 {
 	u8 tmp_tp_rate[MAX_THR_RATES];
 	u8 tmp_prob_rate = 0;
-	u32 usecs;
-	int i;
+	int i, tmp_cur_tp, tmp_prob_tp;
 
 	for (i = 0; i < MAX_THR_RATES; i++)
 	    tmp_tp_rate[i] = 0;
@@ -168,19 +188,9 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 		struct minstrel_rate *mr = &mi->r[i];
 		struct minstrel_rate_stats *mrs = &mi->r[i].stats;
 
-		usecs = mr->perfect_tx_time;
-		if (!usecs)
-			usecs = 1000000;
-
 		/* Update success probabilities per rate */
 		minstrel_calc_rate_stats(mrs);
 
-		/* Update throughput per rate, reset thr. below 10% success */
-		if (mrs->prob_ewma < MINSTREL_FRAC(10, 100))
-			mrs->cur_tp = 0;
-		else
-			mrs->cur_tp = mrs->prob_ewma * (1000000 / usecs);
-
 		/* Sample less often below the 10% chance of success.
 		 * Sample less often above the 95% chance of success. */
 		if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) ||
@@ -205,7 +215,9 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 		 * (2) if all success probabilities < 95%, the rate with
 		 * highest success probability is chosen as max_prob_rate */
 		if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) {
-			if (mrs->cur_tp >= mi->r[tmp_prob_rate].stats.cur_tp)
+			tmp_cur_tp = minstrel_get_tp_avg(mr);
+			tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate]);
+			if (tmp_cur_tp >= tmp_prob_tp)
 				tmp_prob_rate = i;
 		} else {
 			if (mrs->prob_ewma >= mi->r[tmp_prob_rate].stats.prob_ewma)
@@ -676,11 +688,15 @@ static u32 minstrel_get_expected_throughput(void *priv_sta)
 {
 	struct minstrel_sta_info *mi = priv_sta;
 	int idx = mi->max_tp_rate[0];
+	int tmp_cur_tp;
 
 	/* convert pkt per sec in kbps (1200 is the average pkt size used for
 	 * computing cur_tp
 	 */
-	return MINSTREL_TRUNC(mi->r[idx].stats.cur_tp) * 1200 * 8 / 1024;
+	tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx]);
+	tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024;
+
+	return tmp_cur_tp;
 }
 
 const struct rate_control_ops mac80211_minstrel = {
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 58f2870..490df3b 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -38,9 +38,6 @@ struct minstrel_rate_stats {
 	/* total attempts/success counters */
 	u64 att_hist, succ_hist;
 
-	/* current EWMA of rate throughput */
-	unsigned int cur_tp;
-
 	/* statistis of packet delivery probability
 	 *  cur_prob  - current prob within last update intervall
 	 *  prob_ewma - exponential weighted moving average of prob */
@@ -137,6 +134,7 @@ void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
 
 /* Recalculate success probabilities and counters for a given rate using EWMA */
 void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);
+int minstrel_get_tp_avg(struct minstrel_rate *mr);
 
 /* debugfs */
 int minstrel_stats_open(struct inode *inode, struct file *file);
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index c0a04e1..d8ccef7 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -75,7 +75,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
 {
 	struct minstrel_sta_info *mi = inode->i_private;
 	struct minstrel_debugfs_info *ms;
-	unsigned int i, tp, prob, eprob;
+	unsigned int i, tp_avg, prob, eprob;
 	char *p;
 
 	ms = kmalloc(2048, GFP_KERNEL);
@@ -105,13 +105,13 @@ minstrel_stats_open(struct inode *inode, struct file *file)
 		p += sprintf(p, "%3u  ", i);
 		p += sprintf(p, "%6u  ", mr->perfect_tx_time);
 
-		tp = MINSTREL_TRUNC(mrs->cur_tp / 10);
+		tp_avg = minstrel_get_tp_avg(mr);
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
 		p += sprintf(p, " %4u.%1u   %3u.%1u     %3u.%1u %3u"
 				"   %3u %-3u   %9llu   %-9llu\n",
-				tp / 10, tp % 10,
+				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
 				mrs->retry_count,
@@ -145,7 +145,7 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file)
 	struct minstrel_sta_info *mi = inode->i_private;
 	struct minstrel_debugfs_info *ms;
 	struct timeval tv;
-	unsigned int i, tp, prob, eprob;
+	unsigned int i, tp_avg, prob, eprob;
 	char *p;
 
 	ms = kmalloc(2048, GFP_KERNEL);
@@ -173,13 +173,13 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file)
 		p += sprintf(p, "%u,", i);
 		p += sprintf(p, "%u,",mr->perfect_tx_time);
 
-		tp = MINSTREL_TRUNC(mrs->cur_tp / 10);
+		tp_avg = minstrel_get_tp_avg(mr);
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
 		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,"
 				"%llu,%llu,%d,%d\n",
-				tp / 10, tp % 10,
+				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
 				mrs->retry_count,
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 6b07686..2a55f63 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -312,23 +312,23 @@ minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
 }
 
 /*
- * Calculate throughput based on the average A-MPDU length, taking into account
- * the expected number of retransmissions and their expected length
+ * Return current throughput based on the average A-MPDU length, taking into
+ * account the expected number of retransmissions and their expected length
  */
-static void
-minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
+int
+minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate)
 {
 	struct minstrel_rate_stats *mrs;
 	unsigned int nsecs = 0;
-	unsigned int tmp_prob_ewma;
+	unsigned int tmp_prob_ewma, tp_avg;
 
 	mrs = &mi->groups[group].rates[rate];
 	tmp_prob_ewma = mrs->prob_ewma;
 
 	/* do not account throughput if sucess prob is below 10% */
 	if (mrs->prob_ewma < MINSTREL_FRAC(10, 100)) {
-		mrs->cur_tp = 0;
-		return;
+		tp_avg = 0;
+		return tp_avg;
 	}
 
 	/*
@@ -344,7 +344,9 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
 	nsecs += minstrel_mcs_groups[group].duration[rate];
 
 	/* prob is scaled - see MINSTREL_FRAC above */
-	mrs->cur_tp = MINSTREL_TRUNC(1000000 * ((tmp_prob_ewma * 1000) / nsecs));
+	tp_avg = MINSTREL_TRUNC(100000 * ((tmp_prob_ewma * 1000) / nsecs));
+
+	return tp_avg;
 }
 
 /*
@@ -358,22 +360,22 @@ static void
 minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u16 index,
 			       u16 *tp_list)
 {
-	int cur_group, cur_idx, cur_thr, cur_prob;
-	int tmp_group, tmp_idx, tmp_thr, tmp_prob;
+	int cur_group, cur_idx, cur_tp_avg, cur_prob;
+	int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob;
 	int j = MAX_THR_RATES;
 
 	cur_group = index / MCS_GROUP_RATES;
 	cur_idx = index  % MCS_GROUP_RATES;
-	cur_thr = mi->groups[cur_group].rates[cur_idx].cur_tp;
+	cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx);
 	cur_prob = mi->groups[cur_group].rates[cur_idx].prob_ewma;
 
 	do {
 		tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
 		tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
-		tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
+		tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx);
 		tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
-		if (cur_thr < tmp_thr ||
-		    (cur_thr == tmp_thr && cur_prob <= tmp_prob))
+		if (cur_tp_avg < tmp_tp_avg ||
+		    (cur_tp_avg == tmp_tp_avg && cur_prob <= tmp_prob))
 			break;
 		j--;
 	} while (j > 0);
@@ -394,14 +396,19 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
 {
 	struct minstrel_mcs_group_data *mg;
 	struct minstrel_rate_stats *mrs;
-	int tmp_group, tmp_idx, tmp_tp, tmp_prob, max_tp_group;
+	int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob;
+	int max_tp_group, cur_tp_avg, cur_group, cur_idx;
+	int max_group_prob_rate_group, max_group_prob_rate_idx;
+	int max_group_prob_rate_tp_avg;
 
+	cur_group = index / MCS_GROUP_RATES;
+	cur_idx = index % MCS_GROUP_RATES;
 	mg = &mi->groups[index / MCS_GROUP_RATES];
 	mrs = &mg->rates[index % MCS_GROUP_RATES];
 
 	tmp_group = mi->max_prob_rate / MCS_GROUP_RATES;
 	tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES;
-	tmp_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
+	tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx);
 	tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
 
 	/* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from
@@ -412,9 +419,18 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
 		return;
 
 	if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) {
-		if (mrs->cur_tp > tmp_tp)
+		cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx);
+		if (cur_tp_avg > tmp_tp_avg)
 			mi->max_prob_rate = index;
-		if (mrs->cur_tp > mg->rates[mg->max_group_prob_rate].cur_tp)
+
+		max_group_prob_rate_group = mg->max_group_prob_rate /
+								MCS_GROUP_RATES;
+		max_group_prob_rate_idx = mg->max_group_prob_rate %
+								MCS_GROUP_RATES;
+		max_group_prob_rate_tp_avg = minstrel_ht_get_tp_avg(mi,
+						max_group_prob_rate_group,
+						max_group_prob_rate_idx);
+		if (cur_tp_avg > max_group_prob_rate_tp_avg)
 			mg->max_group_prob_rate = index;
 	} else {
 		if (mrs->prob_ewma > tmp_prob)
@@ -441,11 +457,11 @@ minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi,
 
 	tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES;
 	tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES;
-	tmp_cck_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
+	tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx);
 
 	tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES;
 	tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES;
-	tmp_mcs_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
+	tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx);
 
 	if (tmp_cck_tp > tmp_mcs_tp) {
 		for(i = 0; i < MAX_THR_RATES; i++) {
@@ -464,8 +480,7 @@ static inline void
 minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
 {
 	struct minstrel_mcs_group_data *mg;
-	struct minstrel_rate_stats *mrs;
-	int tmp_max_streams, group;
+	int tmp_max_streams, group, tmp_idx;
 	int tmp_tp = 0;
 
 	tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] /
@@ -474,11 +489,14 @@ minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
 		mg = &mi->groups[group];
 		if (!mg->supported || group == MINSTREL_CCK_GROUP)
 			continue;
-		mrs = minstrel_get_ratestats(mi, mg->max_group_prob_rate);
-		if (tmp_tp < mrs->cur_tp &&
+
+		tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
+
+		if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx) &&
 		   (minstrel_mcs_groups[group].streams < tmp_max_streams)) {
 				mi->max_prob_rate = mg->max_group_prob_rate;
-				tmp_tp = mrs->cur_tp;
+				tmp_tp = minstrel_ht_get_tp_avg(mi, group,
+								tmp_idx);
 		}
 	}
 }
@@ -539,9 +557,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 			mrs = &mg->rates[i];
 			mrs->retry_updated = false;
 			minstrel_calc_rate_stats(mrs);
-			minstrel_ht_calc_tp(mi, group, i);
 
-			if (!mrs->cur_tp)
+			if (minstrel_ht_get_tp_avg(mi, group, i) == 0)
 				continue;
 
 			/* Find max throughput rate set */
@@ -1300,7 +1317,7 @@ static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
 {
 	struct minstrel_ht_sta_priv *msp = priv_sta;
 	struct minstrel_ht_sta *mi = &msp->ht;
-	int i, j;
+	int i, j, tp_avg;
 
 	if (!msp->is_ht)
 		return mac80211_minstrel.get_expected_throughput(priv_sta);
@@ -1308,8 +1325,10 @@ static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
 	i = mi->max_tp_rate[0] / MCS_GROUP_RATES;
 	j = mi->max_tp_rate[0] % MCS_GROUP_RATES;
 
-	/* convert cur_tp from pkt per second in kbps */
-	return mi->groups[i].rates[j].cur_tp * AVG_PKT_SIZE * 8 / 1024;
+	/* convert tp_avg from pkt per second in kbps */
+	tp_avg = minstrel_ht_get_tp_avg(mi, i, j) * AVG_PKT_SIZE * 8 / 1024;
+
+	return tp_avg;
 }
 
 static const struct rate_control_ops mac80211_minstrel_ht = {
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index fa21a82..68dce4f 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -121,5 +121,6 @@ struct minstrel_ht_sta_priv {
 
 void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
 void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta);
+int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate);
 
 #endif
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 5529add..ce3baab 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -19,7 +19,7 @@ static char *
 minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
 {
 	const struct mcs_group *mg;
-	unsigned int j, tp, prob, eprob, tx_time;
+	unsigned int j, tp_avg, prob, eprob, tx_time;
 	char htmode = '2';
 	char gimode = 'L';
 	u32 gflags;
@@ -81,13 +81,13 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
 		tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
 		p += sprintf(p, "%6u   ", tx_time);
 
-		tp = mrs->cur_tp / 10;
+		tp_avg = minstrel_ht_get_tp_avg(mi, i, j);
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
 		p += sprintf(p, "%4u.%1u   %3u.%1u     %3u.%1u "
 				"%3u   %3u %-3u   %9llu   %-9llu\n",
-				tp / 10, tp % 10,
+				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
 				mrs->retry_count,
@@ -164,7 +164,7 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p,
 			    struct timeval tv)
 {
 	const struct mcs_group *mg;
-	unsigned int j, tp, prob, eprob, tx_time;
+	unsigned int j, tp_avg, prob, eprob, tx_time;
 	char htmode = '2';
 	char gimode = 'L';
 	u32 gflags;
@@ -225,12 +225,12 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p,
 		tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
 		p += sprintf(p, "%u,", tx_time);
 
-		tp = mrs->cur_tp / 10;
+		tp_avg = minstrel_ht_get_tp_avg(mi, i, j);
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
 		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,",
-				tp / 10, tp % 10,
+				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
 				mrs->retry_count,
-- 
2.2.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 08/10] mac80211: add max. lossless throughput per rate to rc_stats
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
                   ` (6 preceding siblings ...)
  2015-02-13 14:57 ` [PATCH v2 07/10] mac80211: restructure per-rate throughput calculation into function Thomas Huehn
@ 2015-02-13 14:57 ` Thomas Huehn
  2015-03-17  8:32   ` Felix Fietkau
  2015-02-13 14:57 ` [PATCH v2 09/10] mac80211: reduce calculation costs of EWMA Thomas Huehn
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 17+ messages in thread
From: Thomas Huehn @ 2015-02-13 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, nbd, thomas

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 8957 bytes --]

This patch adds the new statistic "maximum possible lossless
throughput" to Minstrels and Minstrel-HTs rc_stats (in debugfs). This
enables comprehensive comparison between current per-rate throughput
and max. achievable per-rate throughput.

Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
---
 net/mac80211/rc80211_minstrel.c            | 12 ++++++++++++
 net/mac80211/rc80211_minstrel.h            |  1 +
 net/mac80211/rc80211_minstrel_debugfs.c    | 18 +++++++++++-------
 net/mac80211/rc80211_minstrel_ht.c         | 19 +++++++++++++++++++
 net/mac80211/rc80211_minstrel_ht.h         |  1 +
 net/mac80211/rc80211_minstrel_ht_debugfs.c | 20 ++++++++++++--------
 6 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 28de2f7a..42dfef8 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -87,7 +87,19 @@ int minstrel_get_tp_avg(struct minstrel_rate *mr)
 	return tp_avg;
 }
 
+/* return max. potential lossless throughput */
+int minstrel_get_tp_max(struct minstrel_rate *mr)
+{
+	int tp_max, usecs;
 
+	usecs = mr->perfect_tx_time;
+	if (!usecs)
+		usecs = 1000000;
+
+	tp_max = 100000 / usecs;
+
+	return tp_max;
+}
 
 /* find & sort topmost throughput rates */
 static inline void
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 490df3b..6693d8d 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -135,6 +135,7 @@ void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
 /* Recalculate success probabilities and counters for a given rate using EWMA */
 void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);
 int minstrel_get_tp_avg(struct minstrel_rate *mr);
+int minstrel_get_tp_max(struct minstrel_rate *mr);
 
 /* debugfs */
 int minstrel_stats_open(struct inode *inode, struct file *file);
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index d8ccef7..182d552 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -75,7 +75,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
 {
 	struct minstrel_sta_info *mi = inode->i_private;
 	struct minstrel_debugfs_info *ms;
-	unsigned int i, tp_avg, prob, eprob;
+	unsigned int i, tp_max, tp_avg, prob, eprob;
 	char *p;
 
 	ms = kmalloc(2048, GFP_KERNEL);
@@ -85,9 +85,9 @@ minstrel_stats_open(struct inode *inode, struct file *file)
 	file->private_data = ms;
 	p = ms->buf;
 	p += sprintf(p, "\n");
-	p += sprintf(p, "best   _______rate_____    __statistics__    "
+	p += sprintf(p, "best   __________rate_________    __statistics__    "
 			"________last_______    ______sum-of________\n");
-	p += sprintf(p, "rate  [name idx airtime]  [ ø(tp) ø(prob)]  "
+	p += sprintf(p, "rate  [name idx airtime max_tp]  [ ø(tp) ø(prob)]  "
 			"[prob.|retry|suc|att]  [#success | #attempts]\n");
 
 	for (i = 0; i < mi->n_rates; i++) {
@@ -103,14 +103,16 @@ minstrel_stats_open(struct inode *inode, struct file *file)
 		p += sprintf(p, " %3u%s ", mr->bitrate / 2,
 				(mr->bitrate & 1 ? ".5" : "  "));
 		p += sprintf(p, "%3u  ", i);
-		p += sprintf(p, "%6u  ", mr->perfect_tx_time);
+		p += sprintf(p, "%6u ", mr->perfect_tx_time);
 
+		tp_max = minstrel_get_tp_max(mr);
 		tp_avg = minstrel_get_tp_avg(mr);
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
-		p += sprintf(p, " %4u.%1u   %3u.%1u     %3u.%1u %3u"
+		p += sprintf(p, "%4u.%1u   %4u.%1u   %3u.%1u     %3u.%1u %3u"
 				"   %3u %-3u   %9llu   %-9llu\n",
+				tp_max / 10, tp_max % 10,
 				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
@@ -145,7 +147,7 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file)
 	struct minstrel_sta_info *mi = inode->i_private;
 	struct minstrel_debugfs_info *ms;
 	struct timeval tv;
-	unsigned int i, tp_avg, prob, eprob;
+	unsigned int i, tp_max, tp_avg, prob, eprob;
 	char *p;
 
 	ms = kmalloc(2048, GFP_KERNEL);
@@ -173,12 +175,14 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file)
 		p += sprintf(p, "%u,", i);
 		p += sprintf(p, "%u,",mr->perfect_tx_time);
 
+		tp_max = minstrel_get_tp_max(mr);
 		tp_avg = minstrel_get_tp_avg(mr);
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
-		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,"
+		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
 				"%llu,%llu,%d,%d\n",
+				tp_max / 10, tp_max % 10,
 				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 2a55f63..b62b04e 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -350,6 +350,25 @@ minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate)
 }
 
 /*
+ * Return max. potential lossless throughput based on the average A-MPDU
+ */
+int
+minstrel_ht_get_tp_max(struct minstrel_ht_sta *mi, int group, int rate)
+{
+	unsigned int nsecs = 0;
+	unsigned int tp_max;
+
+	if (group != MINSTREL_CCK_GROUP)
+		nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
+
+	nsecs += minstrel_mcs_groups[group].duration[rate];
+	tp_max = 100000000 / nsecs;
+
+	return tp_max;
+}
+
+
+/*
  * Find & sort topmost throughput rates
  *
  * If multiple rates provide equal throughput the sorting is based on their
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index 68dce4f..b1ea339 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -122,5 +122,6 @@ struct minstrel_ht_sta_priv {
 void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
 void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta);
 int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate);
+int minstrel_ht_get_tp_max(struct minstrel_ht_sta *mi, int group, int rate);
 
 #endif
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index ce3baab..e70961f 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -19,7 +19,7 @@ static char *
 minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
 {
 	const struct mcs_group *mg;
-	unsigned int j, tp_avg, prob, eprob, tx_time;
+	unsigned int j, tp_max, tp_avg, prob, eprob, tx_time;
 	char htmode = '2';
 	char gimode = 'L';
 	u32 gflags;
@@ -79,14 +79,16 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
 
 		/* tx_time[rate(i)] in usec */
 		tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
-		p += sprintf(p, "%6u   ", tx_time);
+		p += sprintf(p, "%6u  ", tx_time);
 
+		tp_max = minstrel_ht_get_tp_max(mi, i, j);
 		tp_avg = minstrel_ht_get_tp_avg(mi, i, j);
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
-		p += sprintf(p, "%4u.%1u   %3u.%1u     %3u.%1u "
+		p += sprintf(p, "%4u.%1u    %4u.%1u   %3u.%1u    %3u.%1u "
 				"%3u   %3u %-3u   %9llu   %-9llu\n",
+				tp_max / 10, tp_max % 10,
 				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
@@ -125,11 +127,11 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
 	p = ms->buf;
 
 	p += sprintf(p, "\n");
-	p += sprintf(p, "              best   ________rate______    "
+	p += sprintf(p, "              best   ____________rate__________    "
 			"__statistics__    ________last_______    "
 			"______sum-of________\n");
-	p += sprintf(p, "mode guard #  rate  [name   idx airtime]  [ ø(tp) "
-			"ø(prob)]  [prob.|retry|suc|att]  [#success | "
+	p += sprintf(p, "mode guard #  rate  [name   idx airtime  max_tp]  "
+			"[ ø(tp) ø(prob)]  [prob.|retry|suc|att]  [#success | "
 			"#attempts]\n");
 
 	p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
@@ -164,7 +166,7 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p,
 			    struct timeval tv)
 {
 	const struct mcs_group *mg;
-	unsigned int j, tp_avg, prob, eprob, tx_time;
+	unsigned int j, tp_max, tp_avg, prob, eprob, tx_time;
 	char htmode = '2';
 	char gimode = 'L';
 	u32 gflags;
@@ -225,11 +227,13 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p,
 		tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
 		p += sprintf(p, "%u,", tx_time);
 
+		tp_max = minstrel_ht_get_tp_max(mi, i, j);
 		tp_avg = minstrel_ht_get_tp_avg(mi, i, j);
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
-		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,",
+		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,",
+				tp_max / 10, tp_max % 10,
 				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
-- 
2.2.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 09/10] mac80211: reduce calculation costs of EWMA
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
                   ` (7 preceding siblings ...)
  2015-02-13 14:57 ` [PATCH v2 08/10] mac80211: add max. lossless throughput per rate to rc_stats Thomas Huehn
@ 2015-02-13 14:57 ` Thomas Huehn
  2015-02-13 14:57 ` [PATCH v2 10/10] mac80211: add standard deviation to Minstrels throughput statistic Thomas Huehn
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Thomas Huehn @ 2015-02-13 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, nbd, thomas

This patch reduces the calculation costs of the EWMA macro from
"2x multiplication and 1 addition" down to "1x multiplication and
2x additions". This slightly improves performance depending on the
CPU architecture.

Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
---
 net/mac80211/rc80211_minstrel.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 6693d8d..38158b0 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -27,7 +27,12 @@
 static inline int
 minstrel_ewma(int old, int new, int weight)
 {
-	return (new * (EWMA_DIV - weight) + old * weight) / EWMA_DIV;
+	int diff, incr;
+
+	diff = new - old;
+	incr = (EWMA_DIV - weight) * diff / EWMA_DIV;
+
+	return old + incr;
 }
 
 struct minstrel_rate_stats {
-- 
2.2.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 10/10] mac80211: add standard deviation to Minstrels throughput statistic
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
                   ` (8 preceding siblings ...)
  2015-02-13 14:57 ` [PATCH v2 09/10] mac80211: reduce calculation costs of EWMA Thomas Huehn
@ 2015-02-13 14:57 ` Thomas Huehn
  2015-02-25 21:00 ` [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Bastian Bittorf
  2015-02-25 21:18 ` Bastian Bittorf
  11 siblings, 0 replies; 17+ messages in thread
From: Thomas Huehn @ 2015-02-13 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, nbd, thomas

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 8026 bytes --]

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>
---
 net/mac80211/rc80211_minstrel.c            | 19 ++++++++++++++-----
 net/mac80211/rc80211_minstrel.h            | 22 +++++++++++++++++++++-
 net/mac80211/rc80211_minstrel_debugfs.c    | 19 ++++++++++++-------
 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 42dfef8..c108f03 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -161,7 +161,7 @@ minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 }
 
 /*
-* Recalculate success probabilities and counters for a given rate using EWMA
+* Recalculate statistics and counters of a given rate
 */
 void
 minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs)
@@ -169,11 +169,20 @@ minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs)
 	if (unlikely(mrs->attempts > 0)) {
 		mrs->sample_skipped = 0;
 		mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
-		if (unlikely(!mrs->att_hist))
+		if (unlikely(!mrs->att_hist)) {
 			mrs->prob_ewma = mrs->cur_prob;
-		else
+		} else {
+			/* update exponential weighted moving variance */
+			mrs->prob_ewmsd = minstrel_ewmsd(mrs->prob_ewmsd,
+							 mrs->cur_prob,
+							 mrs->prob_ewma,
+							 EWMA_LEVEL);
+
+			/*update exponential weighted moving avarage */
 			mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
-						     mrs->cur_prob, EWMA_LEVEL);
+						       mrs->cur_prob,
+						       EWMA_LEVEL);
+		}
 		mrs->att_hist += mrs->attempts;
 		mrs->succ_hist += mrs->success;
 	} else {
@@ -200,7 +209,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 		struct minstrel_rate *mr = &mi->r[i];
 		struct minstrel_rate_stats *mrs = &mi->r[i].stats;
 
-		/* Update success probabilities per rate */
+		/* Update statistics of success probability per rate */
 		minstrel_calc_rate_stats(mrs);
 
 		/* Sample less often below the 10% chance of success.
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 38158b0..713c81e 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)
 	return old + incr;
 }
 
+/*
+ * Perform EWMSD (Exponentially Weighted Moving Standard Deviation) calculation
+ */
+static inline int
+minstrel_ewmsd(int old_ewmsd, int cur_prob, int prob_ewma, int weight)
+{
+	int diff, incr, tmp_var;
+
+	/* calculate exponential weighted moving variance */
+	diff = MINSTREL_TRUNC((cur_prob - prob_ewma) * 1000000);
+	incr = (EWMA_DIV - weight) * diff / EWMA_DIV;
+	tmp_var = old_ewmsd * old_ewmsd;
+	tmp_var = weight * (tmp_var + diff * incr / 1000000) / EWMA_DIV;
+
+	/* return standard deviation */
+	return (u16) int_sqrt(tmp_var);
+}
+
 struct minstrel_rate_stats {
 	/* current / last sampling period attempts/success counters */
 	u16 attempts, last_attempts;
@@ -45,9 +63,11 @@ struct minstrel_rate_stats {
 
 	/* statistis of packet delivery probability
 	 *  cur_prob  - current prob within last update intervall
-	 *  prob_ewma - exponential weighted moving average of prob */
+	 *  prob_ewma - exponential weighted moving average of prob
+	 *  prob_ewmsd - exp. weighted moving standard deviation of prob */
 	unsigned int cur_prob;
 	unsigned int prob_ewma;
+	u16 prob_ewmsd;
 
 	/* maximum retry counts */
 	u8 retry_count;
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index 182d552..a217a2c 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)
 	file->private_data = ms;
 	p = ms->buf;
 	p += sprintf(p, "\n");
-	p += sprintf(p, "best   __________rate_________    __statistics__    "
-			"________last_______    ______sum-of________\n");
-	p += sprintf(p, "rate  [name idx airtime max_tp]  [ ø(tp) ø(prob)]  "
-			"[prob.|retry|suc|att]  [#success | #attempts]\n");
+	p += sprintf(p, "best   __________rate_________    ______"
+			"statistics______    ________last_______    "
+			"______sum-of________\n");
+	p += sprintf(p, "rate  [name idx airtime max_tp]  [ ø(tp) ø(prob) "
+			"sd(prob)]  [prob.|retry|suc|att]  "
+			"[#success | #attempts]\n");
 
 	for (i = 0; i < mi->n_rates; i++) {
 		struct minstrel_rate *mr = &mi->r[i];
@@ -110,11 +112,13 @@ minstrel_stats_open(struct inode *inode, struct file *file)
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
-		p += sprintf(p, "%4u.%1u   %4u.%1u   %3u.%1u     %3u.%1u %3u"
-				"   %3u %-3u   %9llu   %-9llu\n",
+		p += sprintf(p, "%4u.%1u   %4u.%1u   %3u.%1u    %3u.%1u"
+				"     %3u.%1u %3u   %3u %-3u   "
+				"%9llu   %-9llu\n",
 				tp_max / 10, tp_max % 10,
 				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
+				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
 				prob / 10, prob % 10,
 				mrs->retry_count,
 				mrs->last_success,
@@ -180,11 +184,12 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file)
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
-		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
+		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
 				"%llu,%llu,%d,%d\n",
 				tp_max / 10, tp_max % 10,
 				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
+				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
 				prob / 10, prob % 10,
 				mrs->retry_count,
 				mrs->last_success,
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index e70961f..892e87ab 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)
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
-		p += sprintf(p, "%4u.%1u    %4u.%1u   %3u.%1u    %3u.%1u "
-				"%3u   %3u %-3u   %9llu   %-9llu\n",
+		p += sprintf(p, "%4u.%1u   %4u.%1u   %3u.%1u    %3u.%1u"
+				"     %3u.%1u %3u   %3u %-3u   "
+				"%9llu   %-9llu\n",
 				tp_max / 10, tp_max % 10,
 				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
+				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
 				prob / 10, prob % 10,
 				mrs->retry_count,
 				mrs->last_success,
@@ -128,10 +130,10 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
 
 	p += sprintf(p, "\n");
 	p += sprintf(p, "              best   ____________rate__________    "
-			"__statistics__    ________last_______    "
+			"______statistics______    ________last_______    "
 			"______sum-of________\n");
 	p += sprintf(p, "mode guard #  rate  [name   idx airtime  max_tp]  "
-			"[ ø(tp) ø(prob)]  [prob.|retry|suc|att]  [#success | "
+			"[ ø(tp) ø(prob) sd(prob)]  [prob.|retry|suc|att]  [#success | "
 			"#attempts]\n");
 
 	p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
@@ -232,10 +234,12 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p,
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
 
-		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,",
+		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"
+				"%u,%llu,%llu,",
 				tp_max / 10, tp_max % 10,
 				tp_avg / 10, tp_avg % 10,
 				eprob / 10, eprob % 10,
+				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
 				prob / 10, prob % 10,
 				mrs->retry_count,
 				mrs->last_success,
-- 
2.2.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
                   ` (9 preceding siblings ...)
  2015-02-13 14:57 ` [PATCH v2 10/10] mac80211: add standard deviation to Minstrels throughput statistic Thomas Huehn
@ 2015-02-25 21:00 ` Bastian Bittorf
  2015-02-25 21:18 ` Bastian Bittorf
  11 siblings, 0 replies; 17+ messages in thread
From: Bastian Bittorf @ 2015-02-25 21:00 UTC (permalink / raw)
  To: Thomas Huehn

* Job <thomas@net.t-labs.tu-berlin.de> [13.02.2015 16:32]:
> This patch series adds several improvements to the readability, the
> output format of rc_stats and the calculated statistics of Minstrel
> and Minstrel-HT. Variable names got more consistent and functions
> got unified between both rate control algorithms.

i did intensive testing in our small testnet (~50 routers) with all
kinds of platforms (ar71xx, x86, mpc85xx/ppc) and have no objections
for this patch-series but a big "thumbs up" for very nice, readable
and machine-parseable minstrel/rate-selector-output:

root@KuechenJukebox:~ cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/f4:ec:38:9d:81:f0/rc_stats

              best   ____________rate__________    ___________statistics__________    ________last_______    ______sum-of________
mode guard #  rate  [name   idx airtime  max_tp]  [ ø(tp) ø-2σ(tp) ø(prob) σ(prob)]  [prob.|retry|suc|att]  [#success | #attempts]
CCK    LP  1          1.0M  120   10548     0.9      0.0      0.0     6.4     1.6       5.2   2     0 0            74   585      
CCK    LP  1          2.0M  121    5476     1.8      0.0      0.0     0.0     0.0       0.0   0     0 0             0   2        
CCK    LP  1          5.5M  122    2411     4.1      0.0      0.0     0.0     0.0       0.0   0     0 0             0   2        
CCK    LP  1         11.0M  123    1535     6.5      1.2      1.1    18.7     0.7       0.0   0     0 0             1   3        
HT20  LGI  1    CD   MCS0     0    1480     6.5      3.3      3.2    52.7     1.2      33.3   2     0 0           320   657      
HT20  LGI  1  A   P  MCS1     1     740    12.5      9.9      9.7    79.8     0.9     100.0   3     2 2           645   1234     
HT20  LGI  1         MCS2     2     496    18.1      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  1         MCS3     3     372    23.4      1.9      1.3     8.8     1.5       0.0   5     0 0            69   281      
HT20  LGI  1         MCS4     4     248    33.1      0.0      0.0     0.0     0.0       0.0   0     0 0             0   2        
HT20  LGI  1         MCS5     5     188    41.3      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  1         MCS6     6     168    45.0      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  1         MCS7     7     148    49.5      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  2         MCS8    10     740    12.5      0.0      0.0     0.0     0.0       0.0   0     0 0             0   2        
HT20  LGI  2   B     MCS9    11     372    23.4      7.4      6.8    32.4     1.6       0.0   4     0 8            10   27       
HT20  LGI  2         MCS10   12     248    33.1      0.0      0.0     0.0     0.0       0.0   0     0 0             0   2        
HT20  LGI  2         MCS11   13     188    41.3      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  2         MCS12   14     124    56.1      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  2         MCS13   15      96    66.6      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  2         MCS14   16      84    72.4      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  2         MCS15   17      76    76.9      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        

Total packet count::    ideal 1023      lookaround 48
Average # of aggregated frames per A-MPDU: 2.7


root@KuechenJukebox:~ cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/f4:ec:38:9d:81:f0/rc_stats_csv 
1424897596.239275,CCK,LP,1,,,,,, 1.0M,120,10548,0.9,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,CCK,LP,1,,,,,, 2.0M,121,5476,1.8,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,CCK,LP,1,,,,,, 5.5M,122,2411,4.1,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,CCK,LP,1,,,,,,11.0M,123,1535,6.5,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,A,B,C,D,P,MCS0 ,0,1480,6.2,0.0,0.0,0.0,0.0,0.0,1,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS1 ,1,740,11.7,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS2 ,2,496,16.5,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS3 ,3,372,20.8,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS4 ,4,248,28.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS5 ,5,188,33.7,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS6 ,6,168,36.2,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS7 ,7,148,39.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS8 ,10,740,11.7,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS9 ,11,372,20.8,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS10,12,248,28.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS11,13,188,33.7,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS12,14,124,43.1,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS13,15,96,49.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS14,16,84,52.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS15,17,76,54.3,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0



so a just want to say:

Tested-by: Bastian Bittorf

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics
  2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
                   ` (10 preceding siblings ...)
  2015-02-25 21:00 ` [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Bastian Bittorf
@ 2015-02-25 21:18 ` Bastian Bittorf
  11 siblings, 0 replies; 17+ messages in thread
From: Bastian Bittorf @ 2015-02-25 21:18 UTC (permalink / raw)
  To: linux-wireless

* Job <thomas@net.t-labs.tu-berlin.de> [13.02.2015 16:32]:
> This patch series adds several improvements to the readability, the
> output format of rc_stats and the calculated statistics of Minstrel
> and Minstrel-HT. Variable names got more consistent and functions
> got unified between both rate control algorithms.

i did intensive testing in our small testnet (~50 routers) with all
kinds of platforms (ar71xx, x86, mpc85xx/ppc) and have no objections
for this patch-series but a big "thumbs up" for very nice, readable
and machine-parseable minstrel/rate-selector-output:

root@KuechenJukebox:~ cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/f4:ec:38:9d:81:f0/rc_stats

              best   ____________rate__________    ___________statistics__________    ________last_______    ______sum-of________
mode guard #  rate  [name   idx airtime  max_tp]  [ ø(tp) ø-2σ(tp) ø(prob) σ(prob)]  [prob.|retry|suc|att]  [#success | #attempts]
CCK    LP  1          1.0M  120   10548     0.9      0.0      0.0     6.4     1.6       5.2   2     0 0            74   585      
CCK    LP  1          2.0M  121    5476     1.8      0.0      0.0     0.0     0.0       0.0   0     0 0             0   2        
CCK    LP  1          5.5M  122    2411     4.1      0.0      0.0     0.0     0.0       0.0   0     0 0             0   2        
CCK    LP  1         11.0M  123    1535     6.5      1.2      1.1    18.7     0.7       0.0   0     0 0             1   3        
HT20  LGI  1    CD   MCS0     0    1480     6.5      3.3      3.2    52.7     1.2      33.3   2     0 0           320   657      
HT20  LGI  1  A   P  MCS1     1     740    12.5      9.9      9.7    79.8     0.9     100.0   3     2 2           645   1234     
HT20  LGI  1         MCS2     2     496    18.1      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  1         MCS3     3     372    23.4      1.9      1.3     8.8     1.5       0.0   5     0 0            69   281      
HT20  LGI  1         MCS4     4     248    33.1      0.0      0.0     0.0     0.0       0.0   0     0 0             0   2        
HT20  LGI  1         MCS5     5     188    41.3      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  1         MCS6     6     168    45.0      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  1         MCS7     7     148    49.5      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  2         MCS8    10     740    12.5      0.0      0.0     0.0     0.0       0.0   0     0 0             0   2        
HT20  LGI  2   B     MCS9    11     372    23.4      7.4      6.8    32.4     1.6       0.0   4     0 8            10   27       
HT20  LGI  2         MCS10   12     248    33.1      0.0      0.0     0.0     0.0       0.0   0     0 0             0   2        
HT20  LGI  2         MCS11   13     188    41.3      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  2         MCS12   14     124    56.1      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  2         MCS13   15      96    66.6      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  2         MCS14   16      84    72.4      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        
HT20  LGI  2         MCS15   17      76    76.9      0.0      0.0     0.0     0.0       0.0   0     0 0             0   3        

Total packet count::    ideal 1023      lookaround 48
Average # of aggregated frames per A-MPDU: 2.7


root@KuechenJukebox:~ cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/f4:ec:38:9d:81:f0/rc_stats_csv 
1424897596.239275,CCK,LP,1,,,,,, 1.0M,120,10548,0.9,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,CCK,LP,1,,,,,, 2.0M,121,5476,1.8,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,CCK,LP,1,,,,,, 5.5M,122,2411,4.1,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,CCK,LP,1,,,,,,11.0M,123,1535,6.5,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,A,B,C,D,P,MCS0 ,0,1480,6.2,0.0,0.0,0.0,0.0,0.0,1,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS1 ,1,740,11.7,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS2 ,2,496,16.5,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS3 ,3,372,20.8,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS4 ,4,248,28.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS5 ,5,188,33.7,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS6 ,6,168,36.2,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,1,,,,,,MCS7 ,7,148,39.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS8 ,10,740,11.7,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS9 ,11,372,20.8,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS10,12,248,28.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS11,13,188,33.7,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS12,14,124,43.1,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS13,15,96,49.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS14,16,84,52.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0
1424897596.239275,HT20,LGI,2,,,,,,MCS15,17,76,54.3,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,1.0



so a just want to say:

Tested-by: Bastian Bittorf

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 03/10] mac80211: add new Minstrel statistic output via csv
  2015-02-13 14:57 ` [PATCH v2 03/10] mac80211: add new Minstrel statistic output via csv Thomas Huehn
@ 2015-03-17  8:16   ` Felix Fietkau
  0 siblings, 0 replies; 17+ messages in thread
From: Felix Fietkau @ 2015-03-17  8:16 UTC (permalink / raw)
  To: Thomas Huehn, linux-wireless; +Cc: johannes

On 2015-02-13 15:57, Thomas Huehn wrote:
> 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>
> ---
>  net/mac80211/rc80211_minstrel.h            |  6 +-
>  net/mac80211/rc80211_minstrel_debugfs.c    | 95 ++++++++++++++++++++++++++----
>  net/mac80211/rc80211_minstrel_ht_debugfs.c |  2 +-
>  3 files changed, 88 insertions(+), 15 deletions(-)
> 

> diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
> index 7fc690f..b300513 100644
> --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
> +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
> @@ -112,7 +112,7 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
>  
>  	if (!msp->is_ht) {
>  		inode->i_private = &msp->legacy;
> -		ret = minstrel_stats_open(inode, file);
> +		ret = minstrel_stats_csv_open(inode, file);
That does not look right to me.

- Felix

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 04/10] mac80211: add new Minstrel-HT statistic output via csv
  2015-02-13 14:57 ` [PATCH v2 04/10] mac80211: add new Minstrel-HT " Thomas Huehn
@ 2015-03-17  8:18   ` Felix Fietkau
  0 siblings, 0 replies; 17+ messages in thread
From: Felix Fietkau @ 2015-03-17  8:18 UTC (permalink / raw)
  To: Thomas Huehn, linux-wireless; +Cc: johannes

On 2015-02-13 15:57, Thomas Huehn wrote:
> This patch adds a new debugfs file "rc_stats_csv" to output
> Minstrel-HTs 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>
> ---
> --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
> +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
> +static int
> +minstrel_ht_stats_csv_open(struct inode *inode, struct file *file)
> +{
> +	struct minstrel_ht_sta_priv *msp = inode->i_private;
> +	struct minstrel_ht_sta *mi = &msp->ht;
> +	struct minstrel_debugfs_info *ms;
> +	struct timeval tv;
> +	unsigned int i;
> +	int ret;
> +	char *p;
> +
> +	do_gettimeofday(&tv);
> +
> +	if (!msp->is_ht) {
> +		inode->i_private = &msp->legacy;
> +		ret = minstrel_stats_open(inode, file);
Should be minstrel_stats_csv_open here?

- Felix

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 07/10] mac80211: restructure per-rate throughput calculation into function
  2015-02-13 14:57 ` [PATCH v2 07/10] mac80211: restructure per-rate throughput calculation into function Thomas Huehn
@ 2015-03-17  8:24   ` Felix Fietkau
  0 siblings, 0 replies; 17+ messages in thread
From: Felix Fietkau @ 2015-03-17  8:24 UTC (permalink / raw)
  To: Thomas Huehn, linux-wireless; +Cc: johannes

On 2015-02-13 15:57, Thomas Huehn wrote:
> This patch moves Minstrels and Minstrel-HTs per-rate throughput
> calculation (EWMA(thr)) into a dedicated function to be called.
> Therefore the variable "unsigned int cur_tp" within struct
> "minstrel_rate_stats" becomes obsolete.  and is removed to free
> up its space.
> 
> Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
> ---
>  net/mac80211/rc80211_minstrel.c            | 46 +++++++++++------
>  net/mac80211/rc80211_minstrel.h            |  4 +-
>  net/mac80211/rc80211_minstrel_debugfs.c    | 12 ++---
>  net/mac80211/rc80211_minstrel_ht.c         | 79 ++++++++++++++++++------------
>  net/mac80211/rc80211_minstrel_ht.h         |  1 +
>  net/mac80211/rc80211_minstrel_ht_debugfs.c | 12 ++---
>  6 files changed, 94 insertions(+), 60 deletions(-)
> 
> diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
> index 89db6cf..28de2f7a 100644
> --- a/net/mac80211/rc80211_minstrel.c
> +++ b/net/mac80211/rc80211_minstrel.c
> @@ -69,13 +69,34 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
>  	return i;
>  }
>  
> +/* return current EMWA throughput */
> +int minstrel_get_tp_avg(struct minstrel_rate *mr)
> +{
> +	int tp_avg, usecs;
> +
> +	usecs = mr->perfect_tx_time;
> +	if (!usecs)
> +		usecs = 1000000;
> +
> +	/* reset thr. below 10% success */
> +	if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100))
> +		tp_avg = 0;
You don't really need a variable, you can just do return 0 here and
reduce indentation of the line below.

> +	else
> +		tp_avg = MINSTREL_TRUNC(mr->stats.prob_ewma * (100000 / usecs));
> +
> +	return tp_avg;
> +}
> +
> +
> +
>  /* find & sort topmost throughput rates */
>  static inline void
>  minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
>  {
>  	int j = MAX_THR_RATES;
>  
> -	while (j > 0 && mi->r[i].stats.cur_tp > mi->r[tp_list[j - 1]].stats.cur_tp)
> +	while (j > 0 && (minstrel_get_tp_avg(&mi->r[i]) >
> +				minstrel_get_tp_avg(&mi->r[tp_list[j - 1]])))
Indentation seems off.

>  		j--;
>  	if (j < MAX_THR_RATES - 1)
>  		memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1));
> @@ -158,8 +179,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
>  {
>  	u8 tmp_tp_rate[MAX_THR_RATES];
>  	u8 tmp_prob_rate = 0;
> -	u32 usecs;
> -	int i;
> +	int i, tmp_cur_tp, tmp_prob_tp;
>  
>  	for (i = 0; i < MAX_THR_RATES; i++)
>  	    tmp_tp_rate[i] = 0;
> diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
> index 6b07686..2a55f63 100644
> --- a/net/mac80211/rc80211_minstrel_ht.c
> +++ b/net/mac80211/rc80211_minstrel_ht.c
> @@ -312,23 +312,23 @@ minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
>  }
>  
>  /*
> - * Calculate throughput based on the average A-MPDU length, taking into account
> - * the expected number of retransmissions and their expected length
> + * Return current throughput based on the average A-MPDU length, taking into
> + * account the expected number of retransmissions and their expected length
>   */
> -static void
> -minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
> +int
> +minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate)
>  {
>  	struct minstrel_rate_stats *mrs;
>  	unsigned int nsecs = 0;
> -	unsigned int tmp_prob_ewma;
> +	unsigned int tmp_prob_ewma, tp_avg;
>  
>  	mrs = &mi->groups[group].rates[rate];
>  	tmp_prob_ewma = mrs->prob_ewma;
>  
>  	/* do not account throughput if sucess prob is below 10% */
>  	if (mrs->prob_ewma < MINSTREL_FRAC(10, 100)) {
> -		mrs->cur_tp = 0;
> -		return;
> +		tp_avg = 0;
> +		return tp_avg;
No need for the tp_avg variable.

>  	}
>  
>  	/*
> @@ -344,7 +344,9 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
>  	nsecs += minstrel_mcs_groups[group].duration[rate];
>  
>  	/* prob is scaled - see MINSTREL_FRAC above */
> -	mrs->cur_tp = MINSTREL_TRUNC(1000000 * ((tmp_prob_ewma * 1000) / nsecs));
> +	tp_avg = MINSTREL_TRUNC(100000 * ((tmp_prob_ewma * 1000) / nsecs));
> +
> +	return tp_avg;
>  }
>  
>  /*

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 08/10] mac80211: add max. lossless throughput per rate to rc_stats
  2015-02-13 14:57 ` [PATCH v2 08/10] mac80211: add max. lossless throughput per rate to rc_stats Thomas Huehn
@ 2015-03-17  8:32   ` Felix Fietkau
  0 siblings, 0 replies; 17+ messages in thread
From: Felix Fietkau @ 2015-03-17  8:32 UTC (permalink / raw)
  To: Thomas Huehn, linux-wireless; +Cc: johannes

On 2015-02-13 15:57, Thomas Huehn wrote:
> This patch adds the new statistic "maximum possible lossless
> throughput" to Minstrels and Minstrel-HTs rc_stats (in debugfs). This
> enables comprehensive comparison between current per-rate throughput
> and max. achievable per-rate throughput.
> 
> Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
> ---
>  net/mac80211/rc80211_minstrel.c            | 12 ++++++++++++
>  net/mac80211/rc80211_minstrel.h            |  1 +
>  net/mac80211/rc80211_minstrel_debugfs.c    | 18 +++++++++++-------
>  net/mac80211/rc80211_minstrel_ht.c         | 19 +++++++++++++++++++
>  net/mac80211/rc80211_minstrel_ht.h         |  1 +
>  net/mac80211/rc80211_minstrel_ht_debugfs.c | 20 ++++++++++++--------
>  6 files changed, 56 insertions(+), 15 deletions(-)
> 
> diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
> index 28de2f7a..42dfef8 100644
> --- a/net/mac80211/rc80211_minstrel.c
> +++ b/net/mac80211/rc80211_minstrel.c
> @@ -87,7 +87,19 @@ int minstrel_get_tp_avg(struct minstrel_rate *mr)
>  	return tp_avg;
>  }
>  
> +/* return max. potential lossless throughput */
> +int minstrel_get_tp_max(struct minstrel_rate *mr)
> +{
> +	int tp_max, usecs;
>  
> +	usecs = mr->perfect_tx_time;
> +	if (!usecs)
> +		usecs = 1000000;
> +
> +	tp_max = 100000 / usecs;
> +
> +	return tp_max;
> +}
This should probably be an inline function, and you can remove the
tp_max variable as well.
By the way, in the case of !usecs, the result (100000 / 1000000) will be
0, so you can simplify the logic.


>  /* find & sort topmost throughput rates */
>  static inline void
> diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
> index 2a55f63..b62b04e 100644
> --- a/net/mac80211/rc80211_minstrel_ht.c
> +++ b/net/mac80211/rc80211_minstrel_ht.c
> @@ -350,6 +350,25 @@ minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate)
>  }
>  
>  /*
> + * Return max. potential lossless throughput based on the average A-MPDU
> + */
> +int
> +minstrel_ht_get_tp_max(struct minstrel_ht_sta *mi, int group, int rate)
> +{
> +	unsigned int nsecs = 0;
> +	unsigned int tp_max;
> +
> +	if (group != MINSTREL_CCK_GROUP)
> +		nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
> +
> +	nsecs += minstrel_mcs_groups[group].duration[rate];
> +	tp_max = 100000000 / nsecs;
> +
> +	return tp_max;
> +}
I don't like duplication of the throughput metric - gets annoying if we
ever decide to tweak it. How about unifying this with
minstrel_ht_get_tp_avg by passing in the prob value as a parameter.

- Felix

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2015-03-17  8:32 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-13 14:57 [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Thomas Huehn
2015-02-13 14:57 ` [PATCH v2 01/10] mac80211: enhance readability of Minstrels rc_stats output Thomas Huehn
2015-02-13 14:57 ` [PATCH v2 02/10] mac80211: enhance readability of Minstrel-HTs " Thomas Huehn
2015-02-13 14:57 ` [PATCH v2 03/10] mac80211: add new Minstrel statistic output via csv Thomas Huehn
2015-03-17  8:16   ` Felix Fietkau
2015-02-13 14:57 ` [PATCH v2 04/10] mac80211: add new Minstrel-HT " Thomas Huehn
2015-03-17  8:18   ` Felix Fietkau
2015-02-13 14:57 ` [PATCH v2 05/10] mac80211: unify Minstrel & Minstrel-HTs calculation of rate statistics Thomas Huehn
2015-02-13 14:57 ` [PATCH v2 06/10] mac80211: improve Minstrel variable & function naming Thomas Huehn
2015-02-13 14:57 ` [PATCH v2 07/10] mac80211: restructure per-rate throughput calculation into function Thomas Huehn
2015-03-17  8:24   ` Felix Fietkau
2015-02-13 14:57 ` [PATCH v2 08/10] mac80211: add max. lossless throughput per rate to rc_stats Thomas Huehn
2015-03-17  8:32   ` Felix Fietkau
2015-02-13 14:57 ` [PATCH v2 09/10] mac80211: reduce calculation costs of EWMA Thomas Huehn
2015-02-13 14:57 ` [PATCH v2 10/10] mac80211: add standard deviation to Minstrels throughput statistic Thomas Huehn
2015-02-25 21:00 ` [PATCH v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics Bastian Bittorf
2015-02-25 21:18 ` Bastian Bittorf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.