diff options
author | Ben Greear <greearb@candelatech.com> | 2012-04-23 12:50:30 -0700 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-05-08 21:53:50 -0400 |
commit | b1ab79255c539ebe740baa89f8a44ab139381e1c (patch) | |
tree | 7c51677565d915e57842cd66b5e7a01eb111984f | |
parent | d61992182e41e1beec0507fd7bce4ba1face12d6 (diff) | |
download | linux-b1ab79255c539ebe740baa89f8a44ab139381e1c.tar.bz2 |
mac80211: Support getting sta_info stats via ethtool.
This lets ethtool print out stats related to stations
connected to the interface. Does not yet get stats
from the underlying driver.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | net/mac80211/cfg.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 70b2af2315a6..31023ca17575 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -450,6 +450,94 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); } +static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = { + "rx_packets", "rx_bytes", "wep_weak_iv_count", + "rx_duplicates", "rx_fragments", "rx_dropped", + "tx_packets", "tx_bytes", "tx_fragments", + "tx_filtered", "tx_retry_failed", "tx_retries", + "beacon_loss" +}; +#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats) + +static int ieee80211_get_et_sset_count(struct wiphy *wiphy, + struct net_device *dev, + int sset) +{ + if (sset == ETH_SS_STATS) + return STA_STATS_LEN; + + return -EOPNOTSUPP; +} + +static void ieee80211_get_et_stats(struct wiphy *wiphy, + struct net_device *dev, + struct ethtool_stats *stats, + u64 *data) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct sta_info *sta; + struct ieee80211_local *local = sdata->local; + int i; + + memset(data, 0, sizeof(u64) * STA_STATS_LEN); + +#define ADD_STA_STATS(sta) \ + do { \ + data[i++] += sta->rx_packets; \ + data[i++] += sta->rx_bytes; \ + data[i++] += sta->wep_weak_iv_count; \ + data[i++] += sta->num_duplicates; \ + data[i++] += sta->rx_fragments; \ + data[i++] += sta->rx_dropped; \ + \ + data[i++] += sta->tx_packets; \ + data[i++] += sta->tx_bytes; \ + data[i++] += sta->tx_fragments; \ + data[i++] += sta->tx_filtered_count; \ + data[i++] += sta->tx_retry_failed; \ + data[i++] += sta->tx_retry_count; \ + data[i++] += sta->beacon_loss_count; \ + } while (0) + + /* For Managed stations, find the single station based on BSSID + * and use that. For interface types, iterate through all available + * stations and add stats for any station that is assigned to this + * network device. + */ + + rcu_read_lock(); + + if (sdata->vif.type == NL80211_IFTYPE_STATION) { + sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid); + if (sta && !WARN_ON(sta->sdata->dev != dev)) { + i = 0; + ADD_STA_STATS(sta); + BUG_ON(i != STA_STATS_LEN); + } + } else { + list_for_each_entry_rcu(sta, &local->sta_list, list) { + /* Make sure this station belongs to the proper dev */ + if (sta->sdata->dev != dev) + continue; + + i = 0; + ADD_STA_STATS(sta); + BUG_ON(i != STA_STATS_LEN); + } + } + + rcu_read_unlock(); +} + +static void ieee80211_get_et_strings(struct wiphy *wiphy, + struct net_device *dev, + u32 sset, u8 *data) +{ + if (sset == ETH_SS_STATS) { + int sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats); + memcpy(data, *ieee80211_gstrings_sta_stats, sz_sta_stats); + } +} static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *mac, struct station_info *sinfo) @@ -2794,4 +2882,7 @@ struct cfg80211_ops mac80211_config_ops = { #ifdef CONFIG_PM .set_wakeup = ieee80211_set_wakeup, #endif + .get_et_sset_count = ieee80211_get_et_sset_count, + .get_et_stats = ieee80211_get_et_stats, + .get_et_strings = ieee80211_get_et_strings, }; |