mac80211: Fix station rx-packets counters.
Subsystems (2)
PATCH v2 1/6 mac80211: Fix station rx-packets counters.
From: Ben Greear <[email protected]>
I noticed 'iw dev wlan6 station dump' showed almost no rx-packets one one of my radios. The rx-amsdu path did not appear to gather any stats, and after code inspection, neither did the rx-data handler.
Add common method to deal with these stats. Verified in AX and /a mode, stats look at least generally correct now.
--- net/mac80211/rx.c | 54 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 17 deletions(-)
net/mac80211/rx.c +37 -17
@@ -1713,6 +1713,27 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)return RX_CONTINUE ; } +static void ieee80211_update_data_rx_stats (struct ieee80211_rx_data *rx, +struct ieee80211_sta_rx_stats *stats, +struct ieee80211_rx_status *status, +int skb_len) +{ + stats->fragments++; + stats->packets++; + stats->last_rx = jiffies; + stats->last_rate =sta_stats_encode_rate (status); + +/* The seqno index has the same property as needed +* for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS +* for non-QoS-data frames. Here we know it's a data +* frame, so count MSDUs. +*/ +u64_stats_update_begin (&stats->syncp); + stats->msdu[rx->seqno_idx]++; + stats->bytes += skb_len; +u64_stats_update_end (&stats->syncp); +} + static ieee80211_rx_result debug_noinlineieee80211_rx_h_sta_process (struct ieee80211_rx_data *rx) {
@@ -2706,6 +2727,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (skb);struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;__le16 fc = hdr->frame_control; +ieee80211_rx_result rv; +int orig_len = skb->len;if (!(status->rx_flags &IEEE80211_RX_AMSDU ))return RX_CONTINUE ;
@@ -2734,7 +2757,12 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)if (is_multicast_ether_addr (hdr->addr1))return RX_DROP_UNUSABLE ; -return __ieee80211_rx_h_amsdu (rx,0 ); + rv =__ieee80211_rx_h_amsdu (rx,0 ); +if ((rv ==RX_QUEUED ) && (rx->sta)) { +struct ieee80211_sta_rx_stats *stats = &rx->sta->rx_stats; +ieee80211_update_data_rx_stats (rx, stats, status, orig_len); + } +return rv; }#ifdef CONFIG_MAC80211_MESH
@@ -2958,6 +2986,13 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)mod_timer (&local->dynamic_ps_timer, jiffies +msecs_to_jiffies (local->hw.conf.dynamic_ps_timeout)); + +if (rx->sta) { +struct ieee80211_sta_rx_stats *stats = &rx->sta->rx_stats; +struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (rx->skb); +ieee80211_update_data_rx_stats (rx, stats, status, rx->skb->len); + } +ieee80211_deliver_skb (rx);return RX_QUEUED ;
@@ -4400,12 +4435,6 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,return true; } - stats->last_rx = jiffies; - stats->last_rate =sta_stats_encode_rate (status); - - stats->fragments++; - stats->packets++; -/* do the header conversion - first grab the addresses */ ether_addr_copy (addrs.da, skb->data + fast_rx->da_offs);ether_addr_copy (addrs.sa, skb->data + fast_rx->sa_offs);
@@ -4416,18 +4445,9 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, skb->dev = fast_rx->dev; +ieee80211_update_data_rx_stats (rx, stats, status, orig_len);dev_sw_netstats_rx_add (fast_rx->dev, skb->len); -/* The seqno index has the same property as needed -* for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS -* for non-QoS-data frames. Here we know it's a data -* frame, so count MSDUs. -*/ -u64_stats_update_begin (&stats->syncp); - stats->msdu[rx->seqno_idx]++; - stats->bytes += orig_len; -u64_stats_update_end (&stats->syncp); -if (fast_rx->internal_forward) {struct sk_buff *xmit_skb =NULL ;if (is_multicast_ether_addr (addrs.da)) {
Signature · 1 line
2.20.1
PATCH v2 2/6 mac80211: Provide per-station stats in debugfs
From: Ben Greear <[email protected]>
Including per tid and per acs stats.
Nice for those who like to peer deep into the guts of a system.
--- net/mac80211/debugfs_sta.c | 88 ++++++++++++++++++++++++++++++++++++++ net/mac80211/sta_info.c | 33 ++++++++++++++ net/mac80211/sta_info.h | 4 ++ 3 files changed, 125 insertions(+)
net/mac80211/debugfs_sta.c +88 -0
@@ -102,6 +102,93 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, }STA_OPS (flags); +static ssize_t sta_stats_read (struct file *file,char __user *userbuf, +size_t count,loff_t *ppos) +{ +struct sta_info *sta = file->private_data; +unsigned int len =0 ; +const int buf_len =8000 ; +char *buf =kzalloc (buf_len,GFP_KERNEL ); +unsigned long sum; +char tmp[60 ]; +int i; +struct ieee80211_sta_rx_stats rx_stats = {0 }; + +if (!buf) +return -ENOMEM ; + +sta_accum_rx_stats (sta, &rx_stats); + +#define PRINT_MY_STATS (a, b) do { \ + len += scnprintf(buf + len, buf_len - len, "%30s %18lu\n", a, (unsigned long)(b)); \ + if (len >= buf_len) { \ + goto done; \ + } \ + } while (0) + +#define PRINT_MY_STATS_S (a, b) do { \ + len += scnprintf(buf + len, buf_len - len, "%30s %18ld\n", a, (long)(b)); \ + if (len >= buf_len) { \ + goto done; \ + } \ + } while (0) + +PRINT_MY_STATS ("rx-packets" , rx_stats.packets); +PRINT_MY_STATS ("rx-bytes" , rx_stats.bytes); +PRINT_MY_STATS ("rx-dup" , rx_stats.num_duplicates); +PRINT_MY_STATS ("rx-fragments" , rx_stats.fragments); +PRINT_MY_STATS ("rx-dropped" , rx_stats.dropped); +PRINT_MY_STATS_S ("rx-last-signal" , rx_stats.last_signal); + +for (i =0 ; i<IEEE80211_MAX_CHAINS ; i++) { +if (rx_stats.chains & (1 <<i)) { +sprintf (tmp,"rx-last-signal-chain[%i]" , i); +PRINT_MY_STATS_S (tmp, rx_stats.chain_signal_last[i]); + } + } +PRINT_MY_STATS ("rx-last-rate-encoded" , rx_stats.last_rate); + + len +=scnprintf (buf + len, buf_len - len,"\n" ); + + sum = sta->tx_stats.packets[0 ] + sta->tx_stats.packets[1 ] + + sta->tx_stats.packets[2 ] + sta->tx_stats.packets[3 ]; +PRINT_MY_STATS ("tx-packets" , sum); + + sum = sta->tx_stats.bytes[0 ] + sta->tx_stats.bytes[1 ] + + sta->tx_stats.bytes[2 ] + sta->tx_stats.bytes[3 ]; +PRINT_MY_STATS ("tx-bytes" , sum); + +/* per txq stats */ +PRINT_MY_STATS ("tx-packets-acs[VO]" , sta->tx_stats.packets[IEEE80211_AC_VO ]); +PRINT_MY_STATS ("tx-packets-acs[VI]" , sta->tx_stats.packets[IEEE80211_AC_VI ]); +PRINT_MY_STATS ("tx-packets-acs[BE]" , sta->tx_stats.packets[IEEE80211_AC_BE ]); +PRINT_MY_STATS ("tx-packets-acs[BK]" , sta->tx_stats.packets[IEEE80211_AC_BK ]); + +PRINT_MY_STATS ("tx-bytes-acs[VO]" , sta->tx_stats.bytes[IEEE80211_AC_VO ]); +PRINT_MY_STATS ("tx-bytes-acs[VI]" , sta->tx_stats.bytes[IEEE80211_AC_VI ]); +PRINT_MY_STATS ("tx-bytes-acs[BE]" , sta->tx_stats.bytes[IEEE80211_AC_BE ]); +PRINT_MY_STATS ("tx-bytes-acs[BK]" , sta->tx_stats.bytes[IEEE80211_AC_BK ]); + + len +=scnprintf (buf + len, buf_len - len,"\n" ); +for (i =0 ; i<=IEEE80211_NUM_TIDS ; i++) { +sprintf (tmp,"tx-msdu-tid[%2i]" , i); +PRINT_MY_STATS (tmp, sta->tx_stats.msdu[i]); + } + + len +=scnprintf (buf + len, buf_len - len,"\n" ); +for (i =0 ; i<=IEEE80211_NUM_TIDS ; i++) { +sprintf (tmp,"rx-msdu-tid[%2i]" , i); +PRINT_MY_STATS (tmp, rx_stats.msdu[i]); + } + +#undef PRINT_MY_STATS +done: + i =simple_read_from_buffer (userbuf, count, ppos, buf,strlen (buf)); +kfree (buf); +return i; +} +STA_OPS (stats); +static ssize_t sta_num_ps_buf_frames_read (struct file *file,char __user *userbuf,size_t count,loff_t *ppos)
@@ -1073,6 +1160,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) sta->debugfs_dir =debugfs_create_dir (mac, stations_dir);DEBUGFS_ADD (flags); +DEBUGFS_ADD (stats);DEBUGFS_ADD (aid);DEBUGFS_ADD (num_ps_buf_frames);DEBUGFS_ADD (last_seq_ctrl);
net/mac80211/sta_info.c +33 -0
@@ -2650,6 +2650,39 @@ static void sta_update_codel_params(struct sta_info *sta, u32 thr) } } +void sta_accum_rx_stats (struct sta_info *sta, +struct ieee80211_sta_rx_stats *rx_stats) +{ +int cpu; +int i; + +memcpy (rx_stats, &sta->rx_stats,sizeof (*rx_stats)); + +if (!sta->pcpu_rx_stats) +return ; + +for_each_possible_cpu (cpu) { +struct ieee80211_sta_rx_stats *cpurxs; + + cpurxs =per_cpu_ptr (sta->pcpu_rx_stats, cpu); + rx_stats->packets += cpurxs->packets; +if (time_after (cpurxs->last_rx, rx_stats->last_rx)) { + rx_stats->last_rx = cpurxs->last_rx; + rx_stats->last_signal = cpurxs->last_signal; +for (i =0 ; i<IEEE80211_MAX_CHAINS ; i++) + rx_stats->chain_signal_last[i] = cpurxs->chain_signal_last[i]; + rx_stats->last_rate = cpurxs->last_rate; + } + rx_stats->num_duplicates += cpurxs->num_duplicates; + rx_stats->fragments += cpurxs->fragments; + rx_stats->dropped += cpurxs->dropped; + rx_stats->bytes +=sta_get_stats_bytes (cpurxs); +for (i =0 ; i<=IEEE80211_NUM_TIDS ; i++) { + rx_stats->msdu[i] +=sta_get_tidstats_msdu (cpurxs, i); + } + } +} +void ieee80211_sta_set_expected_throughput (struct ieee80211_sta *pubsta,u32 thr) {
net/mac80211/sta_info.h +4 -0
@@ -422,6 +422,7 @@ struct mesh_sta {DECLARE_EWMA (signal,10 ,8 ) +/* Update sta_accum_rx_stats if you change this structure. */struct ieee80211_sta_rx_stats {unsigned long packets;unsigned long last_rx;
@@ -907,4 +908,7 @@ static inline u32 sta_stats_encode_rate(struct ieee80211_rx_status *s) return r; } +void sta_accum_rx_stats (struct sta_info *sta, +struct ieee80211_sta_rx_stats *rx_stats); +#endif /* STA_INFO_H */
Signature · 1 line
2.20.1
PATCH v2 3/6 mac80211: Provide detailed station rx stats.
In reply to [email protected]From: Ben Greear <[email protected]>
This provides histograms of different encoding types, nss, rate-idx, and some ofdma related stats. The goal is general visibility into what is going on with rate control, ofdma, etc.
--- include/uapi/linux/nl80211.h | 1 + net/mac80211/Kconfig | 11 ++++++++ net/mac80211/debugfs_sta.c | 30 ++++++++++++++++++++ net/mac80211/rx.c | 55 ++++++++++++++++++++++++++++++++++++ net/mac80211/sta_info.c | 16 +++++++++++ net/mac80211/sta_info.h | 17 +++++++++++ 6 files changed, 130 insertions(+)
include/uapi/linux/nl80211.h +1 -0
@@ -3269,6 +3269,7 @@ enum nl80211_he_ru_alloc {NL80211_RATE_INFO_HE_RU_ALLOC_484 ,NL80211_RATE_INFO_HE_RU_ALLOC_996 , NL80211_RATE_INFO_HE_RU_ALLOC_2x996, + NL80211_RATE_INFO_HE_RU_ALLOC_LAST /* new entries before this */ };/**
net/mac80211/Kconfig +11 -0
@@ -295,6 +295,17 @@ config MAC80211_DEBUG_COUNTERS If unsure, say N. +config MAC80211_DEBUG_STA_COUNTERS + bool "Extra Station TX/RX statistics" + depends on MAC80211_DEBUG_MENU + depends on MAC80211_DEBUGFS + help + Selecting this option causes mac80211 to keep additional + and very verbose station-specific TX and RX statistics + These will be exposed in debugfs. + + If unsure, say N. + config MAC80211_STA_HASH_MAX_SIZE int "Station hash table maximum size" if MAC80211_DEBUG_MENU default 0
net/mac80211/debugfs_sta.c +30 -0
@@ -181,6 +181,36 @@ static ssize_t sta_stats_read(struct file *file, char __user *userbuf,PRINT_MY_STATS (tmp, rx_stats.msdu[i]); } +#ifdef CONFIG_MAC80211_DEBUG_STA_COUNTERS +PRINT_MY_STATS ("rx-bw-20" , rx_stats.msdu_20); +PRINT_MY_STATS ("rx-bw-40" , rx_stats.msdu_40); +PRINT_MY_STATS ("rx-bw-80" , rx_stats.msdu_80); +PRINT_MY_STATS ("rx-bw-160" , rx_stats.msdu_160); + +PRINT_MY_STATS ("rx-he-total" , rx_stats.msdu_he_tot); +PRINT_MY_STATS ("rx-vht" , rx_stats.msdu_vht); +PRINT_MY_STATS ("rx-ht" , rx_stats.msdu_ht); +PRINT_MY_STATS ("rx-legacy" , rx_stats.msdu_legacy); + +PRINT_MY_STATS ("rx-he-ru-alloc[ 26]" , rx_stats.msdu_he_ru_alloc[NL80211_RATE_INFO_HE_RU_ALLOC_26 ]); +PRINT_MY_STATS ("rx-he-ru-alloc[ 52]" , rx_stats.msdu_he_ru_alloc[NL80211_RATE_INFO_HE_RU_ALLOC_52 ]); +PRINT_MY_STATS ("rx-he-ru-alloc[ 106]" , rx_stats.msdu_he_ru_alloc[NL80211_RATE_INFO_HE_RU_ALLOC_106 ]); +PRINT_MY_STATS ("rx-he-ru-alloc[ 242]" , rx_stats.msdu_he_ru_alloc[NL80211_RATE_INFO_HE_RU_ALLOC_242 ]); +PRINT_MY_STATS ("rx-he-ru-alloc[ 484]" , rx_stats.msdu_he_ru_alloc[NL80211_RATE_INFO_HE_RU_ALLOC_484 ]); +PRINT_MY_STATS ("rx-he-ru-alloc[ 996]" , rx_stats.msdu_he_ru_alloc[NL80211_RATE_INFO_HE_RU_ALLOC_996 ]); +PRINT_MY_STATS ("rx-he-ru-alloc[2x996]" , rx_stats.msdu_he_ru_alloc[NL80211_RATE_INFO_HE_RU_ALLOC_2x996]); + +for (i =0 ; i <ARRAY_SIZE (rx_stats.msdu_nss); i++) { +sprintf (tmp,"rx-msdu-nss[%i]" , i); +PRINT_MY_STATS (tmp, rx_stats.msdu_nss[i]); + } + +for (i =0 ; i <ARRAY_SIZE (rx_stats.msdu_rate_idx); i++) { +sprintf (tmp,"rx-rate-idx[%3i]" , i); +PRINT_MY_STATS (tmp, rx_stats.msdu_rate_idx[i]); + } +#endif +#undef PRINT_MY_STATS done: i =simple_read_from_buffer (userbuf, count, ppos, buf,strlen (buf));
net/mac80211/rx.c +55 -0
67 lines not on this page · raw message
net/mac80211/sta_info.c +16 -0
@@ -2680,6 +2680,22 @@ void sta_accum_rx_stats(struct sta_info *sta,for (i =0 ; i<=IEEE80211_NUM_TIDS ; i++) { rx_stats->msdu[i] +=sta_get_tidstats_msdu (cpurxs, i); } +#ifdef CONFIG_MAC80211_DEBUG_STA_COUNTERS + rx_stats->msdu_20 += cpurxs->msdu_20; + rx_stats->msdu_40 += cpurxs->msdu_40; + rx_stats->msdu_80 += cpurxs->msdu_80; + rx_stats->msdu_160 += cpurxs->msdu_160; +for (i =0 ; i<NL80211_RATE_INFO_HE_RU_ALLOC_LAST ; i++) + rx_stats->msdu_he_ru_alloc[i] += cpurxs->msdu_he_ru_alloc[i]; + rx_stats->msdu_he_tot += cpurxs->msdu_he_tot; + rx_stats->msdu_vht += cpurxs->msdu_vht; + rx_stats->msdu_ht += cpurxs->msdu_ht; + rx_stats->msdu_legacy += cpurxs->msdu_legacy; +for (i =0 ; i <ARRAY_SIZE (rx_stats->msdu_nss); i++) + rx_stats->msdu_nss[i] += cpurxs->msdu_nss[i]; +for (i =0 ; i <ARRAY_SIZE (rx_stats->msdu_rate_idx); i++) + rx_stats->msdu_rate_idx[i] += cpurxs->msdu_rate_idx[i]; +#endif } }
net/mac80211/sta_info.h +17 -0
@@ -436,6 +436,23 @@ struct ieee80211_sta_rx_stats {struct u64_stats_sync syncp;u64 bytes;u64 msdu[IEEE80211_NUM_TIDS +1 ]; + +#ifdef CONFIG_MAC80211_DEBUG_STA_COUNTERS +/* these take liberty with how things are defined, and are +* designed to give a rough idea of how things are going. +*/ +u32 msdu_20; +u32 msdu_40; +u32 msdu_80; +u32 msdu_160; +u32 msdu_he_ru_alloc[NL80211_RATE_INFO_HE_RU_ALLOC_LAST ]; +u32 msdu_he_tot; +u32 msdu_vht; +u32 msdu_ht; +u32 msdu_legacy; +u32 msdu_nss[8 ]; +u32 msdu_rate_idx[13 ]; +#endif };/*
Signature · 1 line
2.20.1
PATCH v2 4/6 mac80211: Add counters for specific HE encoding types.
In reply to [email protected]From: Ben Greear <[email protected]>
So we can get counters of SU, SU-EXT, MU, Trigger frame types. Drivers use a convoluted way to pass this up the stack, encoding the info in radiotap headers prepended on the skb. So, do a bit of hopefully-correct math to find the radiotap_he header again in mac80211 and store it for stats gathering. This only applies if you have enabled verbose mac80211 station stats.
--- net/mac80211/debugfs_sta.c | 4 ++++ net/mac80211/ieee80211_i.h | 5 +++++ net/mac80211/rx.c | 39 +++++++++++++++++++++++++++++++++----- net/mac80211/sta_info.c | 4 ++++ net/mac80211/sta_info.h | 4 ++++ 5 files changed, 51 insertions(+), 5 deletions(-)
net/mac80211/debugfs_sta.c +4 -0
@@ -188,6 +188,10 @@ static ssize_t sta_stats_read(struct file *file, char __user *userbuf,PRINT_MY_STATS ("rx-bw-160" , rx_stats.msdu_160);PRINT_MY_STATS ("rx-he-total" , rx_stats.msdu_he_tot); +PRINT_MY_STATS ("rx-he-su" , rx_stats.msdu_he_su); +PRINT_MY_STATS ("rx-he-ext-su" , rx_stats.msdu_he_ext_su); +PRINT_MY_STATS ("rx-he-mu" , rx_stats.msdu_he_mu); +PRINT_MY_STATS ("rx-he-trigger" , rx_stats.msdu_he_trigger);PRINT_MY_STATS ("rx-vht" , rx_stats.msdu_vht);PRINT_MY_STATS ("rx-ht" , rx_stats.msdu_ht);PRINT_MY_STATS ("rx-legacy" , rx_stats.msdu_legacy);
net/mac80211/ieee80211_i.h +5 -0
@@ -244,6 +244,11 @@ struct ieee80211_rx_data {u32 tkip_iv32;u16 tkip_iv16; + +#ifdef CONFIG_MAC80211_DEBUG_STA_COUNTERS +/* for stats gathering */ +struct ieee80211_radiotap_he radiotap_he; +#endif };struct ieee80211_csa_settings {
net/mac80211/rx.c +34 -5
@@ -735,8 +735,8 @@ ieee80211_make_monitor_skb(struct ieee80211_local *local,* radiotap header the driver might have added. */ static struct sk_buff * -ieee80211_rx_monitor (struct ieee80211_local *local,struct sk_buff *origskb, -struct ieee80211_rate *rate) +ieee80211_rx_monitor (struct ieee80211_radiotap_he *radiotap_he,struct ieee80211_local *local, +struct sk_buff *origskb,struct ieee80211_rate *rate) {struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (origskb);struct ieee80211_sub_if_data *sdata;
@@ -796,6 +796,19 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,return NULL ; } +#ifdef CONFIG_MAC80211_DEBUG_STA_COUNTERS +if (status->flag &RX_FLAG_RADIOTAP_HE ) { +/* Store this for later so we can gather stats. +* This depends on drivers putting the radiotap_he header +* on the skb first. Seems all drivers do at this point. +*/ +struct ieee80211_radiotap_he *he; + he = (struct ieee80211_radiotap_he *)(origskb->data + (rtap_space -sizeof (*he))); + *radiotap_he = *he; + } +#endif + + only_monitor =should_drop_frame (origskb, present_fcs_len, rtap_space);if (!local->monitors || (status->flag &RX_FLAG_SKIP_MONITOR )) {
@@ -1763,6 +1776,17 @@ static void ieee80211_update_data_rx_stats(struct ieee80211_rx_data *rx,if (status->encoding ==RX_ENC_HE ) { stats->msdu_he_tot++; +if (status->flag &RX_FLAG_RADIOTAP_HE ) { +u8 he_type = rx->radiotap_he.data1 &0x3 ; +if (he_type ==0x0 ) + stats->msdu_he_su++; +if (he_type ==0x1 ) + stats->msdu_he_ext_su++; +if (he_type ==0x2 ) + stats->msdu_he_mu++; +if (he_type ==0x3 ) + stats->msdu_he_trigger++; + } }else if (status->encoding ==RX_ENC_VHT ) { stats->msdu_vht++;
@@ -4601,7 +4625,8 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,static void __ieee80211_rx_handle_packet (struct ieee80211_hw *hw,struct ieee80211_sta *pubsta,struct sk_buff *skb, -struct list_head *list) +struct list_head *list, +struct ieee80211_radiotap_he *radiotap_he) {struct ieee80211_local *local =hw_to_local (hw);struct ieee80211_sub_if_data *sdata;
@@ -4617,6 +4642,9 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, rx.skb = skb; rx.local = local; rx.list = list; +#ifdef CONFIG_MAC80211_DEBUG_STA_COUNTERS + rx.radiotap_he = *radiotap_he; +#endif if (ieee80211_is_data (fc) ||ieee80211_is_mgmt (fc))I802_DEBUG_INC (local->dot11ReceivedFragmentCount);
@@ -4748,6 +4776,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,struct ieee80211_rate *rate =NULL ;struct ieee80211_supported_band *sband;struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (skb); +struct ieee80211_radiotap_he radiotap_he;WARN_ON_ONCE (softirq_count () ==0 );
@@ -4841,13 +4870,13 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,* if it was previously present. * Also, frames with less than 16 bytes are dropped. */ - skb =ieee80211_rx_monitor (local, skb, rate); + skb =ieee80211_rx_monitor (&radiotap_he, local, skb, rate);if (skb) {ieee80211_tpt_led_trig_rx (local, ((struct ieee80211_hdr *)skb->data)->frame_control, skb->len); -__ieee80211_rx_handle_packet (hw, pubsta, skb, list); +__ieee80211_rx_handle_packet (hw, pubsta, skb, list, &radiotap_he); }kcov_remote_stop ();
net/mac80211/sta_info.c +4 -0
@@ -2688,6 +2688,10 @@ void sta_accum_rx_stats(struct sta_info *sta,for (i =0 ; i<NL80211_RATE_INFO_HE_RU_ALLOC_LAST ; i++) rx_stats->msdu_he_ru_alloc[i] += cpurxs->msdu_he_ru_alloc[i]; rx_stats->msdu_he_tot += cpurxs->msdu_he_tot; + rx_stats->msdu_he_su += cpurxs->msdu_he_su; + rx_stats->msdu_he_ext_su += cpurxs->msdu_he_ext_su; + rx_stats->msdu_he_mu += cpurxs->msdu_he_mu; + rx_stats->msdu_he_trigger += cpurxs->msdu_he_trigger; rx_stats->msdu_vht += cpurxs->msdu_vht; rx_stats->msdu_ht += cpurxs->msdu_ht; rx_stats->msdu_legacy += cpurxs->msdu_legacy;
net/mac80211/sta_info.h +4 -0
@@ -447,6 +447,10 @@ struct ieee80211_sta_rx_stats {u32 msdu_160;u32 msdu_he_ru_alloc[NL80211_RATE_INFO_HE_RU_ALLOC_LAST ];u32 msdu_he_tot; +u32 msdu_he_su; +u32 msdu_he_ext_su; +u32 msdu_he_mu; +u32 msdu_he_trigger;u32 msdu_vht;u32 msdu_ht;u32 msdu_legacy;
Signature · 1 line
2.20.1
PATCH v2 5/6 mac80211: Add some additional tx-stats to debugfs
In reply to [email protected]From: Ben Greear <[email protected]>
Give a better idea of TX behaviour. Currently this code does not deal with HE tx rates properly. I'm not sure exactly where to find that info, not sure that ax200 driver that I'm testing properly provides it up to the tx-status logic.
--- net/mac80211/debugfs_sta.c | 24 ++++++++++++++++++- net/mac80211/rx.c | 1 + net/mac80211/sta_info.h | 16 +++++++++++++ net/mac80211/status.c | 47 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 1 deletion(-)
net/mac80211/debugfs_sta.c +23 -1
@@ -107,7 +107,7 @@ static ssize_t sta_stats_read(struct file *file, char __user *userbuf, {struct sta_info *sta = file->private_data;unsigned int len =0 ; -const int buf_len =8000 ; +const int buf_len =12000 ;char *buf =kzalloc (buf_len,GFP_KERNEL );unsigned long sum;char tmp[60 ];
@@ -186,6 +186,7 @@ static ssize_t sta_stats_read(struct file *file, char __user *userbuf,PRINT_MY_STATS ("rx-bw-40" , rx_stats.msdu_40);PRINT_MY_STATS ("rx-bw-80" , rx_stats.msdu_80);PRINT_MY_STATS ("rx-bw-160" , rx_stats.msdu_160); +PRINT_MY_STATS ("rx-bw-he-ru" , rx_stats.msdu_he_ru);PRINT_MY_STATS ("rx-he-total" , rx_stats.msdu_he_tot);PRINT_MY_STATS ("rx-he-su" , rx_stats.msdu_he_su);
@@ -213,6 +214,27 @@ static ssize_t sta_stats_read(struct file *file, char __user *userbuf,sprintf (tmp,"rx-rate-idx[%3i]" , i);PRINT_MY_STATS (tmp, rx_stats.msdu_rate_idx[i]); } + + len +=scnprintf (buf + len, buf_len - len,"\n" ); +PRINT_MY_STATS ("tx-bw-20" , sta->tx_stats.msdu_20); +PRINT_MY_STATS ("tx-bw-40" , sta->tx_stats.msdu_40); +PRINT_MY_STATS ("tx-bw-80" , sta->tx_stats.msdu_80); +PRINT_MY_STATS ("tx-bw-160" , sta->tx_stats.msdu_160); +PRINT_MY_STATS ("tx-bw-he-ru" , sta->tx_stats.msdu_he_ru); + +PRINT_MY_STATS ("tx-vht" , sta->tx_stats.msdu_vht); +PRINT_MY_STATS ("tx-ht" , sta->tx_stats.msdu_ht); +PRINT_MY_STATS ("tx-legacy" , sta->tx_stats.msdu_legacy); + +for (i =0 ; i <ARRAY_SIZE (sta->tx_stats.msdu_nss); i++) { +sprintf (tmp,"tx-msdu-nss[%i]" , i); +PRINT_MY_STATS (tmp, sta->tx_stats.msdu_nss[i]); + } + +for (i =0 ; i <ARRAY_SIZE (sta->tx_stats.msdu_rate_idx); i++) { +sprintf (tmp,"tx-rate-idx[%3i]" , i); +PRINT_MY_STATS (tmp, sta->tx_stats.msdu_rate_idx[i]); + }#endif #undef PRINT_MY_STATS
net/mac80211/rx.c +1 -0
@@ -1767,6 +1767,7 @@ static void ieee80211_update_data_rx_stats(struct ieee80211_rx_data *rx, stats->msdu_160++;break ;case RATE_INFO_BW_HE_RU : + stats->msdu_he_ru++; stats->msdu_he_ru_alloc[status->he_ru]++;break ; };
net/mac80211/sta_info.h +16 -0
@@ -445,6 +445,7 @@ struct ieee80211_sta_rx_stats {u32 msdu_40;u32 msdu_80;u32 msdu_160; +u32 msdu_he_ru;u32 msdu_he_ru_alloc[NL80211_RATE_INFO_HE_RU_ALLOC_LAST ];u32 msdu_he_tot;u32 msdu_he_su;
@@ -636,6 +637,21 @@ struct sta_info {struct ieee80211_tx_rate last_rate;struct rate_info last_rate_info;u64 msdu[IEEE80211_NUM_TIDS +1 ]; +#ifdef CONFIG_MAC80211_DEBUG_STA_COUNTERS +/* these take liberty with how things are defined, and are +* designed to give a rough idea of how things are going. +*/ +u32 msdu_20; +u32 msdu_40; +u32 msdu_80; +u32 msdu_160; +u32 msdu_he_ru; +u32 msdu_vht; +u32 msdu_ht; +u32 msdu_legacy; +u32 msdu_nss[8 ]; +u32 msdu_rate_idx[13 ]; +#endif } tx_stats;u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK +1 ];
net/mac80211/status.c +47 -0
70 lines not on this page · raw message
Signature · 1 line
2.20.1
PATCH v2 6/6 mac80211: last_rate is 32-bit number.
In reply to [email protected]From: Ben Greear <[email protected]>
Assign it to 32-bit holding variable instead of 16 when processing the rx rate.
--- net/mac80211/sta_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mac80211/sta_info.c +1 -1
@@ -2246,7 +2246,7 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u32 rate,static int sta_set_rate_info_rx (struct sta_info *sta,struct rate_info *rinfo) { -u16 rate =READ_ONCE (sta_get_last_rx_stats (sta)->last_rate); +u32 rate =READ_ONCE (sta_get_last_rx_stats (sta)->last_rate);if (rate ==STA_STATS_RATE_INVALID )return -EINVAL ;
Signature · 1 line
2.20.1
Quoted 24 lines · On 3/24/21 11:14 AM, [email protected] wrote:
From: Ben Greear <[email protected]>
I noticed 'iw dev wlan6 station dump' showed almost no rx-packets one one of my radios. The rx-amsdu path did not appear to gather any stats, and after code inspection, neither did the rx-data handler.
Add common method to deal with these stats. Verified in AX and /a mode, stats look at least generally correct now.
Signed-off-by Ben Greear <[email protected]>---
net/mac80211/rx.c +2
-0@@ -2706,6 +2727,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (skb);struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;__le16 fc = hdr->frame_control; +ieee80211_rx_result rv; +int orig_len = skb->len;if (!(status->rx_flags &IEEE80211_RX_AMSDU ))return RX_CONTINUE ;@@ -2734,7 +2757,12 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)if (is_multicast_ether_addr (hdr->addr1))
net/mac80211/rx.c ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) · line 2766
Quoted 10 lines
net/mac80211/rx.c +6
-1return RX_DROP_UNUSABLE ; -return __ieee80211_rx_h_amsdu (rx,0 ); + rv =__ieee80211_rx_h_amsdu (rx,0 ); +if ((rv ==RX_QUEUED ) && (rx->sta)) { +struct ieee80211_sta_rx_stats *stats = &rx->sta->rx_stats; +ieee80211_update_data_rx_stats (rx, stats, status, orig_len); + } +return rv; }
I noticed this is buggy in several ways (potential use-after-free, bogus status field).
I noticed too that upcoming changes changed some API that made later patches in this series not apply cleanly..needed a bit of re-work.
Maybe best if I wait and rebase it against 5.13 when it is ready, unless someone is actually interested enough in this to want to apply it earlier?
Thanks,
Ben
Signature · 2 lines
Ben Greear <[email protected]> Candela Technologies Inc http://www.candelatech.com