Skip to contentSkip to conversation

mac80211: Add per-rate TX/RX statistics into debugfs

RFC New Jouni Malinen 1 participant 1 message Dec 15, 2008 mac80211

lore
Share & tools
lore
#0 lore raw

RFC 1/1 mac80211: Add per-rate TX/RX statistics into debugfs

Collect per-rate statistics about TX/RX frames for each STA if mac80211 debug counters are enabled and make this information available in debugfs.

---
 net/mac80211/debugfs_sta.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/main.c        |   20 ++++++++++++++++++++
 net/mac80211/rx.c          |   15 +++++++++++++++
 net/mac80211/sta_info.h    |   18 ++++++++++++++++++
 4 files changed, 98 insertions(+)
net/mac80211/debugfs_sta.c +45 -0
@@ -163,6 +163,45 @@ static ssize_t sta_agg_status_read(struc
 }
 STA_OPS(agg_status);
 
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+static ssize_t sta_txrx_read(struct file *file, char __user *userbuf,
+			     size_t count, loff_t *ppos)
+{
+	char buf[500], *p = buf;
+	struct sta_info *sta = file->private_data;
+	int i;
+
+	p += scnprintf(p, sizeof(buf) - (p - buf),
+		       "rate\tRX\tTX\texc\tretries\n");
+	for (i = 0; i < NUM_STATS_RATES; i++) {
+		if (sta->rx_frames[i] == 0 &&
+		    sta->tx_frames[i] == 0 &&
+		    sta->tx_exc_retries[i] == 0 &&
+		    sta->tx_retries[i] == 0)
+			continue;
+		p += scnprintf(p, sizeof(buf) - (p - buf),
+			       "%d\t%lu\t%lu\t%lu\t%lu\n",
+			       i, sta->rx_frames[i], sta->tx_frames[i],
+			       sta->tx_exc_retries[i], sta->tx_retries[i]);
+	}
+	for (i = 0; i < NUM_STATS_MCS; i++) {
+		if (sta->rx_frames_mcs[i] == 0 &&
+		    sta->tx_frames_mcs[i] == 0 &&
+		    sta->tx_exc_retries_mcs[i] == 0 &&
+		    sta->tx_retries_mcs[i] == 0)
+			continue;
+		p += scnprintf(p, sizeof(buf) - (p - buf),
+			       "MCS%d\t%lu\t%lu\t%lu\t%lu\n",
+			       i, sta->rx_frames_mcs[i], sta->tx_frames_mcs[i],
+			       sta->tx_exc_retries_mcs[i],
+			       sta->tx_retries_mcs[i]);
+	}
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+STA_OPS(txrx);
+#endif
+
 #define DEBUGFS_ADD(name) \
 	sta->debugfs.name = debugfs_create_file(#name, 0400, \
 		sta->debugfs.dir, sta, &sta_ ##name## _ops);
@@ -203,6 +242,9 @@ void ieee80211_sta_debugfs_add(struct st
 	DEBUGFS_ADD(inactive_ms);
 	DEBUGFS_ADD(last_seq_ctrl);
 	DEBUGFS_ADD(agg_status);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	DEBUGFS_ADD(txrx);
+#endif
 }
 
 void ieee80211_sta_debugfs_remove(struct sta_info *sta)
@@ -212,6 +254,9 @@ void ieee80211_sta_debugfs_remove(struct
 	DEBUGFS_DEL(inactive_ms);
 	DEBUGFS_DEL(last_seq_ctrl);
 	DEBUGFS_DEL(agg_status);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	DEBUGFS_DEL(txrx);
+#endif
 
 	debugfs_remove(sta->debugfs.dir);
 	sta->debugfs.dir = NULL;
net/mac80211/rx.c +15 -0
@@ -2252,6 +2252,21 @@ void __ieee80211_rx(struct ieee80211_hw 
 	 */
 	rcu_read_lock();
 
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	if (skb->len >= 16) {
+		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+		struct sta_info *sta = sta_info_get(local, hdr->addr2);
+		if (sta) {
+			if (status->flag & RX_FLAG_HT &&
+			    status->rate_idx < NUM_STATS_MCS)
+				sta->rx_frames_mcs[status->rate_idx]++;
+			if (!(status->flag & RX_FLAG_HT) &&
+			    status->rate_idx < NUM_STATS_RATES)
+				sta->rx_frames[status->rate_idx]++;
+		}
+	}
+#endif
+
 	/*
 	 * Frames with failed FCS/PLCP checksum are not returned,
 	 * all other frames are returned without radiotap header
net/mac80211/sta_info.h +18 -0
@@ -151,6 +151,9 @@ struct sta_ampdu_mlme {
 #define STA_INFO_PIN_STAT_PINNED	1
 #define STA_INFO_PIN_STAT_DESTROY	2
 
+#define NUM_STATS_RATES 20
+#define NUM_STATS_MCS 76
+
 /**
  * struct sta_info - STA information
  *
@@ -255,6 +258,10 @@ struct sta_info {
 	int last_qual;
 	int last_noise;
 	__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	unsigned long rx_frames[NUM_STATS_RATES];
+	unsigned long rx_frames_mcs[NUM_STATS_MCS];
+#endif
 
 	/* Updated from TX status path only, no locking requirements */
 	unsigned long tx_filtered_count;
@@ -268,6 +275,14 @@ struct sta_info {
 	unsigned long tx_fragments;
 	struct ieee80211_tx_rate last_tx_rate;
 	u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	unsigned long tx_frames[NUM_STATS_RATES];
+	unsigned long tx_retries[NUM_STATS_RATES];
+	unsigned long tx_exc_retries[NUM_STATS_RATES];
+	unsigned long tx_frames_mcs[NUM_STATS_MCS];
+	unsigned long tx_retries_mcs[NUM_STATS_MCS];
+	unsigned long tx_exc_retries_mcs[NUM_STATS_MCS];
+#endif
 
 	/*
 	 * Aggregation information, locked with lock.
@@ -298,6 +313,9 @@ struct sta_info {
 		struct dentry *num_ps_buf_frames;
 		struct dentry *inactive_ms;
 		struct dentry *last_seq_ctrl;
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+		struct dentry *txrx;
+#endif
 		struct dentry *agg_status;
 		bool add_has_run;
 	} debugfs;
net/mac80211/main.c +20 -0
@@ -501,6 +501,26 @@ void ieee80211_tx_status(struct ieee8021
 	sta = sta_info_get(local, hdr->addr1);
 
 	if (sta) {
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+		int idx = info->status.rates[0].idx;
+		if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
+			if (idx >= 0 && idx < NUM_STATS_MCS) {
+				sta->tx_frames_mcs[idx]++;
+				sta->tx_retries_mcs[idx] +=
+					info->status.rates[0].count;
+				if (!(info->flags & (IEEE80211_TX_CTL_NO_ACK |
+						     IEEE80211_TX_STAT_ACK)))
+					sta->tx_exc_retries_mcs[idx]++;
+			}
+		} else if (idx >= 0 && idx < NUM_STATS_RATES) {
+			sta->tx_frames[idx]++;
+			sta->tx_retries[idx] += info->status.rates[0].count;
+			if (!(info->flags & (IEEE80211_TX_CTL_NO_ACK |
+					     IEEE80211_TX_STAT_ACK)))
+				sta->tx_exc_retries[idx]++;
+		}
+#endif
+
 		if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
 		    test_sta_flags(sta, WLAN_STA_PS)) {
 			/*
Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA