From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by dpdk.space (Postfix) with ESMTP id 1E8ADA00E6 for ; Thu, 21 Mar 2019 16:03:18 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 5CEEF1B4C0; Thu, 21 Mar 2019 16:03:17 +0100 (CET) Received: from hqmgw1.hq.eso.org (hqmgw1.hq.eso.org [134.171.42.201]) by dpdk.org (Postfix) with ESMTP id 4C68A1B483 for ; Thu, 21 Mar 2019 16:03:16 +0100 (CET) X-IronPort-AV: E=Sophos;i="5.60,253,1549926000"; d="scan'208";a="48541552" Received: from mxroute01.hq.eso.org ([134.171.15.33]) by hqmgw1.hq.eso.org with ESMTP; 21 Mar 2019 16:03:14 +0100 Received: from mxadauth03.hq.eso.org (mxadauth03.hq.eso.org [134.171.42.80]) by mxroute01.hq.eso.org (Postfix) with ESMTP id DF24E120002; Thu, 21 Mar 2019 16:03:14 +0100 (CET) Received: from [127.0.0.1] (hq-000-kemp01.hq.eso.org [134.171.42.9]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: nbenes) by mxadauth03.hq.eso.org (Postfix) with ESMTPSA id DC23020650; Thu, 21 Mar 2019 16:03:14 +0100 (CET) To: users@dpdk.org From: "N. Benes" Message-ID: Date: Thu, 21 Mar 2019 15:03:00 +0000 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Subject: [dpdk-users] Bug in IPv4 header checksum computation? X-BeenThere: users@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK usage discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: users-bounces@dpdk.org Sender: "users" 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!