Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 25 Jan 2001 23:49:15 +0100 (CET)
From:      Paul Herman <pherman@frenchfries.net>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/24645: sometimes delayed ACKs timeout
Message-ID:  <200101252249.f0PMnFD31982@husten.security.at12.de>

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

>Number:         24645
>Category:       kern
>Synopsis:       sometimes delayed ACKs timeout
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jan 25 15:00:01 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Paul Herman <pherman@frenchfries.net>
>Release:        FreeBSD 4.2-STABLE i386
>Organization:
>Environment:

	4.2-STABLE and 5.0-CURRENT

>Description:

	When receiving large windows worth of data, a delayed ack 
	sometimes won't properly fire off, and the TCP will halt
	for 100ms (or net.inet.tcp.delacktime) multiple times in
	one connection.  In a default installation, this can result
	in a transfer being up to 10x slower.

	This was hashed out on freebsd-net.  See the mail archives with 
        the Subject: "I have delayed ACK problems".

>How-To-Repeat:

	tar cf localhost:/tmp/foo /boot/kernel

>Fix:

	The following patch to tcp_input.c will patch cleanly against
	-STABLE and -CURRENT.

Index: sys/netinet/tcp_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/tcp_input.c,v
retrieving revision 1.107.2.4
diff -u -r1.107.2.4 tcp_input.c
--- sys/netinet/tcp_input.c	2000/08/16 06:14:23	1.107.2.4
+++ sys/netinet/tcp_input.c	2001/01/25 22:12:08
@@ -177,10 +177,14 @@
 	if ((th)->th_seq == (tp)->rcv_nxt && \
 	    LIST_EMPTY(&(tp)->t_segq) && \
 	    (tp)->t_state == TCPS_ESTABLISHED) { \
-		if (tcp_delack_enabled) \
-			callout_reset(tp->tt_delack, tcp_delacktime, \
-			    tcp_timer_delack, tp); \
-		else \
+		if (tcp_delack_enabled) { \
+			if (callout_pending(tp->tt_delack)) { \
+				callout_stop(tp->tt_delack); \
+				tp->t_flags |= TF_ACKNOW; \
+			} else \
+	                        callout_reset(tp->tt_delack, tcp_delacktime, \
+				    tcp_timer_delack, tp); \
+		} else \
 			tp->t_flags |= TF_ACKNOW; \
 		(tp)->rcv_nxt += *(tlenp); \
 		flags = (th)->th_flags & TH_FIN; \
@@ -962,8 +966,12 @@
 			sbappend(&so->so_rcv, m);
 			sorwakeup(so);
 			if (tcp_delack_enabled) {
-	                        callout_reset(tp->tt_delack, tcp_delacktime,
-	                            tcp_timer_delack, tp);
+				if (callout_pending(tp->tt_delack)) {
+					callout_stop(tp->tt_delack);
+					tp->t_flags |= TF_ACKNOW;
+				} else 
+		                        callout_reset(tp->tt_delack, tcp_delacktime,
+					    tcp_timer_delack, tp);
 			} else {
 				tp->t_flags |= TF_ACKNOW;
 				tcp_output(tp);
@@ -1289,10 +1297,14 @@
 			 * If there's data, delay ACK; if there's also a FIN
 			 * ACKNOW will be turned on later.
 			 */
-			if (tcp_delack_enabled && tlen != 0)
-                                callout_reset(tp->tt_delack, tcp_delacktime,  
-                                    tcp_timer_delack, tp);  
-			else
+			if (tcp_delack_enabled && tlen != 0) {
+				if (callout_pending(tp->tt_delack)) {
+					callout_stop(tp->tt_delack);
+					tp->t_flags |= TF_ACKNOW;
+				} else 
+		                        callout_reset(tp->tt_delack, tcp_delacktime,
+					    tcp_timer_delack, tp);
+			} else
 				tp->t_flags |= TF_ACKNOW;
 			/*
 			 * Received <SYN,ACK> in SYN_SENT[*] state.
@@ -2117,10 +2129,14 @@
 			 *  Otherwise, since we received a FIN then no
 			 *  more input can be expected, send ACK now.
 			 */
-			if (tcp_delack_enabled && (tp->t_flags & TF_NEEDSYN))
-                                callout_reset(tp->tt_delack, tcp_delacktime,  
-                                    tcp_timer_delack, tp);  
-			else
+			if (tcp_delack_enabled && (tp->t_flags & TF_NEEDSYN)) {
+				if (callout_pending(tp->tt_delack)) {
+					callout_stop(tp->tt_delack);
+					tp->t_flags |= TF_ACKNOW;
+				} else 
+		                        callout_reset(tp->tt_delack, tcp_delacktime,
+					    tcp_timer_delack, tp);
+			} else
 				tp->t_flags |= TF_ACKNOW;
 			tp->rcv_nxt++;
 		}

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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