mac80211: use per-CPU TX/RX statistics
This isn't all that relevant for RX right now, but TX can be concurrent due to multi-queue and the accounting is therefore broken. Use the standard per-CPU statistics to avoid this. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
ce5b071a45
commit
5a490510ba
|
@ -1094,6 +1094,35 @@ static u16 ieee80211_netdev_select_queue(struct net_device *dev,
|
||||||
return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
|
return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct rtnl_link_stats64 *
|
||||||
|
ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for_each_possible_cpu(i) {
|
||||||
|
const struct pcpu_sw_netstats *tstats;
|
||||||
|
u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
|
||||||
|
unsigned int start;
|
||||||
|
|
||||||
|
tstats = per_cpu_ptr(dev->tstats, i);
|
||||||
|
|
||||||
|
do {
|
||||||
|
start = u64_stats_fetch_begin_irq(&tstats->syncp);
|
||||||
|
rx_packets = tstats->rx_packets;
|
||||||
|
tx_packets = tstats->tx_packets;
|
||||||
|
rx_bytes = tstats->rx_bytes;
|
||||||
|
tx_bytes = tstats->tx_bytes;
|
||||||
|
} while (u64_stats_fetch_retry_irq(&tstats->syncp, start));
|
||||||
|
|
||||||
|
stats->rx_packets += rx_packets;
|
||||||
|
stats->tx_packets += tx_packets;
|
||||||
|
stats->rx_bytes += rx_bytes;
|
||||||
|
stats->tx_bytes += tx_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct net_device_ops ieee80211_dataif_ops = {
|
static const struct net_device_ops ieee80211_dataif_ops = {
|
||||||
.ndo_open = ieee80211_open,
|
.ndo_open = ieee80211_open,
|
||||||
.ndo_stop = ieee80211_stop,
|
.ndo_stop = ieee80211_stop,
|
||||||
|
@ -1103,6 +1132,7 @@ static const struct net_device_ops ieee80211_dataif_ops = {
|
||||||
.ndo_change_mtu = ieee80211_change_mtu,
|
.ndo_change_mtu = ieee80211_change_mtu,
|
||||||
.ndo_set_mac_address = ieee80211_change_mac,
|
.ndo_set_mac_address = ieee80211_change_mac,
|
||||||
.ndo_select_queue = ieee80211_netdev_select_queue,
|
.ndo_select_queue = ieee80211_netdev_select_queue,
|
||||||
|
.ndo_get_stats64 = ieee80211_get_stats64,
|
||||||
};
|
};
|
||||||
|
|
||||||
static u16 ieee80211_monitor_select_queue(struct net_device *dev,
|
static u16 ieee80211_monitor_select_queue(struct net_device *dev,
|
||||||
|
@ -1136,14 +1166,21 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
|
||||||
.ndo_change_mtu = ieee80211_change_mtu,
|
.ndo_change_mtu = ieee80211_change_mtu,
|
||||||
.ndo_set_mac_address = ieee80211_change_mac,
|
.ndo_set_mac_address = ieee80211_change_mac,
|
||||||
.ndo_select_queue = ieee80211_monitor_select_queue,
|
.ndo_select_queue = ieee80211_monitor_select_queue,
|
||||||
|
.ndo_get_stats64 = ieee80211_get_stats64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void ieee80211_if_free(struct net_device *dev)
|
||||||
|
{
|
||||||
|
free_percpu(dev->tstats);
|
||||||
|
free_netdev(dev);
|
||||||
|
}
|
||||||
|
|
||||||
static void ieee80211_if_setup(struct net_device *dev)
|
static void ieee80211_if_setup(struct net_device *dev)
|
||||||
{
|
{
|
||||||
ether_setup(dev);
|
ether_setup(dev);
|
||||||
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
||||||
dev->netdev_ops = &ieee80211_dataif_ops;
|
dev->netdev_ops = &ieee80211_dataif_ops;
|
||||||
dev->destructor = free_netdev;
|
dev->destructor = ieee80211_if_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_iface_work(struct work_struct *work)
|
static void ieee80211_iface_work(struct work_struct *work)
|
||||||
|
@ -1684,6 +1721,12 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
dev_net_set(ndev, wiphy_net(local->hw.wiphy));
|
dev_net_set(ndev, wiphy_net(local->hw.wiphy));
|
||||||
|
|
||||||
|
ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
|
||||||
|
if (!ndev->tstats) {
|
||||||
|
free_netdev(ndev);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
ndev->needed_headroom = local->tx_headroom +
|
ndev->needed_headroom = local->tx_headroom +
|
||||||
4*6 /* four MAC addresses */
|
4*6 /* four MAC addresses */
|
||||||
+ 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */
|
+ 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */
|
||||||
|
|
|
@ -32,6 +32,16 @@
|
||||||
#include "wme.h"
|
#include "wme.h"
|
||||||
#include "rate.h"
|
#include "rate.h"
|
||||||
|
|
||||||
|
static inline void ieee80211_rx_stats(struct net_device *dev, u32 len)
|
||||||
|
{
|
||||||
|
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
|
||||||
|
|
||||||
|
u64_stats_update_begin(&tstats->syncp);
|
||||||
|
tstats->rx_packets++;
|
||||||
|
tstats->rx_bytes += len;
|
||||||
|
u64_stats_update_end(&tstats->syncp);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* monitor mode reception
|
* monitor mode reception
|
||||||
*
|
*
|
||||||
|
@ -529,8 +539,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_dev = sdata->dev;
|
prev_dev = sdata->dev;
|
||||||
sdata->dev->stats.rx_packets++;
|
ieee80211_rx_stats(sdata->dev, skb->len);
|
||||||
sdata->dev->stats.rx_bytes += skb->len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev_dev) {
|
if (prev_dev) {
|
||||||
|
@ -2036,12 +2045,11 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
||||||
struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
|
struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
|
||||||
struct sta_info *dsta;
|
struct sta_info *dsta;
|
||||||
|
|
||||||
dev->stats.rx_packets++;
|
|
||||||
dev->stats.rx_bytes += rx->skb->len;
|
|
||||||
|
|
||||||
skb = rx->skb;
|
skb = rx->skb;
|
||||||
xmit_skb = NULL;
|
xmit_skb = NULL;
|
||||||
|
|
||||||
|
ieee80211_rx_stats(dev, skb->len);
|
||||||
|
|
||||||
if ((sdata->vif.type == NL80211_IFTYPE_AP ||
|
if ((sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
|
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
|
||||||
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
|
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
|
||||||
|
@ -3045,8 +3053,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_dev = sdata->dev;
|
prev_dev = sdata->dev;
|
||||||
sdata->dev->stats.rx_packets++;
|
ieee80211_rx_stats(sdata->dev, skb->len);
|
||||||
sdata->dev->stats.rx_bytes += skb->len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev_dev) {
|
if (prev_dev) {
|
||||||
|
|
|
@ -37,6 +37,16 @@
|
||||||
|
|
||||||
/* misc utils */
|
/* misc utils */
|
||||||
|
|
||||||
|
static inline void ieee80211_tx_stats(struct net_device *dev, u32 len)
|
||||||
|
{
|
||||||
|
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
|
||||||
|
|
||||||
|
u64_stats_update_begin(&tstats->syncp);
|
||||||
|
tstats->tx_packets++;
|
||||||
|
tstats->tx_bytes += len;
|
||||||
|
u64_stats_update_end(&tstats->syncp);
|
||||||
|
}
|
||||||
|
|
||||||
static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
|
static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
|
||||||
struct sk_buff *skb, int group_addr,
|
struct sk_buff *skb, int group_addr,
|
||||||
int next_frag_len)
|
int next_frag_len)
|
||||||
|
@ -2727,8 +2737,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->stats.tx_packets++;
|
ieee80211_tx_stats(dev, skb->len + extra_head);
|
||||||
dev->stats.tx_bytes += skb->len + extra_head;
|
|
||||||
|
|
||||||
/* will not be crypto-handled beyond what we do here, so use false
|
/* will not be crypto-handled beyond what we do here, so use false
|
||||||
* as the may-encrypt argument for the resize to not account for
|
* as the may-encrypt argument for the resize to not account for
|
||||||
|
@ -2909,8 +2918,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
if (IS_ERR(skb))
|
if (IS_ERR(skb))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
dev->stats.tx_packets++;
|
ieee80211_tx_stats(dev, skb->len);
|
||||||
dev->stats.tx_bytes += skb->len;
|
|
||||||
|
|
||||||
ieee80211_xmit(sdata, sta, skb);
|
ieee80211_xmit(sdata, sta, skb);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue