aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Dumazet <dada1@cosmosbay.com>2009-05-17 20:34:33 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-18 18:15:06 -0400
commit7004bf252c53da18f6b55103e0c92f777f846806 (patch)
tree29868ce170599fbed3471f53afe3a20f23fb31c3 /net
parentba98898eb3fc07ee54566fcc3626354a44355acb (diff)
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: Eric Dumazet <dada1@cosmosbay.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 14dd725aaab7..6d3630d16271 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4943,13 +4943,30 @@ void netdev_run_todo(void)
4943 * the internal statistics structure is used. 4943 * the internal statistics structure is used.
4944 */ 4944 */
4945const struct net_device_stats *dev_get_stats(struct net_device *dev) 4945const struct net_device_stats *dev_get_stats(struct net_device *dev)
4946 { 4946{
4947 const struct net_device_ops *ops = dev->netdev_ops; 4947 const struct net_device_ops *ops = dev->netdev_ops;
4948 4948
4949 if (ops->ndo_get_stats) 4949 if (ops->ndo_get_stats)
4950 return ops->ndo_get_stats(dev); 4950 return ops->ndo_get_stats(dev);
4951 else 4951 else {
4952 return &dev->stats; 4952 unsigned long tx_bytes = 0, tx_packets = 0, tx_dropped = 0;
4953 struct net_device_stats *stats = &dev->stats;
4954 unsigned int i;
4955 struct netdev_queue *txq;
4956
4957 for (i = 0; i < dev->num_tx_queues; i++) {
4958 txq = netdev_get_tx_queue(dev, i);
4959 tx_bytes += txq->tx_bytes;
4960 tx_packets += txq->tx_packets;
4961 tx_dropped += txq->tx_dropped;
4962 }
4963 if (tx_bytes || tx_packets || tx_dropped) {
4964 stats->tx_bytes = tx_bytes;
4965 stats->tx_packets = tx_packets;
4966 stats->tx_dropped = tx_dropped;
4967 }
4968 return stats;
4969 }
4953} 4970}
4954EXPORT_SYMBOL(dev_get_stats); 4971EXPORT_SYMBOL(dev_get_stats);
4955 4972