How to disable udp checksum control in kernel

If you can’t receive udp packets in your udp server application while you’re seeing packets in tcpdump/wireshark session, you should think about UDP checksum control in Linux kernel.

Linux kernel calculates checksum value of all received udp packets and if calculated checksum not equal with the checksum in packet, kernel drops entire packet (according to RFC1122) and adds an entry to kernel log.

You can see kernel udp checksum error logs with dmesg command as:

$ dmesg
...
[1277.642155] UDP: bad checksum. From 172.16.0.4:6467 to 172.16.6.2:1500 ulen 72
[1277.742133] UDP: bad checksum. From 172.16.0.4:6467 to 172.16.6.2:1500 ulen 72
[1277.842167] UDP: bad checksum. From 172.16.0.4:6467 to 172.16.6.2:1500 ulen 72

If you have the same problem and you want to disable UDP checksum control only for your udp server application not the kernel in general, you can use SO_NO_CHECK socket option to related udp socket fd in your application as below:

int disable = 1;
if (setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, (void*)&disable, sizeof(disable)) < 0) {
    perror("setsockopt failed");
}

NOTE: It is not possible to disable udp checksum control in IPv6 packets. This is a big topic and there is a specific RFC6936 document about it: https://tools.ietf.org/html/rfc6936

For Ipv6, there’s UDP-Lite that could be set to verify checksum for a part of the payload, see this page for more details https://en.wikipedia.org/wiki/UDP-Lite