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>
This commit is contained in:

committed by
Johannes Berg

parent
0fc1e0495f
commit
2155c3f823
@@ -450,6 +450,14 @@ struct mac80211_hwsim_data {
|
|||||||
s64 bcn_delta;
|
s64 bcn_delta;
|
||||||
/* absolute beacon transmission time. Used to cover up "tx" delay. */
|
/* absolute beacon transmission time. Used to cover up "tx" delay. */
|
||||||
u64 abs_bcn_ts;
|
u64 abs_bcn_ts;
|
||||||
|
|
||||||
|
/* Stats */
|
||||||
|
u64 tx_pkts;
|
||||||
|
u64 rx_pkts;
|
||||||
|
u64 tx_bytes;
|
||||||
|
u64 rx_bytes;
|
||||||
|
u64 tx_dropped;
|
||||||
|
u64 tx_failed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -865,8 +873,10 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
|
|||||||
/* If the queue contains MAX_QUEUE skb's drop some */
|
/* If the queue contains MAX_QUEUE skb's drop some */
|
||||||
if (skb_queue_len(&data->pending) >= MAX_QUEUE) {
|
if (skb_queue_len(&data->pending) >= MAX_QUEUE) {
|
||||||
/* Droping until WARN_QUEUE level */
|
/* Droping until WARN_QUEUE level */
|
||||||
while (skb_queue_len(&data->pending) >= WARN_QUEUE)
|
while (skb_queue_len(&data->pending) >= WARN_QUEUE) {
|
||||||
ieee80211_free_txskb(hw, skb_dequeue(&data->pending));
|
ieee80211_free_txskb(hw, skb_dequeue(&data->pending));
|
||||||
|
data->tx_dropped++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
||||||
@@ -921,11 +931,14 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
|
|||||||
|
|
||||||
/* Enqueue the packet */
|
/* Enqueue the packet */
|
||||||
skb_queue_tail(&data->pending, my_skb);
|
skb_queue_tail(&data->pending, my_skb);
|
||||||
|
data->tx_pkts++;
|
||||||
|
data->tx_bytes += my_skb->len;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__);
|
printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__);
|
||||||
ieee80211_free_txskb(hw, my_skb);
|
ieee80211_free_txskb(hw, my_skb);
|
||||||
|
data->tx_failed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hwsim_chans_compat(struct ieee80211_channel *c1,
|
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,
|
|||||||
rx_status.mactime = now + data2->tsf_offset;
|
rx_status.mactime = now + data2->tsf_offset;
|
||||||
|
|
||||||
memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
|
memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
|
||||||
|
data2->rx_pkts++;
|
||||||
|
data2->rx_bytes += nskb->len;
|
||||||
ieee80211_rx_irqsafe(data2->hw, nskb);
|
ieee80211_rx_irqsafe(data2->hw, nskb);
|
||||||
}
|
}
|
||||||
spin_unlock(&hwsim_radio_lock);
|
spin_unlock(&hwsim_radio_lock);
|
||||||
@@ -1138,6 +1153,8 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
|
|||||||
return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
|
return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
|
||||||
|
|
||||||
/* NO wmediumd detected, perfect medium simulation */
|
/* NO wmediumd detected, perfect medium simulation */
|
||||||
|
data->tx_pkts++;
|
||||||
|
data->tx_bytes += skb->len;
|
||||||
ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel);
|
ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel);
|
||||||
|
|
||||||
if (ack && skb->len >= 16) {
|
if (ack && skb->len >= 16) {
|
||||||
@@ -1921,6 +1938,57 @@ static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
|||||||
hwsim_check_chanctx_magic(ctx);
|
hwsim_check_chanctx_magic(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char mac80211_hwsim_gstrings_stats[][ETH_GSTRING_LEN] = {
|
||||||
|
"tx_pkts_nic",
|
||||||
|
"tx_bytes_nic",
|
||||||
|
"rx_pkts_nic",
|
||||||
|
"rx_bytes_nic",
|
||||||
|
"d_tx_dropped",
|
||||||
|
"d_tx_failed",
|
||||||
|
"d_ps_mode",
|
||||||
|
"d_group",
|
||||||
|
"d_tx_power",
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAC80211_HWSIM_SSTATS_LEN ARRAY_SIZE(mac80211_hwsim_gstrings_stats)
|
||||||
|
|
||||||
|
static void mac80211_hwsim_get_et_strings(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
u32 sset, u8 *data)
|
||||||
|
{
|
||||||
|
if (sset == ETH_SS_STATS)
|
||||||
|
memcpy(data, *mac80211_hwsim_gstrings_stats,
|
||||||
|
sizeof(mac80211_hwsim_gstrings_stats));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mac80211_hwsim_get_et_sset_count(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif, int sset)
|
||||||
|
{
|
||||||
|
if (sset == ETH_SS_STATS)
|
||||||
|
return MAC80211_HWSIM_SSTATS_LEN;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct ethtool_stats *stats, u64 *data)
|
||||||
|
{
|
||||||
|
struct mac80211_hwsim_data *ar = hw->priv;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
data[i++] = ar->tx_pkts;
|
||||||
|
data[i++] = ar->tx_bytes;
|
||||||
|
data[i++] = ar->rx_pkts;
|
||||||
|
data[i++] = ar->rx_bytes;
|
||||||
|
data[i++] = ar->tx_dropped;
|
||||||
|
data[i++] = ar->tx_failed;
|
||||||
|
data[i++] = ar->ps;
|
||||||
|
data[i++] = ar->group;
|
||||||
|
data[i++] = ar->power_level;
|
||||||
|
|
||||||
|
WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct ieee80211_ops mac80211_hwsim_ops = {
|
static const struct ieee80211_ops mac80211_hwsim_ops = {
|
||||||
.tx = mac80211_hwsim_tx,
|
.tx = mac80211_hwsim_tx,
|
||||||
.start = mac80211_hwsim_start,
|
.start = mac80211_hwsim_start,
|
||||||
@@ -1944,6 +2012,9 @@ static const struct ieee80211_ops mac80211_hwsim_ops = {
|
|||||||
.flush = mac80211_hwsim_flush,
|
.flush = mac80211_hwsim_flush,
|
||||||
.get_tsf = mac80211_hwsim_get_tsf,
|
.get_tsf = mac80211_hwsim_get_tsf,
|
||||||
.set_tsf = mac80211_hwsim_set_tsf,
|
.set_tsf = mac80211_hwsim_set_tsf,
|
||||||
|
.get_et_sset_count = mac80211_hwsim_get_et_sset_count,
|
||||||
|
.get_et_stats = mac80211_hwsim_get_et_stats,
|
||||||
|
.get_et_strings = mac80211_hwsim_get_et_strings,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ieee80211_ops mac80211_hwsim_mchan_ops;
|
static struct ieee80211_ops mac80211_hwsim_mchan_ops;
|
||||||
@@ -2394,6 +2465,8 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
|||||||
rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
|
rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
|
||||||
|
|
||||||
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
|
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
|
||||||
|
data2->rx_pkts++;
|
||||||
|
data2->rx_bytes += skb->len;
|
||||||
ieee80211_rx_irqsafe(data2->hw, skb);
|
ieee80211_rx_irqsafe(data2->hw, skb);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user