Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: provide per-TID RX/TX MSDU counters

Implement the new counters cfg80211 can now advertise to userspace.
The TX code is in the sequence number handler, which is a bit odd,
but that place already knows the TID and frame type, so it was
easiest and least impact there.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>

+68 -2
+9
net/mac80211/rx.c
··· 2314 2314 if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) 2315 2315 return RX_DROP_MONITOR; 2316 2316 2317 + if (rx->sta) { 2318 + /* The security index has the same property as needed 2319 + * for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS 2320 + * for non-QoS-data frames. Here we know it's a data 2321 + * frame, so count MSDUs. 2322 + */ 2323 + rx->sta->rx_msdu[rx->security_idx]++; 2324 + } 2325 + 2317 2326 /* 2318 2327 * Send unexpected-4addr-frame event to hostapd. For older versions, 2319 2328 * also drop the frame to cooked monitor interfaces.
+31
net/mac80211/sta_info.c
··· 1843 1843 sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE); 1844 1844 } 1845 1845 1846 + sinfo->filled |= BIT(NL80211_STA_INFO_TID_STATS); 1847 + for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 1848 + struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i]; 1849 + 1850 + if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) { 1851 + tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU); 1852 + tidstats->rx_msdu = sta->rx_msdu[i]; 1853 + } 1854 + 1855 + if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) { 1856 + tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU); 1857 + tidstats->tx_msdu = sta->tx_msdu[i]; 1858 + } 1859 + 1860 + if (!(tidstats->filled & 1861 + BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) && 1862 + local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { 1863 + tidstats->filled |= 1864 + BIT(NL80211_TID_STATS_TX_MSDU_RETRIES); 1865 + tidstats->tx_msdu_retries = sta->tx_msdu_retries[i]; 1866 + } 1867 + 1868 + if (!(tidstats->filled & 1869 + BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) && 1870 + local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { 1871 + tidstats->filled |= 1872 + BIT(NL80211_TID_STATS_TX_MSDU_FAILED); 1873 + tidstats->tx_msdu_failed = sta->tx_msdu_failed[i]; 1874 + } 1875 + } 1876 + 1846 1877 if (ieee80211_vif_is_mesh(&sdata->vif)) { 1847 1878 #ifdef CONFIG_MAC80211_MESH 1848 1879 sinfo->filled |= BIT(NL80211_STA_INFO_LLID) |
+12
net/mac80211/sta_info.h
··· 346 346 * @cipher_scheme: optional cipher scheme for this station 347 347 * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed 348 348 * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED) 349 + * @tx_msdu: MSDUs transmitted to this station, using IEEE80211_NUM_TID 350 + * entry for non-QoS frames 351 + * @tx_msdu_retries: MSDU retries for transmissions to to this station, 352 + * using IEEE80211_NUM_TID entry for non-QoS frames 353 + * @tx_msdu_failed: MSDU failures for transmissions to to this station, 354 + * using IEEE80211_NUM_TID entry for non-QoS frames 355 + * @rx_msdu: MSDUs received from this station, using IEEE80211_NUM_TID 356 + * entry for non-QoS frames 349 357 */ 350 358 struct sta_info { 351 359 /* General information, mostly static */ ··· 424 416 u32 last_rx_rate_vht_flag; 425 417 u8 last_rx_rate_vht_nss; 426 418 u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; 419 + u64 tx_msdu[IEEE80211_NUM_TIDS + 1]; 420 + u64 tx_msdu_retries[IEEE80211_NUM_TIDS + 1]; 421 + u64 tx_msdu_failed[IEEE80211_NUM_TIDS + 1]; 422 + u64 rx_msdu[IEEE80211_NUM_TIDS + 1]; 427 423 428 424 /* 429 425 * Aggregation information, locked with lock.
+13 -2
net/mac80211/status.c
··· 730 730 struct ieee80211_bar *bar; 731 731 int rtap_len; 732 732 int shift = 0; 733 + int tid = IEEE80211_NUM_TIDS;; 733 734 734 735 rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); 735 736 ··· 774 773 775 774 if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && 776 775 (ieee80211_is_data_qos(fc))) { 777 - u16 tid, ssn; 776 + u16 ssn; 778 777 u8 *qc; 779 778 780 779 qc = ieee80211_get_qos_ctl(hdr); ··· 783 782 & IEEE80211_SCTL_SEQ); 784 783 ieee80211_send_bar(&sta->sdata->vif, hdr->addr1, 785 784 tid, ssn); 785 + } else if (ieee80211_is_data_qos(fc)) { 786 + u8 *qc = ieee80211_get_qos_ctl(hdr); 787 + 788 + tid = qc[0] & 0xf; 786 789 } 787 790 788 791 if (!acked && ieee80211_is_back_req(fc)) { 789 - u16 tid, control; 792 + u16 control; 790 793 791 794 /* 792 795 * BAR failed, store the last SSN and retry sending ··· 818 813 if (!acked) 819 814 sta->tx_retry_failed++; 820 815 sta->tx_retry_count += retry_count; 816 + 817 + if (ieee80211_is_data_present(fc)) { 818 + if (!acked) 819 + sta->tx_msdu_failed[tid]++; 820 + sta->tx_msdu_retries[tid] += retry_count; 821 + } 821 822 } 822 823 823 824 rate_control_tx_status(local, sband, sta, skb);
+3
net/mac80211/tx.c
··· 815 815 /* for pure STA mode without beacons, we can do it */ 816 816 hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); 817 817 tx->sdata->sequence_number += 0x10; 818 + if (tx->sta) 819 + tx->sta->tx_msdu[IEEE80211_NUM_TIDS]++; 818 820 return TX_CONTINUE; 819 821 } 820 822 ··· 833 831 qc = ieee80211_get_qos_ctl(hdr); 834 832 tid = *qc & IEEE80211_QOS_CTL_TID_MASK; 835 833 seq = &tx->sta->tid_seq[tid]; 834 + tx->sta->tx_msdu[tid]++; 836 835 837 836 hdr->seq_ctrl = cpu_to_le16(*seq); 838 837