[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lwip-users] Not responding to TCP keep-alives
From: |
David Haas |
Subject: |
Re: [lwip-users] Not responding to TCP keep-alives |
Date: |
Mon, 16 Aug 2004 15:39:24 -0400 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.1) Gecko/20040707 |
I've been looking at this a bit further and here is what I've found:
There are two different kind of keep-alives. In one variety, there is no
data in the segment and the probe simply has the sequence number as one
less than the next sequence number to be sent. LWIP handles this
keep-alive properly. It has code to deal with it.
It turns out that a keep alive can also be sent where the sequence
number is also one less than the sequence number to be sent, but there
is also 1 byte of garbage data. In other words len is 1, but since the
sequence number has already been acked, the receiver should ignore the
data, but SHOULD send out another ack. LWIP is not handling this
situation properly.
Stevens Volume 1, page 335 says:
Some older implementations based on 4.2BSD do not respond to these
keepalive probes unless the sement contains data. Some systems can be
configured to send one garbage byte of data in the probe to elicit the
response. The garbage byte causes no harm, because it's not the expected
byte (it's a byte that the receiver has previously received and
acknowledged), so it's thrown away by the receiver. Otther systems send
the 4.3BSD-style segment (no data) for the first half of the probe
period, and if no respose is received, switch to the 4.2BSD-style
segment for the last half.
Apparently Windows 2000 just starts out doing this when it does
keep-alives against a zero window.
I added some code to deal with this in tcp_receive(). It might not be
the most elegant, but I was afraid of breaking other stuff. I attach the
patch.
Here is a ethereal display from the patched code:
No. Time Source Destination Protocol
Info
784 1231.389373 192.168.10.252 192.168.10.242 TCP
1944 > 1101 [PSH, ACK] Seq=70212 Ack=1 Win=17520 Len=1176
785 1231.390301 192.168.10.242 192.168.10.252 TCP
1101 > 1944 [ACK] Seq=1 Ack=70212 Win=1580 Len=0
786 1231.684792 192.168.10.242 192.168.10.252 TCP
1101 > 1944 [ACK] Seq=1 Ack=71388 Win=404 Len=0
787 1236.598107 192.168.10.252 192.168.10.242 TCP
1944 > 1101 [ACK] Seq=71388 Ack=1 Win=17520 Len=404
788 1236.813665 192.168.10.242 192.168.10.252 TCP
[TCP ZeroWindow] 1101 > 1944 [ACK] Seq=1 Ack=71792 Win=0 Len=0
789 1237.298859 192.168.10.252 192.168.10.242 TCP
1944 > 1101 [ACK] Seq=71792 Ack=1 Win=17520 Len=1
790 1237.299636 192.168.10.242 192.168.10.252 TCP
[TCP ZeroWindow] [TCP Dup ACK 788#1] 1101 > 1944 [ACK] Seq=1 Ack=71792
Win=0 Len=0
791 1238.300340 192.168.10.252 192.168.10.242 TCP
[TCP Keep-Alive] 1944 > 1101 [ACK] Seq=71792 Ack=1 Win=17520 Len=1
792 1238.301060 192.168.10.242 192.168.10.252 TCP
[TCP ZeroWindow] [TCP Keep-Alive ACK] 1101 > 1944 [ACK] Seq=1 Ack=71792
Win=0 Len=0
793 1240.303391 192.168.10.252 192.168.10.242 TCP
[TCP Keep-Alive] 1944 > 1101 [ACK] Seq=71792 Ack=1 Win=17520 Len=1
794 1240.304002 192.168.10.242 192.168.10.252 TCP
[TCP ZeroWindow] [TCP Keep-Alive ACK] 1101 > 1944 [ACK] Seq=1 Ack=71792
Win=0 Len=0
--- devel/lwip/src/core/tcp_in.c 2004-07-25 19:17:07.000000000 -0400
+++ ../cfimage/lwip/core/tcp_in.c 2004-08-16 15:23:24.357617600 -0400
@@ -1162,6 +1162,11 @@
#endif /* TCP_QUEUE_OOSEQ */
}
+ } else {
+ if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
+ TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
+ tcp_ack_now(pcb);
+ }
}
} else {
/* Segments with length 0 is taken care of here. Segments that