Hello,
I am having a problem with TCP Keepalives on Linux. The same tests
below works as expected on Tru64 (4.0F).
I have 2 hosts, Host-A and Host-B that are connected via TCP
connection. Host-A is the client and Host-B is the server.
First, here are my /etc/sysctl.conf parameters for TCP Keepalives:
net.ipv4.tcp_keepalive_intvl = 3
net.ipv4.tcp_keepalive_probes = 2
net.ipv4.tcp_keepalive_time = 10
My expectation is this:
When no data is received over a connection for 10 seconds, the TCP
stack will send a probe to the other end of the connection asking for
an ACK of the last segment sent. In 3 seconds, if nothing is received
then a second probe is sent. If nothing is received in 3 more seconds,
the connection is closed by the TCP stack. Linux select() will notify
of "read" activity for the connection's file descriptor and attempting
to read it returns ETIMEDOUT.
What I have found is this:
If during the period when 2 connection hosts are physically
disconnected (ie cable pull), the client (Host-A) attempts to send
*any* data on the connection (even 1 byte), TCP keepalives stop
functioning and will never cause the connection to drop... even if no
more data is ever sent or received on the connection.
Both processors use the same version of linux (Redhat ES3).
Here is uname -a for one of them:
Linux o1cwp05 2.4.21-32.ELsmp #1 SMP Fri Apr 15 21:17:59 EDT 2005 i686
i686 i386 GNU/Linux
This "example 1" does NOT work as expected:
HOST-A and HOST-B have an established TCP connection
HOST-B is disconnected from the network (unplug ethernet cable for
example)
HOST-A attempts to send some data on the connection
TCP Keepalives never kill the connection even if no data is sent or
received ever again
This "example 2" does work as expected:
HOST-A and HOST-B have an established TCP connection
HOST-B is disconnected from the network (unplug ethernet cable for
example)
HOST-A DOES NOT attempt to send some data on the connection
After at most 16 seconds, the connection is closed and ETIMEDOUT error
occurs as expected
To recreate this problem in my lab, I used W. Richard Steven's "sock"
program provided on his website
http://www.kohala.com/start/unpv12e.html (see link for Source code
half way down)
on Host-B, I ran a TCP server on port 4999 (sock -K -s 10.10.60.25
4999)
on Host-A, I connected to the server on Host-B (sock -K 10.10.60.25
4999)
In the data below, o1fdp01 is Host-A and o1cwp05 is Host-B
Here is the tcpdump output of the run where TCP keepalives never
worked:
tcpdump -vvv port 4999
tcpdump: listening on eth0
20:40:04.325315 o1fdp01.59689 > o1cwp05.4999: S [tcp sum ok]
3927728606:3927728606(0) win 5840 <mss 1460,sackOK,timestamp 10860835
0,nop,wscale 0> (DF) (ttl 64, id 55549, len 60)
20:40:04.325402 o1cwp05.4999 > o1fdp01.59689: S [tcp sum ok]
2921424471:2921424471(0) ack 3927728607 win 5792 <mss
1460,sackOK,timestamp 1354048 10860835,nop,wscale 0> (DF) (ttl 64, id
0, len 60)
20:40:04.325415 o1fdp01.59689 > o1cwp05.4999: . [tcp sum ok] 1:1(0) ack
1 win 5840 <nop,nop,timestamp 10860835 1354048> (DF) (ttl 64, id 55550,
len 52)
20:40:14.322837 o1fdp01.59689 > o1cwp05.4999: . [tcp sum ok] 0:0(0) ack
1 win 5840 <nop,nop,timestamp 10861835 1354048> (DF) (ttl 64, id 55551,
len 52)
20:40:14.322918 o1cwp05.4999 > o1fdp01.59689: . [tcp sum ok] 1:1(0) ack
1 win 5792 <nop,nop,timestamp 1355047 10860835> (DF) (ttl 64, id 53016,
len 52)
20:40:14.323282 o1cwp05.4999 > o1fdp01.59689: . [tcp sum ok] 0:0(0) ack
1 win 5792 <nop,nop,timestamp 1355048 10860835> (DF) (ttl 64, id 53017,
len 52)
20:40:14.323287 o1fdp01.59689 > o1cwp05.4999: . [tcp sum ok] 1:1(0) ack
1 win 5840 <nop,nop,timestamp 10861835 1355047> (DF) (ttl 64, id 55552,
len 52)
20:40:24.323263 o1fdp01.59689 > o1cwp05.4999: . [tcp sum ok] 0:0(0) ack
1 win 5840 <nop,nop,timestamp 10862835 1355047> (DF) (ttl 64, id 55553,
len 52)
20:40:25.785665 o1fdp01.59689 > o1cwp05.4999: P [bad tcp cksum 4770!]
1:2(1) ack 1 win 5840 <nop,nop,timestamp 10862981 1355047> (DF) (ttl
64, id 55554, len 53)
20:40:25.993337 o1fdp01.59689 > o1cwp05.4999: P [bad tcp cksum 3270!]
1:2(1) ack 1 win 5840 <nop,nop,timestamp 10863002 1355047> (DF) (ttl
64, id 55555, len 53)
20:40:26.413378 o1fdp01.59689 > o1cwp05.4999: P [bad tcp cksum 870!]
1:2(1) ack 1 win 5840 <nop,nop,timestamp 10863044 1355047> (DF) (ttl
64, id 55556, len 53)
20:40:27.253387 o1fdp01.59689 > o1cwp05.4999: P [bad tcp cksum b46f!]
1:2(1) ack 1 win 5840 <nop,nop,timestamp 10863128 1355047> (DF) (ttl
64, id 55557, len 53)
20:40:28.933463 o1fdp01.59689 > o1cwp05.4999: P [bad tcp cksum c6f!]
1:2(1) ack 1 win 5840 <nop,nop,timestamp 10863296 1355047> (DF) (ttl
64, id 55558, len 53)
20:40:32.293611 o1fdp01.59689 > o1cwp05.4999: P [bad tcp cksum bc6d!]
1:2(1) ack 1 win 5840 <nop,nop,timestamp 10863632 1355047> (DF) (ttl
64, id 55559, len 53)
20:40:39.013893 o1fdp01.59689 > o1cwp05.4999: P [bad tcp cksum 1c6b!]
1:2(1) ack 1 win 5840 <nop,nop,timestamp 10864304 1355047> (DF) (ttl
64, id 55560, len 53)
...... after this, it stops sending any data at all, but the connection
is not closed as expected
The case below works and exhibits textbook behavior (note last entry R
closing connection)
tcpdump -vvv port 4999
tcpdump: listening on eth0
20:43:01.729986 o1fdp01.59837 > o1cwp05.4999: . [tcp sum ok]
4122167661:4122167661(0) ack 3110189858 win 5840 <nop,nop,timestamp
10878575 1370789> (DF) (ttl 64, id 46060, len 52)
20:43:01.730062 o1cwp05.4999 > o1fdp01.59837: . [tcp sum ok] 1:1(0) ack
1 win 5792 <nop,nop,timestamp 1371788 10877575> (DF) (ttl 64, id 20871,
len 52)
20:43:01.738698 o1cwp05.4999 > o1fdp01.59837: . [tcp sum ok] 0:0(0) ack
1 win 5792 <nop,nop,timestamp 1371789 10877575> (DF) (ttl 64, id 20872,
len 52)
20:43:01.738703 o1fdp01.59837 > o1cwp05.4999: . [tcp sum ok] 1:1(0) ack
1 win 5840 <nop,nop,timestamp 10878575 1371788> (DF) (ttl 64, id 46061,
len 52)
20:43:11.730419 o1fdp01.59837 > o1cwp05.4999: . [tcp sum ok] 0:0(0) ack
1 win 5840 <nop,nop,timestamp 10879575 1371788> (DF) (ttl 64, id 46062,
len 52)
20:43:14.730542 o1fdp01.59837 > o1cwp05.4999: . [tcp sum ok] 0:0(0) ack
1 win 5840 <nop,nop,timestamp 10879875 1371788> (DF) (ttl 64, id 46063,
len 52)
20:43:17.730668 o1fdp01.59837 > o1cwp05.4999: R [tcp sum ok] 1:1(0) ack
1 win 5840 <nop,nop,timestamp 10880175 1371788> (DF) (ttl 64, id 46064,
len 52)
I appreciate any insight anyone can give. I'm hoping there is just a
TCP option I'm missing or something.
Thanks,
Sten