Date: Fri, 19 Jun 2009 22:05:04 +0200 (CEST) From: Hartmut Brandt <hartmut.brandt@dlr.de> To: Karim Fodil-Lemelin <kfl@xiplink.com> Cc: net@freebsd.org Subject: Re: TCP bug? Message-ID: <20090619215930.V970@beagle.kn.op.dlr.de> In-Reply-To: <4A3BE910.6080502@xiplink.com> References: <20090619194608.W697@beagle.kn.op.dlr.de> <4A3BE910.6080502@xiplink.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Hi, On Fri, 19 Jun 2009, Karim Fodil-Lemelin wrote: KF>Looking at Steven's book TCP/IP Volume 2 (1995 edition) page 988 (Processing KF>and Received Data) they call TCP_REASS(tp, ti, m, so, tiflags) where tiflags KF>is thflags and inside the TCP_REASS macro (page 908), this code is used KF>(where ti is the tcpiphdr pointer): KF> KF>flags = (ti)->ti_flags & TH_FIN; \ KF> KF>Same problem there as well ... KF> KF>Also, looking at tcp_reass(), the same approach of using the header version KF>is used there: KF> KF>flags = q->tqe_th->th_flags & TH_FIN; KF> KF>This seems to work since the data was kept inside the reassembly queue and KF>not dropped KF> KF>If this problem is confirmed you've probably found an original implementation KF>bug. Can you describe better the test condition to reproduce this problem? Sure. I've a test environment for TCP which does for this test the following: - open a TCP socket, set the socket send buffer to 32768 byte - call connect() and expect SYN seq=<iss> win=32768 - tester responds with SYN, FIN, ACK=<iss+1> data=(41000 bytes) seq=<irs> - expect ACK=<irs+32769> seq=<iss+1> - check that TCP is in EsTABLISHED state Everything is fine except that TCP ends up in CLOSE_WAIT. harti KF>Harti Brandt wrote: KF>> KF>> Hi all, KF>> KF>> one of my TCP test cases breaks in what one could call an edge case: KF>> KF>> When the TCP is in SYN-SENT state (the user has called connect()) and the KF>> peer answers with an almost-lamp test packet which has SYN, FIN, ACK and KF>> data larger than the window, TCP ACKs a window full of data, drops the KF>> rest, but processes the FIN - it goes into CLOSE_WAIT. This looks wrong to KF>> me. When dropping the data that is outside the window, it should also drop KF>> the FIN. KF>> KF>> The problem seems to be very old - I found it alread in rev. 1.1 KF>> of tcp_input.c. In -CURRENT it is on line 2590: when the sequence number KF>> of the incoming segment is the next expected one, the reassembly queue is KF>> empty and we are in an established state, the segment data is added to the KF>> socket buffer and all TCP header flags are cleared except for TH_FIN. KF>> Unfortunately here the original header flags are taken instead of the KF>> cached version in thflags. Earlier in the processing the out-of-window KF>> data and the FIN in thflags were chopped off and now TH_FIN reappears. KF>> KF>> The fix should be easy: instead of using the original flag byte to get the KF>> FIN use the cached copy. KF>> KF>> Index: tcp_input.c KF>> =================================================================== KF>> --- tcp_input.c (revision 194499) KF>> +++ tcp_input.c (working copy) KF>> @@ -2587,7 +2587,7 @@ KF>> else KF>> tp->t_flags |= TF_ACKNOW; KF>> tp->rcv_nxt += tlen; KF>> - thflags = th->th_flags & TH_FIN; KF>> + thflags &= TH_FIN; KF>> TCPSTAT_INC(tcps_rcvpack); KF>> TCPSTAT_ADD(tcps_rcvbyte, tlen); KF>> ND6_HINT(tp); KF>> KF>> I wonder, though, why the code is as it is, i.e. why it takes the original KF>> FIN flag. Any idea? KF>> KF>> harti KF>> KF>> _______________________________________________ KF>> freebsd-net@freebsd.org mailing list KF>> http://lists.freebsd.org/mailman/listinfo/freebsd-net KF>> To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org" KF> KF>
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090619215930.V970>