diff options
author | Ben Greear <greearb@candelatech.com> | 2012-04-23 15:50:30 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-05-08 21:53:50 -0400 |
commit | b1ab79255c539ebe740baa89f8a44ab139381e1c (patch) | |
tree | 7c51677565d915e57842cd66b5e7a01eb111984f /net/mac80211/cfg.c | |
parent | d61992182e41e1beec0507fd7bce4ba1face12d6 (diff) |
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>
Diffstat (limited to 'net/mac80211/cfg.c')
-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) | |||
450 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); | 450 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); |
451 | } | 451 | } |
452 | 452 | ||
453 | static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = { | ||
454 | "rx_packets", "rx_bytes", "wep_weak_iv_count", | ||
455 | "rx_duplicates", "rx_fragments", "rx_dropped", | ||
456 | "tx_packets", "tx_bytes", "tx_fragments", | ||
457 | "tx_filtered", "tx_retry_failed", "tx_retries", | ||
458 | "beacon_loss" | ||
459 | }; | ||
460 | #define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats) | ||
461 | |||
462 | static int ieee80211_get_et_sset_count(struct wiphy *wiphy, | ||
463 | struct net_device *dev, | ||
464 | int sset) | ||
465 | { | ||
466 | if (sset == ETH_SS_STATS) | ||
467 | return STA_STATS_LEN; | ||
468 | |||
469 | return -EOPNOTSUPP; | ||
470 | } | ||
471 | |||
472 | static void ieee80211_get_et_stats(struct wiphy *wiphy, | ||
473 | struct net_device *dev, | ||
474 | struct ethtool_stats *stats, | ||
475 | u64 *data) | ||
476 | { | ||
477 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
478 | struct sta_info *sta; | ||
479 | struct ieee80211_local *local = sdata->local; | ||
480 | int i; | ||
481 | |||
482 | memset(data, 0, sizeof(u64) * STA_STATS_LEN); | ||
483 | |||
484 | #define ADD_STA_STATS(sta) \ | ||
485 | do { \ | ||
486 | data[i++] += sta->rx_packets; \ | ||
487 | data[i++] += sta->rx_bytes; \ | ||
488 | data[i++] += sta->wep_weak_iv_count; \ | ||
489 | data[i++] += sta->num_duplicates; \ | ||
490 | data[i++] += sta->rx_fragments; \ | ||
491 | data[i++] += sta->rx_dropped; \ | ||
492 | \ | ||
493 | data[i++] += sta->tx_packets; \ | ||
494 | data[i++] += sta->tx_bytes; \ | ||
495 | data[i++] += sta->tx_fragments; \ | ||
496 | data[i++] += sta->tx_filtered_count; \ | ||
497 | data[i++] += sta->tx_retry_failed; \ | ||
498 | data[i++] += sta->tx_retry_count; \ | ||
499 | data[i++] += sta->beacon_loss_count; \ | ||
500 | } while (0) | ||
501 | |||
502 | /* For Managed stations, find the single station based on BSSID | ||
503 | * and use that. For interface types, iterate through all available | ||
504 | * stations and add stats for any station that is assigned to this | ||
505 | * network device. | ||
506 | */ | ||
507 | |||
508 | rcu_read_lock(); | ||
509 | |||
510 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
511 | sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid); | ||
512 | if (sta && !WARN_ON(sta->sdata->dev != dev)) { | ||
513 | i = 0; | ||
514 | ADD_STA_STATS(sta); | ||
515 | BUG_ON(i != STA_STATS_LEN); | ||
516 | } | ||
517 | } else { | ||
518 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
519 | /* Make sure this station belongs to the proper dev */ | ||
520 | if (sta->sdata->dev != dev) | ||
521 | continue; | ||
522 | |||
523 | i = 0; | ||
524 | ADD_STA_STATS(sta); | ||
525 | BUG_ON(i != STA_STATS_LEN); | ||
526 | } | ||
527 | } | ||
528 | |||
529 | rcu_read_unlock(); | ||
530 | } | ||
531 | |||
532 | static void ieee80211_get_et_strings(struct wiphy *wiphy, | ||
533 | struct net_device *dev, | ||
534 | u32 sset, u8 *data) | ||
535 | { | ||
536 | if (sset == ETH_SS_STATS) { | ||
537 | int sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats); | ||
538 | memcpy(data, *ieee80211_gstrings_sta_stats, sz_sta_stats); | ||
539 | } | ||
540 | } | ||
453 | 541 | ||
454 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | 542 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, |
455 | int idx, u8 *mac, struct station_info *sinfo) | 543 | int idx, u8 *mac, struct station_info *sinfo) |
@@ -2794,4 +2882,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
2794 | #ifdef CONFIG_PM | 2882 | #ifdef CONFIG_PM |
2795 | .set_wakeup = ieee80211_set_wakeup, | 2883 | .set_wakeup = ieee80211_set_wakeup, |
2796 | #endif | 2884 | #endif |
2885 | .get_et_sset_count = ieee80211_get_et_sset_count, | ||
2886 | .get_et_stats = ieee80211_get_et_stats, | ||
2887 | .get_et_strings = ieee80211_get_et_strings, | ||
2797 | }; | 2888 | }; |