Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Eric Dumazet and committed by
David S. Miller
6a5dc9e5 f233a976

+72 -28
+5
include/uapi/linux/snmp.h
··· 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 ··· 88 87 ICMP_MIB_OUTTIMESTAMPREPS, /* OutTimestampReps */ 89 88 ICMP_MIB_OUTADDRMASKS, /* OutAddrMasks */ 90 89 ICMP_MIB_OUTADDRMASKREPS, /* OutAddrMaskReps */ 90 + ICMP_MIB_CSUMERRORS, /* InCsumErrors */ 91 91 __ICMP_MIB_MAX 92 92 }; 93 93 ··· 105 103 ICMP6_MIB_INERRORS, /* InErrors */ 106 104 ICMP6_MIB_OUTMSGS, /* OutMsgs */ 107 105 ICMP6_MIB_OUTERRORS, /* OutErrors */ 106 + ICMP6_MIB_CSUMERRORS, /* InCsumErrors */ 108 107 __ICMP6_MIB_MAX 109 108 }; 110 109 ··· 133 130 TCP_MIB_RETRANSSEGS, /* RetransSegs */ 134 131 TCP_MIB_INERRS, /* InErrs */ 135 132 TCP_MIB_OUTRSTS, /* OutRsts */ 133 + TCP_MIB_CSUMERRORS, /* InCsumErrors */ 136 134 __TCP_MIB_MAX 137 135 }; 138 136 ··· 151 147 UDP_MIB_OUTDATAGRAMS, /* OutDatagrams */ 152 148 UDP_MIB_RCVBUFERRORS, /* RcvbufErrors */ 153 149 UDP_MIB_SNDBUFERRORS, /* SndbufErrors */ 150 + UDP_MIB_CSUMERRORS, /* InCsumErrors */ 154 151 __UDP_MIB_MAX 155 152 }; 156 153
+3 -1
net/ipv4/icmp.c
··· 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 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;
+3 -1
net/ipv4/ip_input.c
··· 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 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:
+7 -3
net/ipv4/proc.c
··· 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 ··· 163 162 SNMP_MIB_ITEM("RetransSegs", TCP_MIB_RETRANSSEGS), 164 163 SNMP_MIB_ITEM("InErrs", TCP_MIB_INERRS), 165 164 SNMP_MIB_ITEM("OutRsts", TCP_MIB_OUTRSTS), 165 + SNMP_MIB_ITEM("InCsumErrors", TCP_MIB_CSUMERRORS), 166 166 SNMP_MIB_SENTINEL 167 167 }; 168 168 ··· 174 172 SNMP_MIB_ITEM("OutDatagrams", UDP_MIB_OUTDATAGRAMS), 175 173 SNMP_MIB_ITEM("RcvbufErrors", UDP_MIB_RCVBUFERRORS), 176 174 SNMP_MIB_ITEM("SndbufErrors", UDP_MIB_SNDBUFERRORS), 175 + SNMP_MIB_ITEM("InCsumErrors", UDP_MIB_CSUMERRORS), 177 176 SNMP_MIB_SENTINEL 178 177 }; 179 178 ··· 325 322 struct net *net = seq->private; 326 323 atomic_long_t *ptr = net->mib.icmpmsg_statistics->mibs; 327 324 328 - seq_puts(seq, "\nIcmp: InMsgs InErrors"); 325 + seq_puts(seq, "\nIcmp: InMsgs InErrors InCsumErrors"); 329 326 for (i=0; icmpmibmap[i].name != NULL; i++) 330 327 seq_printf(seq, " In%s", icmpmibmap[i].name); 331 328 seq_printf(seq, " OutMsgs OutErrors"); 332 329 for (i=0; icmpmibmap[i].name != NULL; i++) 333 330 seq_printf(seq, " Out%s", icmpmibmap[i].name); 334 - seq_printf(seq, "\nIcmp: %lu %lu", 331 + seq_printf(seq, "\nIcmp: %lu %lu %lu", 335 332 snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INMSGS), 336 - snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INERRORS)); 333 + snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INERRORS), 334 + snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_CSUMERRORS)); 337 335 for (i=0; icmpmibmap[i].name != NULL; i++) 338 336 seq_printf(seq, " %lu", 339 337 atomic_long_read(ptr + icmpmibmap[i].index));
+1
net/ipv4/tcp_input.c
··· 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:
+10 -4
net/ipv4/tcp_ipv4.c
··· 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 } ··· 1986 1985 * provided case of th->doff==0 is eliminated. 1987 1986 * So, we defer the checks. */ 1988 1987 if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb)) 1989 - goto bad_packet; 1988 + goto csum_error; 1990 1989 1991 1990 th = tcp_hdr(skb); 1992 1991 iph = ip_hdr(skb); ··· 2052 2051 goto discard_it; 2053 2052 2054 2053 if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) { 2054 + csum_error: 2055 + TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); 2055 2056 bad_packet: 2056 2057 TCP_INC_STATS_BH(net, TCP_MIB_INERRS); 2057 2058 } else { ··· 2075 2072 goto discard_it; 2076 2073 } 2077 2074 2078 - if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) { 2079 - TCP_INC_STATS_BH(net, TCP_MIB_INERRS); 2075 + if (skb->len < (th->doff << 2)) { 2080 2076 inet_twsk_put(inet_twsk(sk)); 2081 - goto discard_it; 2077 + goto bad_packet; 2078 + } 2079 + if (tcp_checksum_complete(skb)) { 2080 + inet_twsk_put(inet_twsk(sk)); 2081 + goto csum_error; 2082 2082 } 2083 2083 switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { 2084 2084 case TCP_TW_SYN: {
+2 -1
net/ipv4/tcp_output.c
··· 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.
+9 -2
net/ipv4/udp.c
··· 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); ··· 1288 1286 1289 1287 csum_copy_err: 1290 1288 slow = lock_sock_fast(sk); 1291 - if (!skb_kill_datagram(sk, skb, flags)) 1289 + if (!skb_kill_datagram(sk, skb, flags)) { 1290 + UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); 1292 1291 UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); 1292 + } 1293 1293 unlock_sock_fast(sk, slow); 1294 1294 1295 1295 if (noblock) ··· 1517 1513 1518 1514 if (rcu_access_pointer(sk->sk_filter) && 1519 1515 udp_lib_checksum_complete(skb)) 1520 - goto drop; 1516 + goto csum_error; 1521 1517 1522 1518 1523 1519 if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) ··· 1537 1533 1538 1534 return rc; 1539 1535 1536 + csum_error: 1537 + UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); 1540 1538 drop: 1541 1539 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); 1542 1540 atomic_inc(&sk->sk_drops); ··· 1755 1749 proto == IPPROTO_UDPLITE ? "Lite" : "", 1756 1750 &saddr, ntohs(uh->source), &daddr, ntohs(uh->dest), 1757 1751 ulen); 1752 + UDP_INC_STATS_BH(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); 1758 1753 drop: 1759 1754 UDP_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); 1760 1755 kfree_skb(skb);
+3 -1
net/ipv6/icmp.c
··· 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 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:
+4
net/ipv6/proc.c
··· 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 ··· 100 99 SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS), 101 100 SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS), 102 101 SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS), 102 + SNMP_MIB_ITEM("Icmp6InCsumErrors", ICMP6_MIB_CSUMERRORS), 103 103 SNMP_MIB_SENTINEL 104 104 }; 105 105 ··· 131 129 SNMP_MIB_ITEM("Udp6OutDatagrams", UDP_MIB_OUTDATAGRAMS), 132 130 SNMP_MIB_ITEM("Udp6RcvbufErrors", UDP_MIB_RCVBUFERRORS), 133 131 SNMP_MIB_ITEM("Udp6SndbufErrors", UDP_MIB_SNDBUFERRORS), 132 + SNMP_MIB_ITEM("Udp6InCsumErrors", UDP_MIB_CSUMERRORS), 134 133 SNMP_MIB_SENTINEL 135 134 }; 136 135 ··· 142 139 SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS), 143 140 SNMP_MIB_ITEM("UdpLite6RcvbufErrors", UDP_MIB_RCVBUFERRORS), 144 141 SNMP_MIB_ITEM("UdpLite6SndbufErrors", UDP_MIB_SNDBUFERRORS), 142 + SNMP_MIB_ITEM("UdpLite6InCsumErrors", UDP_MIB_CSUMERRORS), 145 143 SNMP_MIB_SENTINEL 146 144 }; 147 145
+10 -9
net/ipv6/tcp_ipv6.c
··· 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 ··· 1467 1466 goto discard_it; 1468 1467 1469 1468 if (!skb_csum_unnecessary(skb) && tcp_v6_checksum_init(skb)) 1470 - goto bad_packet; 1469 + goto csum_error; 1471 1470 1472 1471 th = tcp_hdr(skb); 1473 1472 hdr = ipv6_hdr(skb); ··· 1531 1530 goto discard_it; 1532 1531 1533 1532 if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { 1533 + csum_error: 1534 + TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); 1534 1535 bad_packet: 1535 1536 TCP_INC_STATS_BH(net, TCP_MIB_INERRS); 1536 1537 } else { ··· 1540 1537 } 1541 1538 1542 1539 discard_it: 1543 - 1544 - /* 1545 - * Discard frame 1546 - */ 1547 - 1548 1540 kfree_skb(skb); 1549 1541 return 0; 1550 1542 ··· 1553 1555 goto discard_it; 1554 1556 } 1555 1557 1556 - if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { 1557 - TCP_INC_STATS_BH(net, TCP_MIB_INERRS); 1558 + if (skb->len < (th->doff<<2)) { 1558 1559 inet_twsk_put(inet_twsk(sk)); 1559 - goto discard_it; 1560 + goto bad_packet; 1561 + } 1562 + if (tcp_checksum_complete(skb)) { 1563 + inet_twsk_put(inet_twsk(sk)); 1564 + goto csum_error; 1560 1565 } 1561 1566 1562 1567 switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
+15 -6
net/ipv6/udp.c
··· 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 + UDP_INC_STATS_USER(sock_net(sk), 488 + UDP_MIB_CSUMERRORS, is_udplite); 487 489 UDP_INC_STATS_USER(sock_net(sk), 488 490 UDP_MIB_INERRORS, is_udplite); 489 - else 491 + } else { 492 + UDP6_INC_STATS_USER(sock_net(sk), 493 + UDP_MIB_CSUMERRORS, is_udplite); 490 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 ··· 642 637 643 638 if (rcu_access_pointer(sk->sk_filter)) { 644 639 if (udp_lib_checksum_complete(skb)) 645 - goto drop; 640 + goto csum_error; 646 641 } 647 642 648 643 if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) ··· 661 656 bh_unlock_sock(sk); 662 657 663 658 return rc; 659 + csum_error: 660 + UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); 664 661 drop: 665 662 UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); 666 663 atomic_inc(&sk->sk_drops); ··· 824 817 } 825 818 826 819 if (udp6_csum_init(skb, uh, proto)) 827 - goto discard; 820 + goto csum_error; 828 821 829 822 /* 830 823 * Multicast receive code ··· 857 850 goto discard; 858 851 859 852 if (udp_lib_checksum_complete(skb)) 860 - goto discard; 853 + goto csum_error; 861 854 862 855 UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); 863 856 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); ··· 874 867 skb->len, 875 868 daddr, 876 869 ntohs(uh->dest)); 877 - 870 + goto discard; 871 + csum_error: 872 + UDP6_INC_STATS_BH(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); 878 873 discard: 879 874 UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); 880 875 kfree_skb(skb);