Skip to content

Commit

Permalink
veth: Fix veth_get_stats()
Browse files Browse the repository at this point in the history
veth_get_stats() can be called in parallel on several cpus.

It's better to not reset dev->stats as it could give wrong result on
one cpu. Use temporary variables, then store the final results.

Also, we should loop on every possible cpus, not only online cpus,
or cpu hotplug can suddenly give wrong veth stats.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Nov 19, 2009
1 parent 56cf548 commit 2b1c8b0
Showing 1 changed file with 16 additions and 19 deletions.
35 changes: 16 additions & 19 deletions drivers/net/veth.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,32 +210,29 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *veth_get_stats(struct net_device *dev)
{
struct veth_priv *priv;
struct net_device_stats *dev_stats;
int cpu;
struct veth_net_stats *stats;
struct veth_net_stats *stats, total = {0};

priv = netdev_priv(dev);
dev_stats = &dev->stats;

dev_stats->rx_packets = 0;
dev_stats->tx_packets = 0;
dev_stats->rx_bytes = 0;
dev_stats->tx_bytes = 0;
dev_stats->tx_dropped = 0;
dev_stats->rx_dropped = 0;

for_each_online_cpu(cpu) {
for_each_possible_cpu(cpu) {
stats = per_cpu_ptr(priv->stats, cpu);

dev_stats->rx_packets += stats->rx_packets;
dev_stats->tx_packets += stats->tx_packets;
dev_stats->rx_bytes += stats->rx_bytes;
dev_stats->tx_bytes += stats->tx_bytes;
dev_stats->tx_dropped += stats->tx_dropped;
dev_stats->rx_dropped += stats->rx_dropped;
total.rx_packets += stats->rx_packets;
total.tx_packets += stats->tx_packets;
total.rx_bytes += stats->rx_bytes;
total.tx_bytes += stats->tx_bytes;
total.tx_dropped += stats->tx_dropped;
total.rx_dropped += stats->rx_dropped;
}

return dev_stats;
dev->stats.rx_packets = total.rx_packets;
dev->stats.tx_packets = total.tx_packets;
dev->stats.rx_bytes = total.rx_bytes;
dev->stats.tx_bytes = total.tx_bytes;
dev->stats.tx_dropped = total.tx_dropped;
dev->stats.rx_dropped = total.rx_dropped;

return &dev->stats;
}

static int veth_open(struct net_device *dev)
Expand Down

0 comments on commit 2b1c8b0

Please sign in to comment.