diff options
author | Johannes Berg <johannes.berg@intel.com> | 2014-11-21 08:26:31 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2015-01-08 09:28:20 -0500 |
commit | 79c892b85027d5074dfa670dd451c14ee649fb88 (patch) | |
tree | b01b5e649d3d0256e5e84c886eda587b73ace6e1 | |
parent | 6de39808cf1dd7b02bf42e7d8695d80f5eaf645d (diff) |
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>
-rw-r--r-- | net/mac80211/rx.c | 9 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 31 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 12 | ||||
-rw-r--r-- | net/mac80211/status.c | 15 | ||||
-rw-r--r-- | net/mac80211/tx.c | 3 |
5 files changed, 68 insertions, 2 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fa5d870655a9..3a1a3ba40bd8 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2314,6 +2314,15 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
2314 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) | 2314 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) |
2315 | return RX_DROP_MONITOR; | 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 | * Send unexpected-4addr-frame event to hostapd. For older versions, | 2327 | * Send unexpected-4addr-frame event to hostapd. For older versions, |
2319 | * also drop the frame to cooked monitor interfaces. | 2328 | * also drop the frame to cooked monitor interfaces. |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 64b53b943d98..dc352fcdd469 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1843,6 +1843,37 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
1843 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE); | 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 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1877 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1847 | #ifdef CONFIG_MAC80211_MESH | 1878 | #ifdef CONFIG_MAC80211_MESH |
1848 | sinfo->filled |= BIT(NL80211_STA_INFO_LLID) | | 1879 | sinfo->filled |= BIT(NL80211_STA_INFO_LLID) | |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4f052bb2a5ad..925e68fe64c7 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -346,6 +346,14 @@ struct ieee80211_tx_latency_stat { | |||
346 | * @cipher_scheme: optional cipher scheme for this station | 346 | * @cipher_scheme: optional cipher scheme for this station |
347 | * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed | 347 | * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed |
348 | * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED) | 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 | struct sta_info { | 358 | struct sta_info { |
351 | /* General information, mostly static */ | 359 | /* General information, mostly static */ |
@@ -416,6 +424,10 @@ struct sta_info { | |||
416 | u32 last_rx_rate_vht_flag; | 424 | u32 last_rx_rate_vht_flag; |
417 | u8 last_rx_rate_vht_nss; | 425 | u8 last_rx_rate_vht_nss; |
418 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | 426 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; |
427 | u64 tx_msdu[IEEE80211_NUM_TIDS + 1]; | ||
428 | u64 tx_msdu_retries[IEEE80211_NUM_TIDS + 1]; | ||
429 | u64 tx_msdu_failed[IEEE80211_NUM_TIDS + 1]; | ||
430 | u64 rx_msdu[IEEE80211_NUM_TIDS + 1]; | ||
419 | 431 | ||
420 | /* | 432 | /* |
421 | * Aggregation information, locked with lock. | 433 | * Aggregation information, locked with lock. |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 7d4e9307164c..788707f05516 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -730,6 +730,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
730 | struct ieee80211_bar *bar; | 730 | struct ieee80211_bar *bar; |
731 | int rtap_len; | 731 | int rtap_len; |
732 | int shift = 0; | 732 | int shift = 0; |
733 | int tid = IEEE80211_NUM_TIDS;; | ||
733 | 734 | ||
734 | rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); | 735 | rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); |
735 | 736 | ||
@@ -773,7 +774,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
773 | 774 | ||
774 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | 775 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && |
775 | (ieee80211_is_data_qos(fc))) { | 776 | (ieee80211_is_data_qos(fc))) { |
776 | u16 tid, ssn; | 777 | u16 ssn; |
777 | u8 *qc; | 778 | u8 *qc; |
778 | 779 | ||
779 | qc = ieee80211_get_qos_ctl(hdr); | 780 | qc = ieee80211_get_qos_ctl(hdr); |
@@ -782,10 +783,14 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
782 | & IEEE80211_SCTL_SEQ); | 783 | & IEEE80211_SCTL_SEQ); |
783 | ieee80211_send_bar(&sta->sdata->vif, hdr->addr1, | 784 | ieee80211_send_bar(&sta->sdata->vif, hdr->addr1, |
784 | tid, ssn); | 785 | tid, ssn); |
786 | } else if (ieee80211_is_data_qos(fc)) { | ||
787 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
788 | |||
789 | tid = qc[0] & 0xf; | ||
785 | } | 790 | } |
786 | 791 | ||
787 | if (!acked && ieee80211_is_back_req(fc)) { | 792 | if (!acked && ieee80211_is_back_req(fc)) { |
788 | u16 tid, control; | 793 | u16 control; |
789 | 794 | ||
790 | /* | 795 | /* |
791 | * BAR failed, store the last SSN and retry sending | 796 | * BAR failed, store the last SSN and retry sending |
@@ -813,6 +818,12 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
813 | if (!acked) | 818 | if (!acked) |
814 | sta->tx_retry_failed++; | 819 | sta->tx_retry_failed++; |
815 | sta->tx_retry_count += retry_count; | 820 | sta->tx_retry_count += retry_count; |
821 | |||
822 | if (ieee80211_is_data_present(fc)) { | ||
823 | if (!acked) | ||
824 | sta->tx_msdu_failed[tid]++; | ||
825 | sta->tx_msdu_retries[tid] += retry_count; | ||
826 | } | ||
816 | } | 827 | } |
817 | 828 | ||
818 | rate_control_tx_status(local, sband, sta, skb); | 829 | rate_control_tx_status(local, sband, sta, skb); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 058686a721a1..da7f352a2b16 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -815,6 +815,8 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
815 | /* for pure STA mode without beacons, we can do it */ | 815 | /* for pure STA mode without beacons, we can do it */ |
816 | hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); | 816 | hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); |
817 | tx->sdata->sequence_number += 0x10; | 817 | tx->sdata->sequence_number += 0x10; |
818 | if (tx->sta) | ||
819 | tx->sta->tx_msdu[IEEE80211_NUM_TIDS]++; | ||
818 | return TX_CONTINUE; | 820 | return TX_CONTINUE; |
819 | } | 821 | } |
820 | 822 | ||
@@ -831,6 +833,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
831 | qc = ieee80211_get_qos_ctl(hdr); | 833 | qc = ieee80211_get_qos_ctl(hdr); |
832 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 834 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
833 | seq = &tx->sta->tid_seq[tid]; | 835 | seq = &tx->sta->tid_seq[tid]; |
836 | tx->sta->tx_msdu[tid]++; | ||
834 | 837 | ||
835 | hdr->seq_ctrl = cpu_to_le16(*seq); | 838 | hdr->seq_ctrl = cpu_to_le16(*seq); |
836 | 839 | ||