When I send TCP data from localhost to localhost (either on 127.0.0.1
or on the public IP of the machine), the TCP checksum is wrong.
I am using the kernel that came with Xubuntu 8.04, /proc/version:
Linux version 2.6.24-19-generic (buildd@palmer) (gcc version 4.2.3
(Ubuntu 4.2.3-2ubuntu7)) #1 SMP Wed Jun 18 14:43:41 UTC 2008
When I run the sample program below and capture traffic on the lo
device using Wireshark, the TCP segment that contains data has an
incorrect checksum. All other segments have a correct checksum.
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char **argv)
{
int fd_srv, fd_s0, fd_s1;
struct sockaddr_in address;
socklen_t len = sizeof(address);
char buffer[1] = {0};
fd_srv = socket(AF_INET, SOCK_STREAM, 6);
memset(&address, 0, len);
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(0x7f000001);
address.sin_port = htons(12345);
bind(fd_srv, (struct sockaddr *)(&address), len);
listen(fd_srv, 0);
fd_s0 = socket(AF_INET, SOCK_STREAM, 6);
connect(fd_s0, (struct sockaddr *)(&address), len);
fd_s1 = accept(fd_srv, (struct sockaddr *)(&address), &len);
close(fd_srv);
write(fd_s0, buffer, 1);
read(fd_s1, buffer, 1);
close(fd_s0);
close(fd_s1);
return 0;
}
--
I suspect this is intended and expected behaviour. The checksum is quite useless as the packet never travels over the network and can't be corrupted. The transmit code in net/ipv4/ip_output.c seems to mark packets for the loopback interface with CHECKSUM_UNNECESSARY. I guess the connection over loopback still carries the data like you'd expect right? Kristof --
Probably. I saw the behaviour as strange because only the segment containing data had an incorrect TCP checksum, all other segments (SYN, SYN ACK, ACKs without data and FIN ACK) had a correct TCP checksum. Also, the incorrect checksum field seems to depend on the IP address and the packet length, but not on the port number, sequence/acknowledgement number or data content. Thus, the incorrect checksum is the same when the sample is run repeatedly, it only changes when the data length The same happens when I bind the server socket on the public IP (e.g. 10.111.110.71:12345) and connect from a socket on the same IP (10.111.110.71). But then, although the IP is for device eth0 rather than for device lo, the packet still never has to be transmitted and the Yes, the data was still received and correct. Kevin --
Kevin Spiteri wrote: [...] The TCP/IP stack will unconditionally start calculating a checksum as it prepares some of the headers. Then at a later stage it checks the checksum capability of the destination route/device (checksum calculation may be offloaded or unnecessary) and decides whether to update the TCP checksum to include the rest of the packet, including the payload. Ben. -- Ben Hutchings, Senior Software Engineer, Solarflare Communications Not speaking for my employer; that's the marketing department's job. --
