TCP FIN-fragment failure in 2.2.x

Greg Beeley (gbeeley@ix.netcom.com)
Tue, 09 Mar 1999 21:36:58 +0000


Hi,

I posted a message here a while back about a TCP problem in 2.2.1; I've
done some research and tracked down the problem and was hoping that someone
closer to the TCP stack development could take the solution and implement
it "right", as this is the first time I've worked with the Linux TCP stack
internals, and I fear I might easily mess something up :)

Ok, here's the deal. When a TCP connection is exhibiting backpressure from
the receiving side of a long data transfer, and then the sender closes the
connection, a FIN is added to the last packet on the send queue. Now, say,
that the receiving end is a serial terminal server, and so the window on
the receiver side opens up very slowly. Now, say that one packet is left
to be transmitted and it is, for instance 500 bytes of data. The receiver
then opens up its zero window after some time to perhaps 100 bytes. Linux
then splits the packet into a 100 byte and 400 byte packet, and sends the
100 byte one to fill up the window. Unfortunately, the TCP code was
including the FIN's sequence number in the count when computing the end_seq
value for the first packet, so when the ACK comes back, it was one sequence
number short of ACKing the packet, so Linux re-sends the packet over and
over, with the receiving end re-ACKing the packet repeatedly.

One solution is to modify tcp_output.c's function tcp_fragment in a way
somewhat like this:

TCP_SKB_CB(skb)->end_seq -= nsize;
skb_trim(skb, skb->len - nsize);

/* Fragmenting a packet with a FIN? Don't include the FIN's
* segment in the first packet!
*/
if (flags & TCPCB_FLAG_FIN) {
TCP_SKB_CB(skb)->end_seq--;
}

/* Rechecksum original buffer. */
skb->csum = csum_partial(skb->data, skb->len, 0);

thus changing the first packet (skb) end sequence number so that it
does not include the FIN's sequence number, which of course originally
it did.

That corrects this particular problem, but I'm not sure if there are
any other implications.

Thanks,

--------
Greg.Beeley@LightSys.org

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/