aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorEric Dumazet <dada1@cosmosbay.com>2009-04-17 18:03:10 -0400
committerDavid S. Miller <davem@davemloft.net>2009-04-20 05:25:26 -0400
commit7eebb0b28f755e297d355a205bb04945b256db6b (patch)
treeae09d5928a764f5cb58eb217ec0d910e5d332474 /drivers/net
parenteb62efd287fe6e12d18083287e38e4a811c28256 (diff)
loopback: packet drops accounting
We can in some situations drop packets in netif_rx() loopback driver does not report these (unlikely) drops to its stats, and incorrectly change packets/bytes counts. After this patch applied, "ifconfig lo" can reports these drops as in : # ifconfig lo lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:692562900 errors:3228 dropped:3228 overruns:0 frame:0 TX packets:692562900 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:2865674174 (2.6 GiB) TX bytes:2865674174 (2.6 GiB) I initialy chose to reflect those errors only in tx_dropped/tx_errors, but David convinced me that it was really RX errors, as loopback_xmit() really starts a RX process. (calling eth_type_trans() for example, that itself pulls the ethernet header) These errors are accounted in rx_dropped/rx_errors. Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/loopback.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index b7d438a367f3..6f71157bea8e 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -62,6 +62,7 @@
62struct pcpu_lstats { 62struct pcpu_lstats {
63 unsigned long packets; 63 unsigned long packets;
64 unsigned long bytes; 64 unsigned long bytes;
65 unsigned long drops;
65}; 66};
66 67
67/* 68/*
@@ -71,18 +72,22 @@ struct pcpu_lstats {
71static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) 72static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
72{ 73{
73 struct pcpu_lstats *pcpu_lstats, *lb_stats; 74 struct pcpu_lstats *pcpu_lstats, *lb_stats;
75 int len;
74 76
75 skb_orphan(skb); 77 skb_orphan(skb);
76 78
77 skb->protocol = eth_type_trans(skb,dev); 79 skb->protocol = eth_type_trans(skb, dev);
78 80
79 /* it's OK to use per_cpu_ptr() because BHs are off */ 81 /* it's OK to use per_cpu_ptr() because BHs are off */
80 pcpu_lstats = dev->ml_priv; 82 pcpu_lstats = dev->ml_priv;
81 lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id()); 83 lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id());
82 lb_stats->bytes += skb->len;
83 lb_stats->packets++;
84 84
85 netif_rx(skb); 85 len = skb->len;
86 if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
87 lb_stats->bytes += len;
88 lb_stats->packets++;
89 } else
90 lb_stats->drops++;
86 91
87 return 0; 92 return 0;
88} 93}
@@ -93,6 +98,7 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev)
93 struct net_device_stats *stats = &dev->stats; 98 struct net_device_stats *stats = &dev->stats;
94 unsigned long bytes = 0; 99 unsigned long bytes = 0;
95 unsigned long packets = 0; 100 unsigned long packets = 0;
101 unsigned long drops = 0;
96 int i; 102 int i;
97 103
98 pcpu_lstats = dev->ml_priv; 104 pcpu_lstats = dev->ml_priv;
@@ -102,11 +108,14 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev)
102 lb_stats = per_cpu_ptr(pcpu_lstats, i); 108 lb_stats = per_cpu_ptr(pcpu_lstats, i);
103 bytes += lb_stats->bytes; 109 bytes += lb_stats->bytes;
104 packets += lb_stats->packets; 110 packets += lb_stats->packets;
111 drops += lb_stats->drops;
105 } 112 }
106 stats->rx_packets = packets; 113 stats->rx_packets = packets;
107 stats->tx_packets = packets; 114 stats->tx_packets = packets;
108 stats->rx_bytes = bytes; 115 stats->rx_dropped = drops;
109 stats->tx_bytes = bytes; 116 stats->rx_errors = drops;
117 stats->rx_bytes = bytes;
118 stats->tx_bytes = bytes;
110 return stats; 119 return stats;
111} 120}
112 121