Date: Tue, 30 Mar 1999 08:40:01 -0800 (PST) From: Martin Kammerhofer <dada@localhost.tu-graz.ac.at> To: freebsd-bugs@FreeBSD.org Subject: Re: kern/3948: nonworking t/tcp server side Message-ID: <199903301640.IAA17999@freefall.freebsd.org>
index | next in thread | raw e-mail
The following reply was made to PR kern/3948; it has been noted by GNATS.
From: Martin Kammerhofer <dada@localhost.tu-graz.ac.at>
To: FreeBSD problems <freebsd-gnats-submit@freebsd.org>
Cc: brian@firehouse.net
Subject: Re: kern/3948: nonworking t/tcp server side
Date: Tue, 30 Mar 1999 00:24:06 +0200 (CEST)
The problem is a benign bug in tcp_output.c. It has nothing to do
with delayed acks. It shows up when two conditions hold:
1. The accepting server reads it's input before sending to the socket.
(If the server writes a greeting message just after the accept, it
will be piggy backed on the SYN/ACK segment as expected.)
2. The server has a large socket buffer space compared to the
MSS obtained from the clients initial packet.
Here is in detail was goes wrong:
1. The clients sends a SFP segment with request data to the server port.
2. The server decides in tcp_input() do delay the ACK. (Until the
TCP fast timer runs).
3. The server accepts the connection.
4. The server reads from the socket. tcp_usr_rcvd() (in tcp_usrreq.c)
calls tcp_output() to check if a window update should be sent.
5. It passes the following test [snippet from tcp_output.c]:
/*
* Compare available window to amount of window
* known to peer (as advertised window less
* next expected input). If the difference is at least two
* max size segments, or at least 50% of the maximum possible
* window, then want to send a window update to peer.
*/
if (win > 0) {
/*
* "adv" is the amount we can increase the window,
* taking into account that we are limited by
* TCP_MAXWIN << tp->rcv_scale.
*/
long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
(tp->rcv_adv - tp->rcv_nxt);
if (adv >= (long) (2 * tp->t_maxseg))
goto send;
if (2 * adv >= (long) so->so_rcv.sb_hiwat)
goto send;
}
[end of snippet]
win is the amount of available space in the socket and is
typically large because only one segment has been received.
6. The "goto send" does what you expect from the label's name.
Doing that test here in the context of a half synchronized T/TCP
connection is a bug. The idea is to let the peer know that a
considerable larger window is available now. But in T/TCP's half
synchronized CLOSE-WAIT* state there is no window advertised to
the client - the client has not seen any packet yet.
The fix is simple: change the test from (win > 0) to
(win > 0 && !(tp->t_flags & TF_NEEDSYN)). See below for a patch.
Although this bug has been reported for FreeBSD 2.2.1 and I verified
my fix with 2.2.8-STABLE it affects the MAIN branch too. (I looked
into the repository version.)
With this tiny patch you could get what rfc1644 promises on page 1:
[quote]
(d) The minimum transaction latency for a client should be RTT +
SPT, where RTT is the round-trip time and SPT is the server
processing time.
(e) In favorable circumstances, a reliable request/response
handshake should be achievable with exactly one packet in each
direction.
[quote off]
What a pity that almost nobody uses T/TCP :(
Regards,
Martin
--
Kommunikation läßt sich durch nichts ersetzen.
<=========== cut here ==============
--- /src/sys/netinet/tcp_output.c.orig Tue Mar 30 00:19:16 1999
+++ /src/sys/netinet/tcp_output.c Mon Mar 29 22:52:57 1999
@@ -241,15 +241,15 @@
/*
* Compare available window to amount of window
* known to peer (as advertised window less
* next expected input). If the difference is at least two
* max size segments, or at least 50% of the maximum possible
* window, then want to send a window update to peer.
*/
- if (win > 0) {
+ if (win > 0 && !(tp->t_flags & TF_NEEDSYN)) {
/*
* "adv" is the amount we can increase the window,
* taking into account that we are limited by
* TCP_MAXWIN << tp->rcv_scale.
*/
long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
(tp->rcv_adv - tp->rcv_nxt);
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199903301640.IAA17999>
