diff options
author | Ben Greear <greearb@candelatech.com> | 2014-10-22 15:22:58 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-10-24 04:19:58 -0400 |
commit | 2155c3f82327bddd092bd704ebaff79c0a2dfb9c (patch) | |
tree | e6e5630b2cb7b883b7703f0798e929742de66dd8 | |
parent | 0fc1e0495fd6e261e75acdbe66b53e769e5ffb81 (diff) |
mac80211-hwsim: add ethtool stats support
This gives a view into packet activity at the virtual radio
level.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 6ffe07323e6e..4e92a5b9324d 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -450,6 +450,14 @@ struct mac80211_hwsim_data { | |||
450 | s64 bcn_delta; | 450 | s64 bcn_delta; |
451 | /* absolute beacon transmission time. Used to cover up "tx" delay. */ | 451 | /* absolute beacon transmission time. Used to cover up "tx" delay. */ |
452 | u64 abs_bcn_ts; | 452 | u64 abs_bcn_ts; |
453 | |||
454 | /* Stats */ | ||
455 | u64 tx_pkts; | ||
456 | u64 rx_pkts; | ||
457 | u64 tx_bytes; | ||
458 | u64 rx_bytes; | ||
459 | u64 tx_dropped; | ||
460 | u64 tx_failed; | ||
453 | }; | 461 | }; |
454 | 462 | ||
455 | 463 | ||
@@ -865,8 +873,10 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, | |||
865 | /* If the queue contains MAX_QUEUE skb's drop some */ | 873 | /* If the queue contains MAX_QUEUE skb's drop some */ |
866 | if (skb_queue_len(&data->pending) >= MAX_QUEUE) { | 874 | if (skb_queue_len(&data->pending) >= MAX_QUEUE) { |
867 | /* Droping until WARN_QUEUE level */ | 875 | /* Droping until WARN_QUEUE level */ |
868 | while (skb_queue_len(&data->pending) >= WARN_QUEUE) | 876 | while (skb_queue_len(&data->pending) >= WARN_QUEUE) { |
869 | ieee80211_free_txskb(hw, skb_dequeue(&data->pending)); | 877 | ieee80211_free_txskb(hw, skb_dequeue(&data->pending)); |
878 | data->tx_dropped++; | ||
879 | } | ||
870 | } | 880 | } |
871 | 881 | ||
872 | skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); | 882 | skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); |
@@ -921,11 +931,14 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, | |||
921 | 931 | ||
922 | /* Enqueue the packet */ | 932 | /* Enqueue the packet */ |
923 | skb_queue_tail(&data->pending, my_skb); | 933 | skb_queue_tail(&data->pending, my_skb); |
934 | data->tx_pkts++; | ||
935 | data->tx_bytes += my_skb->len; | ||
924 | return; | 936 | return; |
925 | 937 | ||
926 | nla_put_failure: | 938 | nla_put_failure: |
927 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); | 939 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); |
928 | ieee80211_free_txskb(hw, my_skb); | 940 | ieee80211_free_txskb(hw, my_skb); |
941 | data->tx_failed++; | ||
929 | } | 942 | } |
930 | 943 | ||
931 | static bool hwsim_chans_compat(struct ieee80211_channel *c1, | 944 | static bool hwsim_chans_compat(struct ieee80211_channel *c1, |
@@ -1071,6 +1084,8 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
1071 | rx_status.mactime = now + data2->tsf_offset; | 1084 | rx_status.mactime = now + data2->tsf_offset; |
1072 | 1085 | ||
1073 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); | 1086 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); |
1087 | data2->rx_pkts++; | ||
1088 | data2->rx_bytes += nskb->len; | ||
1074 | ieee80211_rx_irqsafe(data2->hw, nskb); | 1089 | ieee80211_rx_irqsafe(data2->hw, nskb); |
1075 | } | 1090 | } |
1076 | spin_unlock(&hwsim_radio_lock); | 1091 | spin_unlock(&hwsim_radio_lock); |
@@ -1138,6 +1153,8 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, | |||
1138 | return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); | 1153 | return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); |
1139 | 1154 | ||
1140 | /* NO wmediumd detected, perfect medium simulation */ | 1155 | /* NO wmediumd detected, perfect medium simulation */ |
1156 | data->tx_pkts++; | ||
1157 | data->tx_bytes += skb->len; | ||
1141 | ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel); | 1158 | ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel); |
1142 | 1159 | ||
1143 | if (ack && skb->len >= 16) { | 1160 | if (ack && skb->len >= 16) { |
@@ -1921,6 +1938,57 @@ static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
1921 | hwsim_check_chanctx_magic(ctx); | 1938 | hwsim_check_chanctx_magic(ctx); |
1922 | } | 1939 | } |
1923 | 1940 | ||
1941 | static const char mac80211_hwsim_gstrings_stats[][ETH_GSTRING_LEN] = { | ||
1942 | "tx_pkts_nic", | ||
1943 | "tx_bytes_nic", | ||
1944 | "rx_pkts_nic", | ||
1945 | "rx_bytes_nic", | ||
1946 | "d_tx_dropped", | ||
1947 | "d_tx_failed", | ||
1948 | "d_ps_mode", | ||
1949 | "d_group", | ||
1950 | "d_tx_power", | ||
1951 | }; | ||
1952 | |||
1953 | #define MAC80211_HWSIM_SSTATS_LEN ARRAY_SIZE(mac80211_hwsim_gstrings_stats) | ||
1954 | |||
1955 | static void mac80211_hwsim_get_et_strings(struct ieee80211_hw *hw, | ||
1956 | struct ieee80211_vif *vif, | ||
1957 | u32 sset, u8 *data) | ||
1958 | { | ||
1959 | if (sset == ETH_SS_STATS) | ||
1960 | memcpy(data, *mac80211_hwsim_gstrings_stats, | ||
1961 | sizeof(mac80211_hwsim_gstrings_stats)); | ||
1962 | } | ||
1963 | |||
1964 | static int mac80211_hwsim_get_et_sset_count(struct ieee80211_hw *hw, | ||
1965 | struct ieee80211_vif *vif, int sset) | ||
1966 | { | ||
1967 | if (sset == ETH_SS_STATS) | ||
1968 | return MAC80211_HWSIM_SSTATS_LEN; | ||
1969 | return 0; | ||
1970 | } | ||
1971 | |||
1972 | static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw, | ||
1973 | struct ieee80211_vif *vif, | ||
1974 | struct ethtool_stats *stats, u64 *data) | ||
1975 | { | ||
1976 | struct mac80211_hwsim_data *ar = hw->priv; | ||
1977 | int i = 0; | ||
1978 | |||
1979 | data[i++] = ar->tx_pkts; | ||
1980 | data[i++] = ar->tx_bytes; | ||
1981 | data[i++] = ar->rx_pkts; | ||
1982 | data[i++] = ar->rx_bytes; | ||
1983 | data[i++] = ar->tx_dropped; | ||
1984 | data[i++] = ar->tx_failed; | ||
1985 | data[i++] = ar->ps; | ||
1986 | data[i++] = ar->group; | ||
1987 | data[i++] = ar->power_level; | ||
1988 | |||
1989 | WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN); | ||
1990 | } | ||
1991 | |||
1924 | static const struct ieee80211_ops mac80211_hwsim_ops = { | 1992 | static const struct ieee80211_ops mac80211_hwsim_ops = { |
1925 | .tx = mac80211_hwsim_tx, | 1993 | .tx = mac80211_hwsim_tx, |
1926 | .start = mac80211_hwsim_start, | 1994 | .start = mac80211_hwsim_start, |
@@ -1944,6 +2012,9 @@ static const struct ieee80211_ops mac80211_hwsim_ops = { | |||
1944 | .flush = mac80211_hwsim_flush, | 2012 | .flush = mac80211_hwsim_flush, |
1945 | .get_tsf = mac80211_hwsim_get_tsf, | 2013 | .get_tsf = mac80211_hwsim_get_tsf, |
1946 | .set_tsf = mac80211_hwsim_set_tsf, | 2014 | .set_tsf = mac80211_hwsim_set_tsf, |
2015 | .get_et_sset_count = mac80211_hwsim_get_et_sset_count, | ||
2016 | .get_et_stats = mac80211_hwsim_get_et_stats, | ||
2017 | .get_et_strings = mac80211_hwsim_get_et_strings, | ||
1947 | }; | 2018 | }; |
1948 | 2019 | ||
1949 | static struct ieee80211_ops mac80211_hwsim_mchan_ops; | 2020 | static struct ieee80211_ops mac80211_hwsim_mchan_ops; |
@@ -2394,6 +2465,8 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, | |||
2394 | rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); | 2465 | rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); |
2395 | 2466 | ||
2396 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | 2467 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
2468 | data2->rx_pkts++; | ||
2469 | data2->rx_bytes += skb->len; | ||
2397 | ieee80211_rx_irqsafe(data2->hw, skb); | 2470 | ieee80211_rx_irqsafe(data2->hw, skb); |
2398 | 2471 | ||
2399 | return 0; | 2472 | return 0; |