Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7004bf25 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

net: add tx_packets/tx_bytes/tx_dropped counters in struct netdev_queue



offsetof(struct net_device, features)=0x44
offsetof(struct net_device, stats.tx_packets)=0x54
offsetof(struct net_device, stats.tx_bytes)=0x5c
offsetof(struct net_device, stats.tx_dropped)=0x6c

Network drivers that touch dev->stats.tx_packets/stats.tx_bytes in their
tx path can slow down SMP operations, since they dirty a cache line
that should stay shared (dev->features is needed in rx and tx paths)

We could move away stats field in net_device but it wont help that much.
(Two cache lines dirtied in tx path, we can do one only)

Better solution is to add tx_packets/tx_bytes/tx_dropped in struct
netdev_queue because this structure is already touched in tx path and
counters updates will then be free (no increase in size)

Signed-off-by: default avatarEric Dumazet <dada1@cosmosbay.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ba98898e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -474,6 +474,9 @@ struct netdev_queue {
	 * please use this field instead of dev->trans_start
	 */
	unsigned long		trans_start;
	unsigned long		tx_bytes;
	unsigned long		tx_packets;
	unsigned long		tx_dropped;
} ____cacheline_aligned_in_smp;


+20 −3
Original line number Diff line number Diff line
@@ -4948,8 +4948,25 @@ const struct net_device_stats *dev_get_stats(struct net_device *dev)

	if (ops->ndo_get_stats)
		return ops->ndo_get_stats(dev);
	else
		return &dev->stats;
	else {
		unsigned long tx_bytes = 0, tx_packets = 0, tx_dropped = 0;
		struct net_device_stats *stats = &dev->stats;
		unsigned int i;
		struct netdev_queue *txq;

		for (i = 0; i < dev->num_tx_queues; i++) {
			txq = netdev_get_tx_queue(dev, i);
			tx_bytes   += txq->tx_bytes;
			tx_packets += txq->tx_packets;
			tx_dropped += txq->tx_dropped;
		}
		if (tx_bytes || tx_packets || tx_dropped) {
			stats->tx_bytes   = tx_bytes;
			stats->tx_packets = tx_packets;
			stats->tx_dropped = tx_dropped;
		}
		return stats;
	}
}
EXPORT_SYMBOL(dev_get_stats);