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>