aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-09-30 17:06:55 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-05 17:47:55 -0400
commitcaf586e5f23cebb2a68cbaf288d59dbbf2d74052 (patch)
tree5c0dfcf5a14c55501f9225835c83abddb8d1876e
parenta00eac0c459abecb539fb2a2abd3122dd7ca5d4a (diff)
net: add a core netdev->rx_dropped counter
In various situations, a device provides a packet to our stack and we drop it before it enters protocol stack : - softnet backlog full (accounted in /proc/net/softnet_stat) - bad vlan tag (not accounted) - unknown/unregistered protocol (not accounted) We can handle a per-device counter of such dropped frames at core level, and automatically adds it to the device provided stats (rx_dropped), so that standard tools can be used (ifconfig, ip link, cat /proc/net/dev) This is a generalization of commit 8990f468a (net: rx_dropped accounting), thus reverting it. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/loopback.c8
-rw-r--r--include/linux/netdevice.h3
-rw-r--r--net/8021q/vlan.h2
-rw-r--r--net/8021q/vlan_core.c2
-rw-r--r--net/8021q/vlan_dev.c11
-rw-r--r--net/core/dev.c19
-rw-r--r--net/ipv4/ip_gre.c3
-rw-r--r--net/ipv4/ipip.c3
-rw-r--r--net/ipv6/ip6_tunnel.c3
-rw-r--r--net/ipv6/ip6mr.c3
-rw-r--r--net/ipv6/sit.c3
11 files changed, 26 insertions, 34 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 4b0e30b564e5..2d9663a1c54d 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -64,7 +64,6 @@ struct pcpu_lstats {
64 u64 packets; 64 u64 packets;
65 u64 bytes; 65 u64 bytes;
66 struct u64_stats_sync syncp; 66 struct u64_stats_sync syncp;
67 unsigned long drops;
68}; 67};
69 68
70/* 69/*
@@ -90,8 +89,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
90 lb_stats->bytes += len; 89 lb_stats->bytes += len;
91 lb_stats->packets++; 90 lb_stats->packets++;
92 u64_stats_update_end(&lb_stats->syncp); 91 u64_stats_update_end(&lb_stats->syncp);
93 } else 92 }
94 lb_stats->drops++;
95 93
96 return NETDEV_TX_OK; 94 return NETDEV_TX_OK;
97} 95}
@@ -101,7 +99,6 @@ static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev,
101{ 99{
102 u64 bytes = 0; 100 u64 bytes = 0;
103 u64 packets = 0; 101 u64 packets = 0;
104 u64 drops = 0;
105 int i; 102 int i;
106 103
107 for_each_possible_cpu(i) { 104 for_each_possible_cpu(i) {
@@ -115,14 +112,11 @@ static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev,
115 tbytes = lb_stats->bytes; 112 tbytes = lb_stats->bytes;
116 tpackets = lb_stats->packets; 113 tpackets = lb_stats->packets;
117 } while (u64_stats_fetch_retry(&lb_stats->syncp, start)); 114 } while (u64_stats_fetch_retry(&lb_stats->syncp, start));
118 drops += lb_stats->drops;
119 bytes += tbytes; 115 bytes += tbytes;
120 packets += tpackets; 116 packets += tpackets;
121 } 117 }
122 stats->rx_packets = packets; 118 stats->rx_packets = packets;
123 stats->tx_packets = packets; 119 stats->tx_packets = packets;
124 stats->rx_dropped = drops;
125 stats->rx_errors = drops;
126 stats->rx_bytes = bytes; 120 stats->rx_bytes = bytes;
127 stats->tx_bytes = bytes; 121 stats->tx_bytes = bytes;
128 return stats; 122 return stats;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 92d81edd5808..6abcef67b178 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -884,6 +884,9 @@ struct net_device {
884 int iflink; 884 int iflink;
885 885
886 struct net_device_stats stats; 886 struct net_device_stats stats;
887 atomic_long_t rx_dropped; /* dropped packets by core network
888 * Do not use this in drivers.
889 */
887 890
888#ifdef CONFIG_WIRELESS_EXT 891#ifdef CONFIG_WIRELESS_EXT
889 /* List of functions to handle Wireless Extensions (instead of ioctl). 892 /* List of functions to handle Wireless Extensions (instead of ioctl).
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index b26ce343072c..8d9503ad01da 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -25,7 +25,6 @@ struct vlan_priority_tci_mapping {
25 * @rx_multicast: number of received multicast packets 25 * @rx_multicast: number of received multicast packets
26 * @syncp: synchronization point for 64bit counters 26 * @syncp: synchronization point for 64bit counters
27 * @rx_errors: number of errors 27 * @rx_errors: number of errors
28 * @rx_dropped: number of dropped packets
29 */ 28 */
30struct vlan_rx_stats { 29struct vlan_rx_stats {
31 u64 rx_packets; 30 u64 rx_packets;
@@ -33,7 +32,6 @@ struct vlan_rx_stats {
33 u64 rx_multicast; 32 u64 rx_multicast;
34 struct u64_stats_sync syncp; 33 struct u64_stats_sync syncp;
35 unsigned long rx_errors; 34 unsigned long rx_errors;
36 unsigned long rx_dropped;
37}; 35};
38 36
39/** 37/**
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index b6d55a9304f2..dee727ce0291 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -33,6 +33,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
33 return polling ? netif_receive_skb(skb) : netif_rx(skb); 33 return polling ? netif_receive_skb(skb) : netif_rx(skb);
34 34
35drop: 35drop:
36 atomic_long_inc(&skb->dev->rx_dropped);
36 dev_kfree_skb_any(skb); 37 dev_kfree_skb_any(skb);
37 return NET_RX_DROP; 38 return NET_RX_DROP;
38} 39}
@@ -123,6 +124,7 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
123 return dev_gro_receive(napi, skb); 124 return dev_gro_receive(napi, skb);
124 125
125drop: 126drop:
127 atomic_long_inc(&skb->dev->rx_dropped);
126 return GRO_DROP; 128 return GRO_DROP;
127} 129}
128 130
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index f6fbcc0f1af9..f54251edd40d 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -225,16 +225,15 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
225 } 225 }
226 } 226 }
227 227
228 if (unlikely(netif_rx(skb) == NET_RX_DROP)) { 228 netif_rx(skb);
229 if (rx_stats) 229
230 rx_stats->rx_dropped++;
231 }
232 rcu_read_unlock(); 230 rcu_read_unlock();
233 return NET_RX_SUCCESS; 231 return NET_RX_SUCCESS;
234 232
235err_unlock: 233err_unlock:
236 rcu_read_unlock(); 234 rcu_read_unlock();
237err_free: 235err_free:
236 atomic_long_inc(&dev->rx_dropped);
238 kfree_skb(skb); 237 kfree_skb(skb);
239 return NET_RX_DROP; 238 return NET_RX_DROP;
240} 239}
@@ -846,15 +845,13 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st
846 accum.rx_packets += rxpackets; 845 accum.rx_packets += rxpackets;
847 accum.rx_bytes += rxbytes; 846 accum.rx_bytes += rxbytes;
848 accum.rx_multicast += rxmulticast; 847 accum.rx_multicast += rxmulticast;
849 /* rx_errors, rx_dropped are ulong, not protected by syncp */ 848 /* rx_errors is ulong, not protected by syncp */
850 accum.rx_errors += p->rx_errors; 849 accum.rx_errors += p->rx_errors;
851 accum.rx_dropped += p->rx_dropped;
852 } 850 }
853 stats->rx_packets = accum.rx_packets; 851 stats->rx_packets = accum.rx_packets;
854 stats->rx_bytes = accum.rx_bytes; 852 stats->rx_bytes = accum.rx_bytes;
855 stats->rx_errors = accum.rx_errors; 853 stats->rx_errors = accum.rx_errors;
856 stats->multicast = accum.rx_multicast; 854 stats->multicast = accum.rx_multicast;
857 stats->rx_dropped = accum.rx_dropped;
858 } 855 }
859 return stats; 856 return stats;
860} 857}
diff --git a/net/core/dev.c b/net/core/dev.c
index ce6ad88c980b..7d149550e8d6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1483,8 +1483,9 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
1483 skb_orphan(skb); 1483 skb_orphan(skb);
1484 nf_reset(skb); 1484 nf_reset(skb);
1485 1485
1486 if (!(dev->flags & IFF_UP) || 1486 if (unlikely(!(dev->flags & IFF_UP) ||
1487 (skb->len > (dev->mtu + dev->hard_header_len))) { 1487 (skb->len > (dev->mtu + dev->hard_header_len)))) {
1488 atomic_long_inc(&dev->rx_dropped);
1488 kfree_skb(skb); 1489 kfree_skb(skb);
1489 return NET_RX_DROP; 1490 return NET_RX_DROP;
1490 } 1491 }
@@ -2548,6 +2549,7 @@ enqueue:
2548 2549
2549 local_irq_restore(flags); 2550 local_irq_restore(flags);
2550 2551
2552 atomic_long_inc(&skb->dev->rx_dropped);
2551 kfree_skb(skb); 2553 kfree_skb(skb);
2552 return NET_RX_DROP; 2554 return NET_RX_DROP;
2553} 2555}
@@ -2995,6 +2997,7 @@ ncls:
2995 if (pt_prev) { 2997 if (pt_prev) {
2996 ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); 2998 ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
2997 } else { 2999 } else {
3000 atomic_long_inc(&skb->dev->rx_dropped);
2998 kfree_skb(skb); 3001 kfree_skb(skb);
2999 /* Jamal, now you will not able to escape explaining 3002 /* Jamal, now you will not able to escape explaining
3000 * me how you were going to use this. :-) 3003 * me how you were going to use this. :-)
@@ -5429,14 +5432,14 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
5429 5432
5430 if (ops->ndo_get_stats64) { 5433 if (ops->ndo_get_stats64) {
5431 memset(storage, 0, sizeof(*storage)); 5434 memset(storage, 0, sizeof(*storage));
5432 return ops->ndo_get_stats64(dev, storage); 5435 ops->ndo_get_stats64(dev, storage);
5433 } 5436 } else if (ops->ndo_get_stats) {
5434 if (ops->ndo_get_stats) {
5435 netdev_stats_to_stats64(storage, ops->ndo_get_stats(dev)); 5437 netdev_stats_to_stats64(storage, ops->ndo_get_stats(dev));
5436 return storage; 5438 } else {
5439 netdev_stats_to_stats64(storage, &dev->stats);
5440 dev_txq_stats_fold(dev, storage);
5437 } 5441 }
5438 netdev_stats_to_stats64(storage, &dev->stats); 5442 storage->rx_dropped += atomic_long_read(&dev->rx_dropped);
5439 dev_txq_stats_fold(dev, storage);
5440 return storage; 5443 return storage;
5441} 5444}
5442EXPORT_SYMBOL(dev_get_stats); 5445EXPORT_SYMBOL(dev_get_stats);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index fbe2c473a06a..9d421f4cf3ef 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -679,8 +679,7 @@ static int ipgre_rcv(struct sk_buff *skb)
679 skb_reset_network_header(skb); 679 skb_reset_network_header(skb);
680 ipgre_ecn_decapsulate(iph, skb); 680 ipgre_ecn_decapsulate(iph, skb);
681 681
682 if (netif_rx(skb) == NET_RX_DROP) 682 netif_rx(skb);
683 tunnel->dev->stats.rx_dropped++;
684 683
685 rcu_read_unlock(); 684 rcu_read_unlock();
686 return 0; 685 return 0;
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 6ad46c28ede2..e9b816e6cd73 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -414,8 +414,7 @@ static int ipip_rcv(struct sk_buff *skb)
414 414
415 ipip_ecn_decapsulate(iph, skb); 415 ipip_ecn_decapsulate(iph, skb);
416 416
417 if (netif_rx(skb) == NET_RX_DROP) 417 netif_rx(skb);
418 tunnel->dev->stats.rx_dropped++;
419 418
420 rcu_read_unlock(); 419 rcu_read_unlock();
421 return 0; 420 return 0;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 8be3c452af90..c2c0f89397b1 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -768,8 +768,7 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
768 768
769 dscp_ecn_decapsulate(t, ipv6h, skb); 769 dscp_ecn_decapsulate(t, ipv6h, skb);
770 770
771 if (netif_rx(skb) == NET_RX_DROP) 771 netif_rx(skb);
772 t->dev->stats.rx_dropped++;
773 772
774 rcu_read_unlock(); 773 rcu_read_unlock();
775 return 0; 774 return 0;
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 2640c9be589d..6f32ffce7022 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -666,8 +666,7 @@ static int pim6_rcv(struct sk_buff *skb)
666 666
667 skb_tunnel_rx(skb, reg_dev); 667 skb_tunnel_rx(skb, reg_dev);
668 668
669 if (netif_rx(skb) == NET_RX_DROP) 669 netif_rx(skb);
670 reg_dev->stats.rx_dropped++;
671 670
672 dev_put(reg_dev); 671 dev_put(reg_dev);
673 return 0; 672 return 0;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index d7701782b639..367a6cc584cc 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -600,8 +600,7 @@ static int ipip6_rcv(struct sk_buff *skb)
600 600
601 ipip6_ecn_decapsulate(iph, skb); 601 ipip6_ecn_decapsulate(iph, skb);
602 602
603 if (netif_rx(skb) == NET_RX_DROP) 603 netif_rx(skb);
604 tunnel->dev->stats.rx_dropped++;
605 604
606 rcu_read_unlock(); 605 rcu_read_unlock();
607 return 0; 606 return 0;