From patchwork Mon Mar 7 16:23:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mohammed Shafi Shajakhan X-Patchwork-Id: 8521091 Return-Path: X-Original-To: patchwork-ath10k@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 293DF9F46A for ; Mon, 7 Mar 2016 16:30:42 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C5A4620256 for ; Mon, 7 Mar 2016 16:30:40 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5EE7B2028D for ; Mon, 7 Mar 2016 16:30:39 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1acy3F-0005Qi-2w; Mon, 07 Mar 2016 16:30:33 +0000 Received: from wolverine01.qualcomm.com ([199.106.114.254]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1acxxO-0005IC-3e for ath10k@lists.infradead.org; Mon, 07 Mar 2016 16:24:59 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=qti.qualcomm.com; i=@qti.qualcomm.com; q=dns/txt; s=qcdkim; t=1457367870; x=1488903870; h=from:to:cc:subject:date:message-id:mime-version; bh=L4isiDgU+n9lJe8LUOeznqJ4qO4Wz9K0FOvHHKjJYVE=; b=PNJ4gkzxBx9nbLJEJY35Xfc5Y1e0wrOjmNY4upW5BUeW2YzF30evKKLl LDs5HGC1DGgPvhvIjyrj7//eUiPuG9Rxu16BZsQMqwAzKuPorU0J1R8yW kDeNPaLg5QE6CsU4Rzo6ZH4Ox7XKuhQsDeLCPpp+gnE70Gz7lgGWgeRbf Y=; X-IronPort-AV: E=Sophos;i="5.22,552,1449561600"; d="scan'208";a="174715276" Received: from unknown (HELO Ironmsg04-R.qualcomm.com) ([10.53.140.108]) by wolverine01.qualcomm.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 07 Mar 2016 08:24:08 -0800 From: Mohammed Shafi Shajakhan X-IronPort-AV: E=McAfee;i="5700,7163,8096"; a="1151617588" Received: from nasanexm01c.na.qualcomm.com ([10.85.0.83]) by Ironmsg04-R.qualcomm.com with ESMTP/TLS/RC4-SHA; 07 Mar 2016 08:24:03 -0800 Received: from aphydexm01b.ap.qualcomm.com (10.252.127.11) by NASANEXM01C.na.qualcomm.com (10.85.0.83) with Microsoft SMTP Server (TLS) id 15.0.1130.7; Mon, 7 Mar 2016 08:24:02 -0800 Received: from qcmail1.qualcomm.com (10.80.80.8) by aphydexm01b.ap.qualcomm.com (10.252.127.11) with Microsoft SMTP Server (TLS) id 15.0.1130.7; Mon, 7 Mar 2016 21:53:52 +0530 Received: by qcmail1.qualcomm.com (sSMTP sendmail emulation); Mon, 07 Mar 2016 21:53:30 +0530 To: Subject: [RFC v1] mac80211: Add support for per station rx stats histogram Date: Mon, 7 Mar 2016 21:53:29 +0530 Message-ID: <1457367809-13637-1-git-send-email-mohammed@qca.qualcomm.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: NASANEXM01F.na.qualcomm.com (10.85.0.32) To aphydexm01b.ap.qualcomm.com (10.252.127.11) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160307_082431_555263_92FC73C9 X-CRM114-Status: GOOD ( 17.61 ) X-Spam-Score: -7.0 (-------) X-BeenThere: ath10k@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anilkumar Kolli , ath10k@lists.infradead.org, Mohammed Shafi Shajakhan , mohammed@codeaurora.org, johannes@sipsolutions.net, kvalo@codeaurora.org Sender: "ath10k" Errors-To: ath10k-bounces+patchwork-ath10k=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Mohammed Shafi Shajakhan Enable a provision in mac80211 'MAC80211_DEBUG_PER_STA_RX_STATS' to keep track and dump per station stats. Dump rx pkts / bytes per {MCS, BW, NSS, GI} per station in histogram format. Rx stats provides a history of the receive stats of the stations connected to us. Information such as how consistently we received the packet in higher MCS index / Bandwidth is very useful to assess the performance of us(AP) and the connected clients By default this feature is disabled though there is no impact in performance (based on our test results) This change is based on the design of Yanbo Li and HT packet rate table fix by Anil Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Anilkumar Kolli --- net/mac80211/Kconfig | 12 +++ net/mac80211/debugfs_sta.c | 225 ++++++++++++++++++++++++++++++++++++++++++++ net/mac80211/debugfs_sta.h | 5 + net/mac80211/rx.c | 2 + net/mac80211/sta_info.h | 23 +++++ 5 files changed, 267 insertions(+) diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 3891cbd..89fb17c 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -309,6 +309,18 @@ config MAC80211_DEBUG_COUNTERS If unsure, say N. +config MAC80211_DEBUG_PER_STA_RX_STATS + bool "Per Station Receive Stats Histogram" + depends on MAC80211_DEBUG_MENU + depends on MAC80211_DEBUGFS + ---help--- + Selecting this option causes mac80211 to keep track of + per station received packets, classify them based + on Bandwidth, Rate index (legacy, HT, VHT) and dump + a histogram of the same + + If unsure, say N. + config MAC80211_STA_HASH_MAX_SIZE int "Station hash table maximum size" if MAC80211_DEBUG_MENU default 0 diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index a39512f..ed095f3 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -289,6 +289,130 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, } STA_OPS(ht_capa); +static ssize_t sta_rx_stats_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ +#ifdef CONFIG_MAC80211_DEBUG_PER_STA_RX_STATS +#define RX_STATS_HIST_FMT(n) \ + do { \ + if ((i + 1) % n == 0) \ + len += scnprintf(buf + len, size - len, "\n\t\t"); \ + } while (0) + int retval = 0, len = 0; + char *buf; + const int size = 3072; + struct sta_info *sta = file->private_data; + struct ieee80211_local *local = sta->local; + int i; + char *bw_str[IEEE80211_BW_NUM] = {"20", "40", "80", "160"}; + char *nss_str[IEEE80211_NSS_NUM] = {"1x1", "2x2", "3x3", "4x4"}; + char *gi_str[IEEE80211_GI_NUM] = {"LGI", "SGI"}; + char *legacy_str[IEEE80211_LEGACY_RATE_NUM] = {"1", "2", "5.5", + "11", "6", "9", + "12", "18", "24", + "36", "48", "54"}; + buf = kzalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + len += scnprintf(buf + len, size - len, "VHT MCS packets: "); + for (i = 0; i < IEEE80211_VHT_MCS_NUM; i++) { + len += scnprintf(buf + len, size - len, "MCS %d: %llu, ", + i, sta->rx_vht_pkt[i]); + RX_STATS_HIST_FMT(5); + } + + len += scnprintf(buf + len, size - len, "\nHT MCS packets: "); + for (i = 0; i < IEEE80211_HT_MCS_NUM; i++) { + len += scnprintf(buf + len, size - len, "MCS %d: %llu, ", + i, sta->rx_ht_pkt[i]); + RX_STATS_HIST_FMT(5); + } + + len += scnprintf(buf + len, size - len, "\n\nBW packets: "); + for (i = 0; i < IEEE80211_BW_NUM; i++) + len += scnprintf(buf + len, size - len, "\t%sMhz: %llu", + bw_str[i], sta->rx_bw_pkt[i]); + + len += scnprintf(buf + len, size - len, "\n\nNSS packets: "); + for (i = 0; i < IEEE80211_NSS_NUM; i++) + len += scnprintf(buf + len, size - len, "\t%s: %llu", + nss_str[i], sta->rx_nss_pkt[i]); + + len += scnprintf(buf + len, size - len, "\n\nGI packets: "); + for (i = 0; i < IEEE80211_GI_NUM; i++) + len += scnprintf(buf + len, size - len, "\t%s: %llu", + gi_str[i], sta->rx_gi_pkt[i]); + + len += scnprintf(buf + len, size - len, "\n\nLegacy rate packets: "); + for (i = 0; i < IEEE80211_LEGACY_RATE_NUM; i++) { + len += scnprintf(buf + len, size - len, "\t%sMbps: %llu", + legacy_str[i], sta->rx_legacy_pkt[i]); + RX_STATS_HIST_FMT(4); + } + + len += scnprintf(buf + len, size - len, "\nRate table packets: "); + for (i = 0; i < IEEE80211_RATE_TABLE_NUM; i++) { + len += scnprintf(buf + len, size - len, "\t%llu", + sta->rx_rate_pkt[i]); + RX_STATS_HIST_FMT(8); + } + + len += scnprintf(buf + len, size - len, "\nVHT MCS bytes: "); + for (i = 0; i < IEEE80211_VHT_MCS_NUM; i++) { + len += scnprintf(buf + len, size - len, "MCS %d: %llu, ", + i, sta->rx_vht_byte[i]); + RX_STATS_HIST_FMT(5); + } + + len += scnprintf(buf + len, size - len, "\nHT MCS bytes: "); + for (i = 0; i < IEEE80211_HT_MCS_NUM; i++) { + len += scnprintf(buf + len, size - len, "MCS %d: %llu, ", + i, sta->rx_ht_byte[i]); + RX_STATS_HIST_FMT(5); + } + + len += scnprintf(buf + len, size - len, "\n\nNSS bytes: "); + for (i = 0; i < IEEE80211_NSS_NUM; i++) + len += scnprintf(buf + len, size - len, "\t%s: %llu", + nss_str[i], sta->rx_nss_byte[i]); + + len += scnprintf(buf + len, size - len, "\n\nBW bytes: "); + for (i = 0; i < IEEE80211_BW_NUM; i++) + len += scnprintf(buf + len, size - len, "\t%sMhz: %llu", + bw_str[i], sta->rx_bw_byte[i]); + + len += scnprintf(buf + len, size - len, "\n\nGI bytes: "); + for (i = 0; i < IEEE80211_GI_NUM; i++) + len += scnprintf(buf + len, size - len, "\t%s: %llu", + gi_str[i], sta->rx_gi_byte[i]); + + len += scnprintf(buf + len, size - len, "\n\nLegacy rate bytes: "); + for (i = 0; i < IEEE80211_LEGACY_RATE_NUM; i++) { + len += scnprintf(buf + len, size - len, "\t%sMbps: %llu", + legacy_str[i], sta->rx_legacy_byte[i]); + RX_STATS_HIST_FMT(4); + } + + len += scnprintf(buf + len, size - len, "\nRate table bytes: "); + for (i = 0; i < IEEE80211_RATE_TABLE_NUM; i++) { + len += scnprintf(buf + len, size - len, "\t%llu", + sta->rx_rate_byte[i]); + RX_STATS_HIST_FMT(8); + } + + if (len > size) + len = size; + retval = simple_read_from_buffer(userbuf, count, ppos, buf, len); + kfree(buf); + +#undef RX_STATS_HIST_FMT + return retval; +#endif + return -EINVAL; +} +STA_OPS(rx_stats); + static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -332,6 +456,106 @@ STA_OPS(vht_capa); debugfs_create_u64(#name, 0400, sta->debugfs.dir, \ (u64 *) &sta->field); +#ifdef CONFIG_MAC80211_DEBUG_PER_STA_RX_STATS +static int legacy_rate_to_index(u16 rate) +{ + int legacy_rate[] = {10, 20, 55, 110, 60, 90, 120, + 180, 240, 360, 480, 540}; + int i; + + for (i = 0; i < IEEE80211_LEGACY_RATE_NUM - 1; i++) + if (rate == legacy_rate[i]) + return i; + return -1; +} +#endif + +void ieee80211_rx_h_sta_stats(struct sta_info *sta, struct sk_buff *skb) +{ +#ifdef CONFIG_MAC80211_DEBUG_PER_STA_RX_STATS + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + unsigned int pkt_len = skb->len; + unsigned int bw_idx, gi_idx, mcs_idx = 0, nss_idx = 0, i; + + /* Not support 5Mhz and 10Mhz currently */ + if (status->flag & (RX_FLAG_5MHZ | RX_FLAG_10MHZ)) + goto out; + + if (status->vht_flag & RX_VHT_FLAG_160MHZ) + bw_idx = 3; + else if (status->vht_flag & RX_VHT_FLAG_80MHZ) + bw_idx = 2; + else if (status->flag & RX_FLAG_40MHZ) + bw_idx = 1; + else + bw_idx = 0; + + if (status->flag & RX_FLAG_HT) { + mcs_idx = status->rate_idx; + nss_idx = (mcs_idx >> 3) - 1; + + if (status->rate_idx > IEEE80211_HT_MCS_NUM - 1 || + nss_idx > IEEE80211_NSS_NUM - 1) + goto out; + + sta->rx_ht_pkt[mcs_idx]++; + sta->rx_ht_byte[mcs_idx] += pkt_len; + sta->rx_nss_pkt[nss_idx]++; + sta->rx_nss_byte[nss_idx] += pkt_len; + /* To fit into rate table for HT packets */ + mcs_idx = mcs_idx % 8; + } else if (status->flag & RX_FLAG_VHT) { + mcs_idx = status->rate_idx; + nss_idx = status->vht_nss - 1; + + if (nss_idx > IEEE80211_NSS_NUM - 1 || + mcs_idx > (IEEE80211_VHT_MCS_NUM - 1)) + goto out; + + sta->rx_vht_pkt[mcs_idx]++; + sta->rx_vht_byte[mcs_idx] += pkt_len; + sta->rx_nss_pkt[nss_idx]++; + sta->rx_nss_byte[nss_idx] += pkt_len; + } + + gi_idx = (status->flag & RX_FLAG_SHORT_GI) ? 1 : 0; + sta->rx_gi_pkt[gi_idx]++; + sta->rx_gi_byte[gi_idx] += pkt_len; + sta->rx_bw_pkt[bw_idx]++; + sta->rx_bw_byte[bw_idx] += pkt_len; + + if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) { + /* Update Rate table based on http://mcsindex.com/ */ + i = mcs_idx * 8 + 8 * 10 * nss_idx; + i += bw_idx * 2 + gi_idx; + sta->rx_rate_pkt[i]++; + sta->rx_rate_byte[i] += pkt_len; + } else { + struct ieee80211_local *local = sta->local; + struct ieee80211_sub_if_data *sdata = sta->sdata; + enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + struct ieee80211_supported_band *sband; + int shift = ieee80211_vif_get_shift(&sta->sdata->vif); + u16 brate, legacy_rate; + + if (status->rate_idx > IEEE80211_LEGACY_RATE_NUM - 1) + goto out; + + sband = local->hw.wiphy->bands[band]; + brate = sband->bitrates[status->rate_idx].bitrate; + legacy_rate = DIV_ROUND_UP(brate, 1 << shift); + i = legacy_rate_to_index(legacy_rate); + if (i < 0) + goto out; + + sta->rx_legacy_pkt[i]++; + sta->rx_legacy_byte[i] += pkt_len; + } +out: + return; +#endif +} + void ieee80211_sta_debugfs_add(struct sta_info *sta) { struct ieee80211_local *local = sta->local; @@ -365,6 +589,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) DEBUGFS_ADD(agg_status); DEBUGFS_ADD(ht_capa); DEBUGFS_ADD(vht_capa); + DEBUGFS_ADD(rx_stats); DEBUGFS_ADD_COUNTER(rx_duplicates, rx_stats.num_duplicates); DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments); diff --git a/net/mac80211/debugfs_sta.h b/net/mac80211/debugfs_sta.h index 8b60890..c7a3424 100644 --- a/net/mac80211/debugfs_sta.h +++ b/net/mac80211/debugfs_sta.h @@ -6,9 +6,14 @@ #ifdef CONFIG_MAC80211_DEBUGFS void ieee80211_sta_debugfs_add(struct sta_info *sta); void ieee80211_sta_debugfs_remove(struct sta_info *sta); +void ieee80211_rx_h_sta_stats(struct sta_info *sta, struct sk_buff *skb); #else static inline void ieee80211_sta_debugfs_add(struct sta_info *sta) {} static inline void ieee80211_sta_debugfs_remove(struct sta_info *sta) {} +static inline void ieee80211_rx_h_sta_stats(struct sta_info *sta, + struct sk_buff *skb) +{ +} #endif #endif /* __MAC80211_DEBUGFS_STA_H */ diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index bc08185..c5e8559 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -31,6 +31,7 @@ #include "tkip.h" #include "wme.h" #include "rate.h" +#include "debugfs_sta.h" static inline void ieee80211_rx_stats(struct net_device *dev, u32 len) { @@ -1421,6 +1422,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) sta->rx_stats.last_rate_flag = status->flag; sta->rx_stats.last_rate_vht_flag = status->vht_flag; sta->rx_stats.last_rate_vht_nss = status->vht_nss; + ieee80211_rx_h_sta_stats(sta, skb); } } diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index d605162..2c0d806 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -248,6 +248,13 @@ struct sta_ampdu_mlme { #define IEEE80211_FAST_XMIT_MAX_IV 18 +#define IEEE80211_HT_MCS_NUM 32 +#define IEEE80211_VHT_MCS_NUM 10 +#define IEEE80211_BW_NUM 4 +#define IEEE80211_NSS_NUM 4 +#define IEEE80211_GI_NUM 2 +#define IEEE80211_RATE_TABLE_NUM 320 +#define IEEE80211_LEGACY_RATE_NUM 12 /** * struct ieee80211_fast_tx - TX fastpath information * @key: key to use for hw crypto @@ -495,6 +502,22 @@ struct sta_info { struct cfg80211_chan_def tdls_chandef; +#ifdef CONFIG_MAC80211_DEBUG_PER_STA_RX_STATS + u64 rx_legacy_pkt[IEEE80211_LEGACY_RATE_NUM]; + u64 rx_ht_pkt[IEEE80211_HT_MCS_NUM]; + u64 rx_vht_pkt[IEEE80211_VHT_MCS_NUM]; + u64 rx_bw_pkt[IEEE80211_BW_NUM]; + u64 rx_nss_pkt[IEEE80211_NSS_NUM]; + u64 rx_gi_pkt[IEEE80211_GI_NUM]; + u64 rx_rate_pkt[IEEE80211_RATE_TABLE_NUM]; + u64 rx_legacy_byte[IEEE80211_LEGACY_RATE_NUM]; + u64 rx_ht_byte[IEEE80211_HT_MCS_NUM]; + u64 rx_vht_byte[IEEE80211_VHT_MCS_NUM]; + u64 rx_bw_byte[IEEE80211_BW_NUM]; + u64 rx_nss_byte[IEEE80211_NSS_NUM]; + u64 rx_gi_byte[IEEE80211_GI_NUM]; + u64 rx_rate_byte[IEEE80211_RATE_TABLE_NUM]; +#endif /* keep last! */ struct ieee80211_sta sta; };