Subject: TCP fast retransmit
To: None <tech-net@NetBSD.org>
From: Michael Eriksson <Michael.Eriksson@era-t.ericsson.se>
List: tech-net
Date: 12/09/2004 23:52:35
Tjupp!

Here's a question for all you TCP gurus out there...

Below is a TCP dump from the sending side of a connection that loses a
lot of packets, especially when multiple packets are sent
back-to-back. I would have expected fast restransmit to kick in after
three acks, but we have to wait for the retransmit timer.

The reason that the three acks don't cause a fast restransmit is that
the receive window is updated between the two first acks for 1809. My
question: Why does a receive window update disqualify the ack as a
duplicate? The receive window is updated when the receiving process
gets some data from the socket, i.e., it's a completely local thing.

Here are lines 2000-2002 from /sys/netinet/tcp_input.c 1.190.2.6, as
used in NetBSD 2.0 (-current's 1.209 look the same). Why the
"tiwin == tp->snd_wnd"?

---8<----------------------------------------------------------------
		if (SEQ_LEQ(th->th_ack, tp->snd_una)) {
			if (tlen == 0 && tiwin == tp->snd_wnd) {
				tcpstat.tcps_rcvdupack++;
---8<----------------------------------------------------------------


The TCP dump:

21:57:57.064379 sender.ssh > reciever.65518: P 1:285(284) ack 20 win 32850 <nop,nop,timestamp 5559 5559> (DF) [tos 0x10]
21:57:57.064524 sender.ssh > reciever.65518: P 285:609(324) ack 20 win 32850 <nop,nop,timestamp 5559 5559> (DF) [tos 0x10]
21:57:57.064616 sender.ssh > reciever.65518: P 609:933(324) ack 20 win 32850 <nop,nop,timestamp 5559 5559> (DF) [tos 0x10]
21:57:57.064706 sender.ssh > reciever.65518: P 933:1209(276) ack 20 win 32850 <nop,nop,timestamp 5559 5559> (DF) [tos 0x10]
21:57:57.064835 sender.ssh > reciever.65518: P 1209:1525(316) ack 20 win 32850 <nop,nop,timestamp 5559 5559> (DF) [tos 0x10]
21:57:57.064924 sender.ssh > reciever.65518: P 1525:1809(284) ack 20 win 32850 <nop,nop,timestamp 5559 5559> (DF) [tos 0x10]
21:57:57.065040 sender.ssh > reciever.65518: P 1809:2109(300) ack 20 win 32850 <nop,nop,timestamp 5559 5559> (DF) [tos 0x10]
21:57:57.065131 sender.ssh > reciever.65518: P 2109:2409(300) ack 20 win 32850 <nop,nop,timestamp 5559 5559> (DF) [tos 0x10]
21:57:57.065209 sender.ssh > reciever.65518: P 2409:2701(292) ack 20 win 32850 <nop,nop,timestamp 5559 5559> (DF) [tos 0x10]
21:57:57.083793 reciever.65518 > sender.ssh: . ack 609 win 32688 <nop,nop,timestamp 5559 5559> (DF)
21:57:57.083840 sender.ssh > reciever.65518: . 2701:4149(1448) ack 20 win 32850 <nop,nop,timestamp 5559 5559> (DF) [tos 0x10]
21:57:57.083848 sender.ssh > reciever.65518: P 4149:4257(108) ack 20 win 32850 <nop,nop,timestamp 5559 5559> (DF) [tos 0x10]
21:57:57.096514 reciever.65518 > sender.ssh: . ack 1209 win 32712 <nop,nop,timestamp 5559 5559> (DF)
21:57:57.109150 reciever.65518 > sender.ssh: . ack 1809 win 32708 <nop,nop,timestamp 5559 5559> (DF)
21:57:57.134611 reciever.65518 > sender.ssh: . ack 1809 win 32850 <nop,nop,timestamp 5559 5559> (DF)
21:57:57.136171 reciever.65518 > sender.ssh: . ack 1809 win 32850 <nop,nop,timestamp 5559 5559> (DF)
21:57:58.599242 sender.ssh > reciever.65518: . 1809:3257(1448) ack 20 win 32850 <nop,nop,timestamp 5562 5559> (DF) [tos 0x10]
21:57:58.632228 reciever.65518 > sender.ssh: . ack 4257 win 31626 <nop,nop,timestamp 5562 5562> (DF)

/Micke