Commit 6de39808 authored by Johannes Berg's avatar Johannes Berg

nl80211: support per-TID station statistics

The base for the current statistics is pretty mixed up, support
exporting RX/TX statistics for MSDUs per TID. This (currently)
covers received MSDUs, transmitted MSDUs and retries/failures
thereof.

Doing it per TID for MSDUs makes more sense than say only per AC
because it's symmetric - we could export per-AC statistics for all
frames (which AC we used for transmission can be determined also
for management frames) but per TID is better and usually data
frames are really the ones we care about. Also, on RX we can't
determine the AC - but we do know the TID for any QoS MPDU we
received.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 8d791361
...@@ -939,6 +939,24 @@ struct sta_bss_parameters { ...@@ -939,6 +939,24 @@ struct sta_bss_parameters {
u16 beacon_interval; u16 beacon_interval;
}; };
/**
* struct cfg80211_tid_stats - per-TID statistics
* @filled: bitmap of flags using the bits of &enum nl80211_tid_stats to
* indicate the relevant values in this struct are filled
* @rx_msdu: number of received MSDUs
* @tx_msdu: number of (attempted) transmitted MSDUs
* @tx_msdu_retries: number of retries (not counting the first) for
* transmitted MSDUs
* @tx_msdu_failed: number of failed transmitted MSDUs
*/
struct cfg80211_tid_stats {
u32 filled;
u64 rx_msdu;
u64 tx_msdu;
u64 tx_msdu_retries;
u64 tx_msdu_failed;
};
#define IEEE80211_MAX_CHAINS 4 #define IEEE80211_MAX_CHAINS 4
/** /**
...@@ -990,6 +1008,8 @@ struct sta_bss_parameters { ...@@ -990,6 +1008,8 @@ struct sta_bss_parameters {
* @rx_beacon: number of beacons received from this peer * @rx_beacon: number of beacons received from this peer
* @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received * @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received
* from this peer * from this peer
* @pertid: per-TID statistics, see &struct cfg80211_tid_stats, using the last
* (IEEE80211_NUM_TIDS) index for MSDUs not encapsulated in QoS-MPDUs.
*/ */
struct station_info { struct station_info {
u32 filled; u32 filled;
...@@ -1032,6 +1052,7 @@ struct station_info { ...@@ -1032,6 +1052,7 @@ struct station_info {
u64 rx_beacon; u64 rx_beacon;
u8 rx_beacon_signal_avg; u8 rx_beacon_signal_avg;
struct cfg80211_tid_stats pertid[IEEE80211_NUM_TIDS + 1];
}; };
/** /**
......
...@@ -2384,6 +2384,11 @@ enum nl80211_sta_bss_param { ...@@ -2384,6 +2384,11 @@ enum nl80211_sta_bss_param {
* @NL80211_STA_INFO_BEACON_RX: number of beacons received from this peer (u64) * @NL80211_STA_INFO_BEACON_RX: number of beacons received from this peer (u64)
* @NL80211_STA_INFO_BEACON_SIGNAL_AVG: signal strength average * @NL80211_STA_INFO_BEACON_SIGNAL_AVG: signal strength average
* for beacons only (u8, dBm) * for beacons only (u8, dBm)
* @NL80211_STA_INFO_TID_STATS: per-TID statistics (see &enum nl80211_tid_stats)
* This is a nested attribute where each the inner attribute number is the
* TID+1 and the special TID 16 (i.e. value 17) is used for non-QoS frames;
* each one of those is again nested with &enum nl80211_tid_stats
* attributes carrying the actual values.
* @__NL80211_STA_INFO_AFTER_LAST: internal * @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute * @NL80211_STA_INFO_MAX: highest possible station info attribute
*/ */
...@@ -2419,12 +2424,38 @@ enum nl80211_sta_info { ...@@ -2419,12 +2424,38 @@ enum nl80211_sta_info {
NL80211_STA_INFO_RX_DROP_MISC, NL80211_STA_INFO_RX_DROP_MISC,
NL80211_STA_INFO_BEACON_RX, NL80211_STA_INFO_BEACON_RX,
NL80211_STA_INFO_BEACON_SIGNAL_AVG, NL80211_STA_INFO_BEACON_SIGNAL_AVG,
NL80211_STA_INFO_TID_STATS,
/* keep last */ /* keep last */
__NL80211_STA_INFO_AFTER_LAST, __NL80211_STA_INFO_AFTER_LAST,
NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1 NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
}; };
/**
* enum nl80211_tid_stats - per TID statistics attributes
* @__NL80211_TID_STATS_INVALID: attribute number 0 is reserved
* @NL80211_TID_STATS_RX_MSDU: number of MSDUs received (u64)
* @NL80211_TID_STATS_TX_MSDU: number of MSDUs transmitted (or
* attempted to transmit; u64)
* @NL80211_TID_STATS_TX_MSDU_RETRIES: number of retries for
* transmitted MSDUs (not counting the first attempt; u64)
* @NL80211_TID_STATS_TX_MSDU_FAILED: number of failed transmitted
* MSDUs (u64)
* @NUM_NL80211_TID_STATS: number of attributes here
* @NL80211_TID_STATS_MAX: highest numbered attribute here
*/
enum nl80211_tid_stats {
__NL80211_TID_STATS_INVALID,
NL80211_TID_STATS_RX_MSDU,
NL80211_TID_STATS_TX_MSDU,
NL80211_TID_STATS_TX_MSDU_RETRIES,
NL80211_TID_STATS_TX_MSDU_FAILED,
/* keep last */
NUM_NL80211_TID_STATS,
NL80211_TID_STATS_MAX = NUM_NL80211_TID_STATS - 1
};
/** /**
* enum nl80211_mpath_flags - nl80211 mesh path flags * enum nl80211_mpath_flags - nl80211 mesh path flags
* *
......
...@@ -3772,6 +3772,47 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, ...@@ -3772,6 +3772,47 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8); PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
#undef PUT_SINFO #undef PUT_SINFO
if (sinfo->filled & BIT(NL80211_STA_INFO_TID_STATS)) {
struct nlattr *tidsattr;
int tid;
tidsattr = nla_nest_start(msg, NL80211_STA_INFO_TID_STATS);
if (!tidsattr)
goto nla_put_failure;
for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
struct cfg80211_tid_stats *tidstats;
struct nlattr *tidattr;
tidstats = &sinfo->pertid[tid];
if (!tidstats->filled)
continue;
tidattr = nla_nest_start(msg, tid + 1);
if (!tidattr)
goto nla_put_failure;
#define PUT_TIDVAL(attr, memb, type) do { \
if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
nla_put_ ## type(msg, NL80211_TID_STATS_ ## attr, \
tidstats->memb)) \
goto nla_put_failure; \
} while (0)
PUT_TIDVAL(RX_MSDU, rx_msdu, u64);
PUT_TIDVAL(TX_MSDU, tx_msdu, u64);
PUT_TIDVAL(TX_MSDU_RETRIES, tx_msdu_retries, u64);
PUT_TIDVAL(TX_MSDU_FAILED, tx_msdu_failed, u64);
#undef PUT_TIDVAL
nla_nest_end(msg, tidattr);
}
nla_nest_end(msg, tidsattr);
}
nla_nest_end(msg, sinfoattr); nla_nest_end(msg, sinfoattr);
if (sinfo->assoc_req_ies_len && if (sinfo->assoc_req_ies_len &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment