Skip to content

Commit 5a49051

Browse files
committed
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>
1 parent ce5b071 commit 5a49051

File tree

3 files changed

+70
-12
lines changed

3 files changed

+70
-12
lines changed

net/mac80211/iface.c

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,35 @@ static u16 ieee80211_netdev_select_queue(struct net_device *dev,
10941094
return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
10951095
}
10961096

1097+
static struct rtnl_link_stats64 *
1098+
ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
1099+
{
1100+
int i;
1101+
1102+
for_each_possible_cpu(i) {
1103+
const struct pcpu_sw_netstats *tstats;
1104+
u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
1105+
unsigned int start;
1106+
1107+
tstats = per_cpu_ptr(dev->tstats, i);
1108+
1109+
do {
1110+
start = u64_stats_fetch_begin_irq(&tstats->syncp);
1111+
rx_packets = tstats->rx_packets;
1112+
tx_packets = tstats->tx_packets;
1113+
rx_bytes = tstats->rx_bytes;
1114+
tx_bytes = tstats->tx_bytes;
1115+
} while (u64_stats_fetch_retry_irq(&tstats->syncp, start));
1116+
1117+
stats->rx_packets += rx_packets;
1118+
stats->tx_packets += tx_packets;
1119+
stats->rx_bytes += rx_bytes;
1120+
stats->tx_bytes += tx_bytes;
1121+
}
1122+
1123+
return stats;
1124+
}
1125+
10971126
static const struct net_device_ops ieee80211_dataif_ops = {
10981127
.ndo_open = ieee80211_open,
10991128
.ndo_stop = ieee80211_stop,
@@ -1103,6 +1132,7 @@ static const struct net_device_ops ieee80211_dataif_ops = {
11031132
.ndo_change_mtu = ieee80211_change_mtu,
11041133
.ndo_set_mac_address = ieee80211_change_mac,
11051134
.ndo_select_queue = ieee80211_netdev_select_queue,
1135+
.ndo_get_stats64 = ieee80211_get_stats64,
11061136
};
11071137

11081138
static u16 ieee80211_monitor_select_queue(struct net_device *dev,
@@ -1136,14 +1166,21 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
11361166
.ndo_change_mtu = ieee80211_change_mtu,
11371167
.ndo_set_mac_address = ieee80211_change_mac,
11381168
.ndo_select_queue = ieee80211_monitor_select_queue,
1169+
.ndo_get_stats64 = ieee80211_get_stats64,
11391170
};
11401171

1172+
static void ieee80211_if_free(struct net_device *dev)
1173+
{
1174+
free_percpu(dev->tstats);
1175+
free_netdev(dev);
1176+
}
1177+
11411178
static void ieee80211_if_setup(struct net_device *dev)
11421179
{
11431180
ether_setup(dev);
11441181
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
11451182
dev->netdev_ops = &ieee80211_dataif_ops;
1146-
dev->destructor = free_netdev;
1183+
dev->destructor = ieee80211_if_free;
11471184
}
11481185

11491186
static void ieee80211_iface_work(struct work_struct *work)
@@ -1684,6 +1721,12 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
16841721
return -ENOMEM;
16851722
dev_net_set(ndev, wiphy_net(local->hw.wiphy));
16861723

1724+
ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
1725+
if (!ndev->tstats) {
1726+
free_netdev(ndev);
1727+
return -ENOMEM;
1728+
}
1729+
16871730
ndev->needed_headroom = local->tx_headroom +
16881731
4*6 /* four MAC addresses */
16891732
+ 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */

net/mac80211/rx.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@
3232
#include "wme.h"
3333
#include "rate.h"
3434

35+
static inline void ieee80211_rx_stats(struct net_device *dev, u32 len)
36+
{
37+
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
38+
39+
u64_stats_update_begin(&tstats->syncp);
40+
tstats->rx_packets++;
41+
tstats->rx_bytes += len;
42+
u64_stats_update_end(&tstats->syncp);
43+
}
44+
3545
/*
3646
* monitor mode reception
3747
*
@@ -529,8 +539,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
529539
}
530540

531541
prev_dev = sdata->dev;
532-
sdata->dev->stats.rx_packets++;
533-
sdata->dev->stats.rx_bytes += skb->len;
542+
ieee80211_rx_stats(sdata->dev, skb->len);
534543
}
535544

536545
if (prev_dev) {
@@ -2036,12 +2045,11 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
20362045
struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
20372046
struct sta_info *dsta;
20382047

2039-
dev->stats.rx_packets++;
2040-
dev->stats.rx_bytes += rx->skb->len;
2041-
20422048
skb = rx->skb;
20432049
xmit_skb = NULL;
20442050

2051+
ieee80211_rx_stats(dev, skb->len);
2052+
20452053
if ((sdata->vif.type == NL80211_IFTYPE_AP ||
20462054
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
20472055
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
@@ -3045,8 +3053,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
30453053
}
30463054

30473055
prev_dev = sdata->dev;
3048-
sdata->dev->stats.rx_packets++;
3049-
sdata->dev->stats.rx_bytes += skb->len;
3056+
ieee80211_rx_stats(sdata->dev, skb->len);
30503057
}
30513058

30523059
if (prev_dev) {

net/mac80211/tx.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@
3737

3838
/* misc utils */
3939

40+
static inline void ieee80211_tx_stats(struct net_device *dev, u32 len)
41+
{
42+
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
43+
44+
u64_stats_update_begin(&tstats->syncp);
45+
tstats->tx_packets++;
46+
tstats->tx_bytes += len;
47+
u64_stats_update_end(&tstats->syncp);
48+
}
49+
4050
static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
4151
struct sk_buff *skb, int group_addr,
4252
int next_frag_len)
@@ -2727,8 +2737,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
27272737
return true;
27282738
}
27292739

2730-
dev->stats.tx_packets++;
2731-
dev->stats.tx_bytes += skb->len + extra_head;
2740+
ieee80211_tx_stats(dev, skb->len + extra_head);
27322741

27332742
/* will not be crypto-handled beyond what we do here, so use false
27342743
* 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,
29092918
if (IS_ERR(skb))
29102919
goto out;
29112920

2912-
dev->stats.tx_packets++;
2913-
dev->stats.tx_bytes += skb->len;
2921+
ieee80211_tx_stats(dev, skb->len);
29142922

29152923
ieee80211_xmit(sdata, sta, skb);
29162924
}

0 commit comments

Comments
 (0)