diff options
author | Eric Dumazet <edumazet@google.com> | 2013-04-29 04:39:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-04-29 15:14:03 -0400 |
commit | 6a5dc9e598fe90160fee7de098fa319665f5253e (patch) | |
tree | 7f2c2130e3dec81aea01e997cec7e87744f02694 /net/ipv4 | |
parent | f233a976ad15c3b8c54c0157f3c41d23f7514279 (diff) |
net: Add MIB counters for checksum errors
Add MIB counters for checksum errors in IP layer,
and TCP/UDP/ICMP layers, to help diagnose problems.
$ nstat -a | grep Csum
IcmpInCsumErrors 72 0.0
TcpInCsumErrors 382 0.0
UdpInCsumErrors 463221 0.0
Icmp6InCsumErrors 75 0.0
Udp6InCsumErrors 173442 0.0
IpExtInCsumErrors 10884 0.0
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/icmp.c | 4 | ||||
-rw-r--r-- | net/ipv4/ip_input.c | 4 | ||||
-rw-r--r-- | net/ipv4/proc.c | 10 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 14 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 3 | ||||
-rw-r--r-- | net/ipv4/udp.c | 11 |
7 files changed, 35 insertions, 12 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 3ac5dff79627..76e10b47e053 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -881,7 +881,7 @@ int icmp_rcv(struct sk_buff *skb) | |||
881 | case CHECKSUM_NONE: | 881 | case CHECKSUM_NONE: |
882 | skb->csum = 0; | 882 | skb->csum = 0; |
883 | if (__skb_checksum_complete(skb)) | 883 | if (__skb_checksum_complete(skb)) |
884 | goto error; | 884 | goto csum_error; |
885 | } | 885 | } |
886 | 886 | ||
887 | if (!pskb_pull(skb, sizeof(*icmph))) | 887 | if (!pskb_pull(skb, sizeof(*icmph))) |
@@ -929,6 +929,8 @@ int icmp_rcv(struct sk_buff *skb) | |||
929 | drop: | 929 | drop: |
930 | kfree_skb(skb); | 930 | kfree_skb(skb); |
931 | return 0; | 931 | return 0; |
932 | csum_error: | ||
933 | ICMP_INC_STATS_BH(net, ICMP_MIB_CSUMERRORS); | ||
932 | error: | 934 | error: |
933 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); | 935 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); |
934 | goto drop; | 936 | goto drop; |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 2bdf802e28e2..3da817b89e9b 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -419,7 +419,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, | |||
419 | iph = ip_hdr(skb); | 419 | iph = ip_hdr(skb); |
420 | 420 | ||
421 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) | 421 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) |
422 | goto inhdr_error; | 422 | goto csum_error; |
423 | 423 | ||
424 | len = ntohs(iph->tot_len); | 424 | len = ntohs(iph->tot_len); |
425 | if (skb->len < len) { | 425 | if (skb->len < len) { |
@@ -446,6 +446,8 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, | |||
446 | return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL, | 446 | return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL, |
447 | ip_rcv_finish); | 447 | ip_rcv_finish); |
448 | 448 | ||
449 | csum_error: | ||
450 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_CSUMERRORS); | ||
449 | inhdr_error: | 451 | inhdr_error: |
450 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS); | 452 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS); |
451 | drop: | 453 | drop: |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 6da51d55d03a..2a5bf86d2415 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -125,6 +125,7 @@ static const struct snmp_mib snmp4_ipextstats_list[] = { | |||
125 | SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS), | 125 | SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS), |
126 | SNMP_MIB_ITEM("InBcastOctets", IPSTATS_MIB_INBCASTOCTETS), | 126 | SNMP_MIB_ITEM("InBcastOctets", IPSTATS_MIB_INBCASTOCTETS), |
127 | SNMP_MIB_ITEM("OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS), | 127 | SNMP_MIB_ITEM("OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS), |
128 | SNMP_MIB_ITEM("InCsumErrors", IPSTATS_MIB_CSUMERRORS), | ||
128 | SNMP_MIB_SENTINEL | 129 | SNMP_MIB_SENTINEL |
129 | }; | 130 | }; |
130 | 131 | ||
@@ -162,6 +163,7 @@ static const struct snmp_mib snmp4_tcp_list[] = { | |||
162 | SNMP_MIB_ITEM("RetransSegs", TCP_MIB_RETRANSSEGS), | 163 | SNMP_MIB_ITEM("RetransSegs", TCP_MIB_RETRANSSEGS), |
163 | SNMP_MIB_ITEM("InErrs", TCP_MIB_INERRS), | 164 | SNMP_MIB_ITEM("InErrs", TCP_MIB_INERRS), |
164 | SNMP_MIB_ITEM("OutRsts", TCP_MIB_OUTRSTS), | 165 | SNMP_MIB_ITEM("OutRsts", TCP_MIB_OUTRSTS), |
166 | SNMP_MIB_ITEM("InCsumErrors", TCP_MIB_CSUMERRORS), | ||
165 | SNMP_MIB_SENTINEL | 167 | SNMP_MIB_SENTINEL |
166 | }; | 168 | }; |
167 | 169 | ||
@@ -172,6 +174,7 @@ static const struct snmp_mib snmp4_udp_list[] = { | |||
172 | SNMP_MIB_ITEM("OutDatagrams", UDP_MIB_OUTDATAGRAMS), | 174 | SNMP_MIB_ITEM("OutDatagrams", UDP_MIB_OUTDATAGRAMS), |
173 | SNMP_MIB_ITEM("RcvbufErrors", UDP_MIB_RCVBUFERRORS), | 175 | SNMP_MIB_ITEM("RcvbufErrors", UDP_MIB_RCVBUFERRORS), |
174 | SNMP_MIB_ITEM("SndbufErrors", UDP_MIB_SNDBUFERRORS), | 176 | SNMP_MIB_ITEM("SndbufErrors", UDP_MIB_SNDBUFERRORS), |
177 | SNMP_MIB_ITEM("InCsumErrors", UDP_MIB_CSUMERRORS), | ||
175 | SNMP_MIB_SENTINEL | 178 | SNMP_MIB_SENTINEL |
176 | }; | 179 | }; |
177 | 180 | ||
@@ -322,15 +325,16 @@ static void icmp_put(struct seq_file *seq) | |||
322 | struct net *net = seq->private; | 325 | struct net *net = seq->private; |
323 | atomic_long_t *ptr = net->mib.icmpmsg_statistics->mibs; | 326 | atomic_long_t *ptr = net->mib.icmpmsg_statistics->mibs; |
324 | 327 | ||
325 | seq_puts(seq, "\nIcmp: InMsgs InErrors"); | 328 | seq_puts(seq, "\nIcmp: InMsgs InErrors InCsumErrors"); |
326 | for (i=0; icmpmibmap[i].name != NULL; i++) | 329 | for (i=0; icmpmibmap[i].name != NULL; i++) |
327 | seq_printf(seq, " In%s", icmpmibmap[i].name); | 330 | seq_printf(seq, " In%s", icmpmibmap[i].name); |
328 | seq_printf(seq, " OutMsgs OutErrors"); | 331 | seq_printf(seq, " OutMsgs OutErrors"); |
329 | for (i=0; icmpmibmap[i].name != NULL; i++) | 332 | for (i=0; icmpmibmap[i].name != NULL; i++) |
330 | seq_printf(seq, " Out%s", icmpmibmap[i].name); | 333 | seq_printf(seq, " Out%s", icmpmibmap[i].name); |
331 | seq_printf(seq, "\nIcmp: %lu %lu", | 334 | seq_printf(seq, "\nIcmp: %lu %lu %lu", |
332 | snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INMSGS), | 335 | snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INMSGS), |
333 | snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INERRORS)); | 336 | snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INERRORS), |
337 | snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_CSUMERRORS)); | ||
334 | for (i=0; icmpmibmap[i].name != NULL; i++) | 338 | for (i=0; icmpmibmap[i].name != NULL; i++) |
335 | seq_printf(seq, " %lu", | 339 | seq_printf(seq, " %lu", |
336 | atomic_long_read(ptr + icmpmibmap[i].index)); | 340 | atomic_long_read(ptr + icmpmibmap[i].index)); |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index aafd052865ba..08bbe6096528 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -5273,6 +5273,7 @@ step5: | |||
5273 | return 0; | 5273 | return 0; |
5274 | 5274 | ||
5275 | csum_error: | 5275 | csum_error: |
5276 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS); | ||
5276 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); | 5277 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); |
5277 | 5278 | ||
5278 | discard: | 5279 | discard: |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 2278669b1d85..8ea975164596 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1866,6 +1866,7 @@ discard: | |||
1866 | return 0; | 1866 | return 0; |
1867 | 1867 | ||
1868 | csum_err: | 1868 | csum_err: |
1869 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS); | ||
1869 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); | 1870 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); |
1870 | goto discard; | 1871 | goto discard; |
1871 | } | 1872 | } |
@@ -1985,7 +1986,7 @@ int tcp_v4_rcv(struct sk_buff *skb) | |||
1985 | * provided case of th->doff==0 is eliminated. | 1986 | * provided case of th->doff==0 is eliminated. |
1986 | * So, we defer the checks. */ | 1987 | * So, we defer the checks. */ |
1987 | if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb)) | 1988 | if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb)) |
1988 | goto bad_packet; | 1989 | goto csum_error; |
1989 | 1990 | ||
1990 | th = tcp_hdr(skb); | 1991 | th = tcp_hdr(skb); |
1991 | iph = ip_hdr(skb); | 1992 | iph = ip_hdr(skb); |
@@ -2051,6 +2052,8 @@ no_tcp_socket: | |||
2051 | goto discard_it; | 2052 | goto discard_it; |
2052 | 2053 | ||
2053 | if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) { | 2054 | if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) { |
2055 | csum_error: | ||
2056 | TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); | ||
2054 | bad_packet: | 2057 | bad_packet: |
2055 | TCP_INC_STATS_BH(net, TCP_MIB_INERRS); | 2058 | TCP_INC_STATS_BH(net, TCP_MIB_INERRS); |
2056 | } else { | 2059 | } else { |
@@ -2072,10 +2075,13 @@ do_time_wait: | |||
2072 | goto discard_it; | 2075 | goto discard_it; |
2073 | } | 2076 | } |
2074 | 2077 | ||
2075 | if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) { | 2078 | if (skb->len < (th->doff << 2)) { |
2076 | TCP_INC_STATS_BH(net, TCP_MIB_INERRS); | ||
2077 | inet_twsk_put(inet_twsk(sk)); | 2079 | inet_twsk_put(inet_twsk(sk)); |
2078 | goto discard_it; | 2080 | goto bad_packet; |
2081 | } | ||
2082 | if (tcp_checksum_complete(skb)) { | ||
2083 | inet_twsk_put(inet_twsk(sk)); | ||
2084 | goto csum_error; | ||
2079 | } | 2085 | } |
2080 | switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { | 2086 | switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { |
2081 | case TCP_TW_SYN: { | 2087 | case TCP_TW_SYN: { |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index b735c23a961d..536d40929ba6 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -80,8 +80,9 @@ static void tcp_event_new_data_sent(struct sock *sk, const struct sk_buff *skb) | |||
80 | 80 | ||
81 | tp->packets_out += tcp_skb_pcount(skb); | 81 | tp->packets_out += tcp_skb_pcount(skb); |
82 | if (!prior_packets || icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS || | 82 | if (!prior_packets || icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS || |
83 | icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) | 83 | icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) { |
84 | tcp_rearm_rto(sk); | 84 | tcp_rearm_rto(sk); |
85 | } | ||
85 | } | 86 | } |
86 | 87 | ||
87 | /* SND.NXT, if window was not shrunk. | 88 | /* SND.NXT, if window was not shrunk. |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 2722db024a0b..3159d16441d0 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1131,6 +1131,8 @@ static unsigned int first_packet_length(struct sock *sk) | |||
1131 | spin_lock_bh(&rcvq->lock); | 1131 | spin_lock_bh(&rcvq->lock); |
1132 | while ((skb = skb_peek(rcvq)) != NULL && | 1132 | while ((skb = skb_peek(rcvq)) != NULL && |
1133 | udp_lib_checksum_complete(skb)) { | 1133 | udp_lib_checksum_complete(skb)) { |
1134 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, | ||
1135 | IS_UDPLITE(sk)); | ||
1134 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, | 1136 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, |
1135 | IS_UDPLITE(sk)); | 1137 | IS_UDPLITE(sk)); |
1136 | atomic_inc(&sk->sk_drops); | 1138 | atomic_inc(&sk->sk_drops); |
@@ -1286,8 +1288,10 @@ out: | |||
1286 | 1288 | ||
1287 | csum_copy_err: | 1289 | csum_copy_err: |
1288 | slow = lock_sock_fast(sk); | 1290 | slow = lock_sock_fast(sk); |
1289 | if (!skb_kill_datagram(sk, skb, flags)) | 1291 | if (!skb_kill_datagram(sk, skb, flags)) { |
1292 | UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); | ||
1290 | UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); | 1293 | UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); |
1294 | } | ||
1291 | unlock_sock_fast(sk, slow); | 1295 | unlock_sock_fast(sk, slow); |
1292 | 1296 | ||
1293 | if (noblock) | 1297 | if (noblock) |
@@ -1513,7 +1517,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1513 | 1517 | ||
1514 | if (rcu_access_pointer(sk->sk_filter) && | 1518 | if (rcu_access_pointer(sk->sk_filter) && |
1515 | udp_lib_checksum_complete(skb)) | 1519 | udp_lib_checksum_complete(skb)) |
1516 | goto drop; | 1520 | goto csum_error; |
1517 | 1521 | ||
1518 | 1522 | ||
1519 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) | 1523 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) |
@@ -1533,6 +1537,8 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1533 | 1537 | ||
1534 | return rc; | 1538 | return rc; |
1535 | 1539 | ||
1540 | csum_error: | ||
1541 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); | ||
1536 | drop: | 1542 | drop: |
1537 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); | 1543 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); |
1538 | atomic_inc(&sk->sk_drops); | 1544 | atomic_inc(&sk->sk_drops); |
@@ -1749,6 +1755,7 @@ csum_error: | |||
1749 | proto == IPPROTO_UDPLITE ? "Lite" : "", | 1755 | proto == IPPROTO_UDPLITE ? "Lite" : "", |
1750 | &saddr, ntohs(uh->source), &daddr, ntohs(uh->dest), | 1756 | &saddr, ntohs(uh->source), &daddr, ntohs(uh->dest), |
1751 | ulen); | 1757 | ulen); |
1758 | UDP_INC_STATS_BH(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); | ||
1752 | drop: | 1759 | drop: |
1753 | UDP_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); | 1760 | UDP_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); |
1754 | kfree_skb(skb); | 1761 | kfree_skb(skb); |