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>
