Date: Tue, 31 May 2011 09:46:12 +0100 From: "Scheffenegger, Richard" <rs@netapp.com> To: <freebsd-net@freebsd.org> Subject: kern/140597: Lost Retransmission Detection Message-ID: <5FDC413D5FA246468C200652D63E627A0E99C89B@LDCMVEXC1-PRD.hq.netapp.com>
next in thread | raw e-mail | index | archive | help
Hi, please review the following patch, which enables the detection and recovery of lost retransmissions for SACK. This patch address the second most prominent cause of retransmission timeouts (after the failure to initiate loss recovery for small window sessions - e.g. Early Retransmit). The idea behind this patch is the same one that is emergent behavior in the linux stack: 1RTT after sending a retransmission, that retransmission should have made it to the receiver; the 1RTT signal is a newly sent segment (snd.fack advances) being acknowledged by the receiver... The pointer indicating where a retransmission is to be started, is set to snd.nxt (new segment after this loss window) - outside the boundaries of the hole itself - to remember when a hole needs to be retransmitted. If all retransmissions are proceeding in-order, these holes would close and eventually be evicted from the scoreboard, before the first new transmission after the loss window is SACKed by the receiver. Over the first instance of this patch, it addresses a slight oversight, when retransmitted segments from multiple holes became lost - it traverses all the holes from the sackhint forward to the beginning of the scoreboard when snd.fack is adjusted, and resets the pointer (and sackhint) where the next transmission should come from accordingly. However - just like Linux - there is no congestion control reaction (even though the papers discussing lost retransmission all mention that another reduction of cwnd would be appropriate). Richard Scheffenegger diff -u netinet.orig/tcp_output.c netinet/tcp_output.c --- netinet.orig/tcp_output.c 2009-10-25 02:10:29.000000000 +0100 +++ netinet/tcp_output.c 2010-04-02 16:55:14.000000000 +0200 @@ -953,6 +953,10 @@ } else { th->th_seq =3D htonl(p->rxmit); p->rxmit +=3D len; + /* lost again detection */ + if (SEQ_GEQ(p->rxmit, p->end)) { + p->rxmit =3D tp->snd_nxt; + } tp->sackhint.sack_bytes_rexmit +=3D len; } th->th_ack =3D htonl(tp->rcv_nxt); diff -u netinet.orig/tcp_sack.c netinet.simple_mod/tcp_sack.c --- netinet.orig/tcp_sack.c 2009-10-25 02:10:29.000000000 +0100 +++ netinet/tcp_sack.c 2010-04-21 00:48:23.000000000 +0200 @@ -508,7 +508,9 @@ if (SEQ_GEQ(sblkp->end, cur->end)) { /* Move end of hole backward. */ cur->end =3D sblkp->start; - cur->rxmit =3D SEQ_MIN(cur->rxmit, cur->end); + if (SEQ_GEQ(cur->rxmit, cur->end)) { + cur->rxmit =3D tp->snd_nxt; + } } else { /* * ACKs some data in middle of a hole; need @@ -524,8 +526,9 @@ - temp->start); } cur->end =3D sblkp->start; - cur->rxmit =3D = SEQ_MIN(cur->rxmit, - cur->end); + if (SEQ_GEQ(cur->rxmit, cur->end)) { + cur->rxmit =3D tp->snd_nxt; + } } } } @@ -540,6 +543,15 @@ else sblkp--; } + /* retransmission lost again - then restart */ + if ((temp =3D tp->sackhint.nexthole) !=3D NULL) { + do { + if (SEQ_GT(tp->snd_fack, temp->rxmit)) { + temp->rxmit =3D temp->start; + tp->sackhint.nexthole =3D temp; + } + } while ((temp =3D TAILQ_PREV(temp, sackhole_head, scblink)) !=3D NULL); + } } /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5FDC413D5FA246468C200652D63E627A0E99C89B>