Hi,
the function for calculating the IPv4 header checksum avoids returning 0
with an additional complement. This is similar to the algorithm for UDP
checksums (where 0 is reserved for "no checksum"), but I could not find
a reference that the same shall also be done for IPv4.
I'm wondering whether I just failed to find the correct reference or if
it is a bug in DPDK?
https://git.dpdk.org/dpdk/tree/lib/librte_net/rte_ip.h#n251
https://git.dpdk.org/dpdk-stable/tree/lib/librte_net/rte_ip.h#n313
> static inline uint16_t
> rte_ipv4_cksum(const struct ipv4_hdr *ipv4_hdr)
> {
> uint16_t cksum;
> cksum = rte_raw_cksum(ipv4_hdr, sizeof(struct ipv4_hdr));
> return (cksum == 0xffff) ? cksum : ~cksum;
> }
In /UDP/, a checksum value 0x0000 means that no checksum was calculated
by the sender and that the receiver cannot check anything. The checksum
is computed from the one's complement sum of 16-bit words, followed by a
one's complement. If the resulting value is 0, it is inverted again.
Therefore, a one's complement 16-bit sum "0xffff" is not inverted, while
all other values are (e.g. "return (sum == 0xffff) ? sum : ~sum"):
https://tools.ietf.org/html/rfc768
> Checksum is the 16-bit one's complement of the one's complement sum of a
> pseudo header of information from the IP header, the UDP header, and the
> data, padded with zero octets at the end (if necessary) to make a
> multiple of two octets....
> If the computed checksum is zero, it is transmitted as all ones (the
> equivalent in one's complement arithmetic). An all zero transmitted
> checksum value means that the transmitter generated no checksum (for
> debugging or for higher level protocols that don't care).
The above function 'rte_ipv4_cksum()' is supposed to compute the
checksum of the /IPv4/ header and -- like checksums for UDP -- does not
return 0 by doing an additional inversion.
However, the IPv4 header checksum is specified as:
https://tools.ietf.org/rfc/rfc791
> The checksum algorithm is:
>
> The checksum field is the 16 bit one's complement of the one's
> complement sum of all 16 bit words in the header. For purposes of
> computing the checksum, the value of the checksum field is zero.
There are no mentioning to an additional inversion, if the resulting
checksum was 0.
Also Wireshark shows an IPv4 header checksum error for packets with
checksum 0. I understand this as indication that IPv4 is not supposed to
allow for ignoring header checksums.
Example to generate a PCAP with 0x0000 IPv4 header checksum and
(correct) UDP payload with 0 checksum:
text2pcap -n -e 0800 ipcks.txt ipcks.pcapng
> 0000 45 00 00 20 12 34 00 00 10 11 00 00 0a 00 00 01
> 0010 0a 00 00 02 01 00 00 16 00 0c 00 00 00 00 00 00
Cheers!