Commit 6a5dc9e598fe90160fee7de098fa319665f5253e

Authored by Eric Dumazet
Committed by David S. Miller
1 parent f233a976ad

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>

Showing 12 changed files with 72 additions and 28 deletions Side-by-side Diff

include/uapi/linux/snmp.h
... ... @@ -50,6 +50,7 @@
50 50 IPSTATS_MIB_OUTMCASTOCTETS, /* OutMcastOctets */
51 51 IPSTATS_MIB_INBCASTOCTETS, /* InBcastOctets */
52 52 IPSTATS_MIB_OUTBCASTOCTETS, /* OutBcastOctets */
  53 + IPSTATS_MIB_CSUMERRORS, /* InCsumErrors */
53 54 __IPSTATS_MIB_MAX
54 55 };
55 56  
... ... @@ -87,6 +88,7 @@
87 88 ICMP_MIB_OUTTIMESTAMPREPS, /* OutTimestampReps */
88 89 ICMP_MIB_OUTADDRMASKS, /* OutAddrMasks */
89 90 ICMP_MIB_OUTADDRMASKREPS, /* OutAddrMaskReps */
  91 + ICMP_MIB_CSUMERRORS, /* InCsumErrors */
90 92 __ICMP_MIB_MAX
91 93 };
92 94  
... ... @@ -103,6 +105,7 @@
103 105 ICMP6_MIB_INERRORS, /* InErrors */
104 106 ICMP6_MIB_OUTMSGS, /* OutMsgs */
105 107 ICMP6_MIB_OUTERRORS, /* OutErrors */
  108 + ICMP6_MIB_CSUMERRORS, /* InCsumErrors */
106 109 __ICMP6_MIB_MAX
107 110 };
108 111  
... ... @@ -130,6 +133,7 @@
130 133 TCP_MIB_RETRANSSEGS, /* RetransSegs */
131 134 TCP_MIB_INERRS, /* InErrs */
132 135 TCP_MIB_OUTRSTS, /* OutRsts */
  136 + TCP_MIB_CSUMERRORS, /* InCsumErrors */
133 137 __TCP_MIB_MAX
134 138 };
135 139  
... ... @@ -147,6 +151,7 @@
147 151 UDP_MIB_OUTDATAGRAMS, /* OutDatagrams */
148 152 UDP_MIB_RCVBUFERRORS, /* RcvbufErrors */
149 153 UDP_MIB_SNDBUFERRORS, /* SndbufErrors */
  154 + UDP_MIB_CSUMERRORS, /* InCsumErrors */
150 155 __UDP_MIB_MAX
151 156 };
152 157  
... ... @@ -881,7 +881,7 @@
881 881 case CHECKSUM_NONE:
882 882 skb->csum = 0;
883 883 if (__skb_checksum_complete(skb))
884   - goto error;
  884 + goto csum_error;
885 885 }
886 886  
887 887 if (!pskb_pull(skb, sizeof(*icmph)))
... ... @@ -929,6 +929,8 @@
929 929 drop:
930 930 kfree_skb(skb);
931 931 return 0;
  932 +csum_error:
  933 + ICMP_INC_STATS_BH(net, ICMP_MIB_CSUMERRORS);
932 934 error:
933 935 ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
934 936 goto drop;
... ... @@ -419,7 +419,7 @@
419 419 iph = ip_hdr(skb);
420 420  
421 421 if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
422   - goto inhdr_error;
  422 + goto csum_error;
423 423  
424 424 len = ntohs(iph->tot_len);
425 425 if (skb->len < len) {
... ... @@ -446,6 +446,8 @@
446 446 return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL,
447 447 ip_rcv_finish);
448 448  
  449 +csum_error:
  450 + IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_CSUMERRORS);
449 451 inhdr_error:
450 452 IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
451 453 drop:
... ... @@ -125,6 +125,7 @@
125 125 SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
126 126 SNMP_MIB_ITEM("InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
127 127 SNMP_MIB_ITEM("OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
  128 + SNMP_MIB_ITEM("InCsumErrors", IPSTATS_MIB_CSUMERRORS),
128 129 SNMP_MIB_SENTINEL
129 130 };
130 131  
... ... @@ -162,6 +163,7 @@
162 163 SNMP_MIB_ITEM("RetransSegs", TCP_MIB_RETRANSSEGS),
163 164 SNMP_MIB_ITEM("InErrs", TCP_MIB_INERRS),
164 165 SNMP_MIB_ITEM("OutRsts", TCP_MIB_OUTRSTS),
  166 + SNMP_MIB_ITEM("InCsumErrors", TCP_MIB_CSUMERRORS),
165 167 SNMP_MIB_SENTINEL
166 168 };
167 169  
... ... @@ -172,6 +174,7 @@
172 174 SNMP_MIB_ITEM("OutDatagrams", UDP_MIB_OUTDATAGRAMS),
173 175 SNMP_MIB_ITEM("RcvbufErrors", UDP_MIB_RCVBUFERRORS),
174 176 SNMP_MIB_ITEM("SndbufErrors", UDP_MIB_SNDBUFERRORS),
  177 + SNMP_MIB_ITEM("InCsumErrors", UDP_MIB_CSUMERRORS),
175 178 SNMP_MIB_SENTINEL
176 179 };
177 180  
178 181  
179 182  
... ... @@ -322,15 +325,16 @@
322 325 struct net *net = seq->private;
323 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 329 for (i=0; icmpmibmap[i].name != NULL; i++)
327 330 seq_printf(seq, " In%s", icmpmibmap[i].name);
328 331 seq_printf(seq, " OutMsgs OutErrors");
329 332 for (i=0; icmpmibmap[i].name != NULL; i++)
330 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 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 338 for (i=0; icmpmibmap[i].name != NULL; i++)
335 339 seq_printf(seq, " %lu",
336 340 atomic_long_read(ptr + icmpmibmap[i].index));
net/ipv4/tcp_input.c
... ... @@ -5273,6 +5273,7 @@
5273 5273 return 0;
5274 5274  
5275 5275 csum_error:
  5276 + TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS);
5276 5277 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
5277 5278  
5278 5279 discard:
... ... @@ -1866,6 +1866,7 @@
1866 1866 return 0;
1867 1867  
1868 1868 csum_err:
  1869 + TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS);
1869 1870 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
1870 1871 goto discard;
1871 1872 }
... ... @@ -1985,7 +1986,7 @@
1985 1986 * provided case of th->doff==0 is eliminated.
1986 1987 * So, we defer the checks. */
1987 1988 if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb))
1988   - goto bad_packet;
  1989 + goto csum_error;
1989 1990  
1990 1991 th = tcp_hdr(skb);
1991 1992 iph = ip_hdr(skb);
... ... @@ -2051,6 +2052,8 @@
2051 2052 goto discard_it;
2052 2053  
2053 2054 if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
  2055 +csum_error:
  2056 + TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS);
2054 2057 bad_packet:
2055 2058 TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
2056 2059 } else {
2057 2060  
... ... @@ -2072,10 +2075,13 @@
2072 2075 goto discard_it;
2073 2076 }
2074 2077  
2075   - if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
2076   - TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
  2078 + if (skb->len < (th->doff << 2)) {
2077 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 2086 switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
2081 2087 case TCP_TW_SYN: {
net/ipv4/tcp_output.c
... ... @@ -80,8 +80,9 @@
80 80  
81 81 tp->packets_out += tcp_skb_pcount(skb);
82 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 84 tcp_rearm_rto(sk);
  85 + }
85 86 }
86 87  
87 88 /* SND.NXT, if window was not shrunk.
... ... @@ -1131,6 +1131,8 @@
1131 1131 spin_lock_bh(&rcvq->lock);
1132 1132 while ((skb = skb_peek(rcvq)) != NULL &&
1133 1133 udp_lib_checksum_complete(skb)) {
  1134 + UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS,
  1135 + IS_UDPLITE(sk));
1134 1136 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS,
1135 1137 IS_UDPLITE(sk));
1136 1138 atomic_inc(&sk->sk_drops);
1137 1139  
... ... @@ -1286,8 +1288,10 @@
1286 1288  
1287 1289 csum_copy_err:
1288 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 1293 UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
  1294 + }
1291 1295 unlock_sock_fast(sk, slow);
1292 1296  
1293 1297 if (noblock)
... ... @@ -1513,7 +1517,7 @@
1513 1517  
1514 1518 if (rcu_access_pointer(sk->sk_filter) &&
1515 1519 udp_lib_checksum_complete(skb))
1516   - goto drop;
  1520 + goto csum_error;
1517 1521  
1518 1522  
1519 1523 if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf))
... ... @@ -1533,6 +1537,8 @@
1533 1537  
1534 1538 return rc;
1535 1539  
  1540 +csum_error:
  1541 + UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
1536 1542 drop:
1537 1543 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
1538 1544 atomic_inc(&sk->sk_drops);
... ... @@ -1749,6 +1755,7 @@
1749 1755 proto == IPPROTO_UDPLITE ? "Lite" : "",
1750 1756 &saddr, ntohs(uh->source), &daddr, ntohs(uh->dest),
1751 1757 ulen);
  1758 + UDP_INC_STATS_BH(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE);
1752 1759 drop:
1753 1760 UDP_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);
1754 1761 kfree_skb(skb);
... ... @@ -699,7 +699,7 @@
699 699 if (__skb_checksum_complete(skb)) {
700 700 LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n",
701 701 saddr, daddr);
702   - goto discard_it;
  702 + goto csum_error;
703 703 }
704 704 }
705 705  
... ... @@ -785,6 +785,8 @@
785 785 kfree_skb(skb);
786 786 return 0;
787 787  
  788 +csum_error:
  789 + ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_CSUMERRORS);
788 790 discard_it:
789 791 ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_INERRORS);
790 792 drop_no_count:
... ... @@ -90,6 +90,7 @@
90 90 SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
91 91 SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
92 92 SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
  93 + SNMP_MIB_ITEM("InCsumErrors", IPSTATS_MIB_CSUMERRORS),
93 94 SNMP_MIB_SENTINEL
94 95 };
95 96  
... ... @@ -99,6 +100,7 @@
99 100 SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS),
100 101 SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS),
101 102 SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS),
  103 + SNMP_MIB_ITEM("Icmp6InCsumErrors", ICMP6_MIB_CSUMERRORS),
102 104 SNMP_MIB_SENTINEL
103 105 };
104 106  
... ... @@ -129,6 +131,7 @@
129 131 SNMP_MIB_ITEM("Udp6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
130 132 SNMP_MIB_ITEM("Udp6RcvbufErrors", UDP_MIB_RCVBUFERRORS),
131 133 SNMP_MIB_ITEM("Udp6SndbufErrors", UDP_MIB_SNDBUFERRORS),
  134 + SNMP_MIB_ITEM("Udp6InCsumErrors", UDP_MIB_CSUMERRORS),
132 135 SNMP_MIB_SENTINEL
133 136 };
134 137  
... ... @@ -139,6 +142,7 @@
139 142 SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
140 143 SNMP_MIB_ITEM("UdpLite6RcvbufErrors", UDP_MIB_RCVBUFERRORS),
141 144 SNMP_MIB_ITEM("UdpLite6SndbufErrors", UDP_MIB_SNDBUFERRORS),
  145 + SNMP_MIB_ITEM("UdpLite6InCsumErrors", UDP_MIB_CSUMERRORS),
142 146 SNMP_MIB_SENTINEL
143 147 };
144 148  
... ... @@ -1405,6 +1405,7 @@
1405 1405 kfree_skb(skb);
1406 1406 return 0;
1407 1407 csum_err:
  1408 + TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS);
1408 1409 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
1409 1410 goto discard;
1410 1411  
... ... @@ -1466,7 +1467,7 @@
1466 1467 goto discard_it;
1467 1468  
1468 1469 if (!skb_csum_unnecessary(skb) && tcp_v6_checksum_init(skb))
1469   - goto bad_packet;
  1470 + goto csum_error;
1470 1471  
1471 1472 th = tcp_hdr(skb);
1472 1473 hdr = ipv6_hdr(skb);
... ... @@ -1530,6 +1531,8 @@
1530 1531 goto discard_it;
1531 1532  
1532 1533 if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
  1534 +csum_error:
  1535 + TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS);
1533 1536 bad_packet:
1534 1537 TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
1535 1538 } else {
... ... @@ -1537,11 +1540,6 @@
1537 1540 }
1538 1541  
1539 1542 discard_it:
1540   -
1541   - /*
1542   - * Discard frame
1543   - */
1544   -
1545 1543 kfree_skb(skb);
1546 1544 return 0;
1547 1545  
1548 1546  
... ... @@ -1555,10 +1553,13 @@
1555 1553 goto discard_it;
1556 1554 }
1557 1555  
1558   - if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
1559   - TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
  1556 + if (skb->len < (th->doff<<2)) {
1560 1557 inet_twsk_put(inet_twsk(sk));
1561   - goto discard_it;
  1558 + goto bad_packet;
  1559 + }
  1560 + if (tcp_checksum_complete(skb)) {
  1561 + inet_twsk_put(inet_twsk(sk));
  1562 + goto csum_error;
1562 1563 }
1563 1564  
1564 1565 switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
... ... @@ -483,12 +483,17 @@
483 483 csum_copy_err:
484 484 slow = lock_sock_fast(sk);
485 485 if (!skb_kill_datagram(sk, skb, flags)) {
486   - if (is_udp4)
  486 + if (is_udp4) {
487 487 UDP_INC_STATS_USER(sock_net(sk),
  488 + UDP_MIB_CSUMERRORS, is_udplite);
  489 + UDP_INC_STATS_USER(sock_net(sk),
488 490 UDP_MIB_INERRORS, is_udplite);
489   - else
  491 + } else {
490 492 UDP6_INC_STATS_USER(sock_net(sk),
  493 + UDP_MIB_CSUMERRORS, is_udplite);
  494 + UDP6_INC_STATS_USER(sock_net(sk),
491 495 UDP_MIB_INERRORS, is_udplite);
  496 + }
492 497 }
493 498 unlock_sock_fast(sk, slow);
494 499  
... ... @@ -637,7 +642,7 @@
637 642  
638 643 if (rcu_access_pointer(sk->sk_filter)) {
639 644 if (udp_lib_checksum_complete(skb))
640   - goto drop;
  645 + goto csum_error;
641 646 }
642 647  
643 648 if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf))
... ... @@ -656,6 +661,8 @@
656 661 bh_unlock_sock(sk);
657 662  
658 663 return rc;
  664 +csum_error:
  665 + UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
659 666 drop:
660 667 UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
661 668 atomic_inc(&sk->sk_drops);
... ... @@ -817,7 +824,7 @@
817 824 }
818 825  
819 826 if (udp6_csum_init(skb, uh, proto))
820   - goto discard;
  827 + goto csum_error;
821 828  
822 829 /*
823 830 * Multicast receive code
... ... @@ -850,7 +857,7 @@
850 857 goto discard;
851 858  
852 859 if (udp_lib_checksum_complete(skb))
853   - goto discard;
  860 + goto csum_error;
854 861  
855 862 UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);
856 863 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
... ... @@ -867,7 +874,9 @@
867 874 skb->len,
868 875 daddr,
869 876 ntohs(uh->dest));
870   -
  877 + goto discard;
  878 +csum_error:
  879 + UDP6_INC_STATS_BH(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE);
871 880 discard:
872 881 UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);
873 882 kfree_skb(skb);