Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 Mar 2005 05:49:13 GMT
From:      Noritoshi Demizu <demizu@dd.iij4u.or.jp>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/78226: rcv_lastsack in struct tcpcb is not updated when the right most SACK block expands.
Message-ID:  <200503010549.j215nDjk068343@www.freebsd.org>
Resent-Message-ID: <200503010550.j215oHW9067729@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         78226
>Category:       kern
>Synopsis:       rcv_lastsack in struct tcpcb is not updated when the right most SACK block expands.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar 01 05:50:16 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Noritoshi Demizu
>Release:        FreeBSD 6.0 current (as of Mar 1, 2005)
>Organization:
NICT
>Environment:
FreeBSD xxx 6.0-CURRENT FreeBSD 6.0-CURRENT #7: Tue Mar  1 10:50:54 JST 2005
noritosi@xxx:/home/FreeBSD-current/src/sys/i386/compile/GENERIC  i386
>Description:
rcv_lastsack in struct tcpcb is "last seq number(+1) sack'd by rcv'r"
according to the comment in tcp_var.h.  In tcp_sack.c Rev 1.9, it is
updated only when the first SACK block or a new right most SACK block
is reported.  In other words, it is not updated when the right most
SACK block expands to the right.  Hence, tcp_sack_adjust() may choose
inappropriate snd_nxt at the last line.
>How-To-Repeat:
In my experimental environment, there are three machines: a sender, a
router and a receiver.  Dummynet runs on the router configured as
RTT=40ms, bandwidth=10Mbps, queue=8pkts and plr=0.03.  The sender's
buffer size and the receiver's buffer size are 192k bytes.

In the environment, when a fast retransmitted packet is lost, the
sender has to wait for a timeout.  But the sender keeps sending data
segments until the timeout is triggered because buffer is big enough.

In such case, just after the timeout, the sender keeps receiving ACK
segments containing SACK information of segments sent before the
timeout.  Such SACK information can be used to avoid unnecessary
retransmission.  However, since rcv_lastsack is not updated when fack
advances, sack'd data are sent unnecessarily.
>Fix:
The following patch fixes this problem in my environment.
Since rcv_lastsack is referred only when snd_holes != NULL, this
patch does not touch tcp_del_sackholes() and tcp_free_sackholes().

--- tcp_sack.c-ORG	Mon Feb 28 10:43:29 2005
+++ tcp_sack.c	Tue Mar  1 14:46:16 2005
@@ -431,6 +431,8 @@
 			tp->rcv_lastsack = sack.end;
 			tp->snd_numholes++;
 		}
+		if (SEQ_LT(tp->rcv_lastsack, sack.end))
+			tp->rcv_lastsack = sack.end;
 	}
 	return (0);
 }
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200503010549.j215nDjk068343>