Subject: kern/2335: 4.4BSD-Lite2 TCP persist timeout patches not in -current
To: None <gnats-bugs@NetBSD.ORG>
From: None <pete@demon.net>
List: netbsd-bugs
Date: 04/16/1996 13:15:53
>Number: 2335
>Category: kern
>Synopsis: 4.4BSD-Lite2 TCP persist timeout patches not in -current
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Tue Apr 16 08:35:01 1996
>Last-Modified:
>Originator: Pete Bentley
>Organization:
Demon Internet
>Release: 16 April 1996
>Environment:
System: NetBSD chico.eng.demon.net 1.1 NetBSD 1.1 (PETE) #68: Sat Apr 13 14:18:08 BST 1996 pete@chico.eng.demon.net:/src/NetBSD/1.1/src/sys/arch/i386/compile/PETE i386
>Description:
Not all the 4.4BSD-Lite2 TCP patches, in particular the persist timeout
patches seem to have made it into NetBSD-Current. This means TCP sockets
can get into CLOSE_WAIT or FIN_WAIT_1 with data queued on them and neither
persist nor keepalive timers running, tieing up mbus forever and eventually
filling up the mbuf map
>How-To-Repeat:
Run a machine with many TCP connections from dial-up clients which
may disappear from the net before closing down the TCP sockets (eg a web
server or web cache). Note that netstat -m shows network memory in use
monotonically increaing until mb_map fills up after some period.
>Fix:
This patch makes sure that TCP send window reaches zero that the persist
timer is running, and that if enough persist probes fail the socket will be
dropped (Stevens, "TCP/IP Illustrated, Volume 3", pp196--200).
--- /src/NetBSD/current/src/sys/netinet/tcp_var.h Wed Feb 14 12:37:03 1996
+++ tcp_var.h Tue Apr 16 11:32:59 1996
@@ -180,6 +180,7 @@
u_long tcps_timeoutdrop; /* conn. dropped in rxmt timeout */
u_long tcps_rexmttimeo; /* retransmit timeouts */
u_long tcps_persisttimeo; /* persist timeouts */
+ u_long tcps_persistdrop; /* connections dropped in persist */
u_long tcps_keeptimeo; /* keepalive timeouts */
u_long tcps_keepprobe; /* keepalive probes sent */
u_long tcps_keepdrops; /* connections dropped in keepalive */
--- /src/NetBSD/current/src/sys/netinet/tcp_output.c Wed Feb 14 12:37:02 1996
+++ tcp_output.c Tue Apr 16 11:31:38 1996
@@ -153,14 +153,18 @@
* but we haven't been called to retransmit,
* len will be -1. Otherwise, window shrank
* after we sent into it. If window shrank to 0,
- * cancel pending retransmit and pull snd_nxt
- * back to (closed) window. We will enter persist
- * state below. If the window didn't close completely,
- * just wait for an ACK.
+ * cancel pending retransmit, pull snd_nxt back
+ * to (closed) window, and set the persist timer
+ * if it isn't already going. If the window didn't
+ * close completely, just wait for an ACK.
*/
len = 0;
if (win == 0) {
tp->t_timer[TCPT_REXMT] = 0;
+ tp->t_rxtshift = 0;
+ tp->snd_nxt = tp->snd_una;
+ if (tp->t_timer[TCPT_PERSIST] == 0)
+ tcp_setpersist(tp);
tp->snd_nxt = tp->snd_una;
}
}
--- /src/NetBSD/current/src/sys/netinet/tcp_timer.c Wed Feb 14 12:37:03 1996
+++ tcp_timer.c Tue Apr 16 11:28:46 1996
@@ -62,6 +62,7 @@
int tcp_keepidle = TCPTV_KEEP_IDLE;
int tcp_keepintvl = TCPTV_KEEPINTVL;
+int tcp_maxpersistidle = TCPTV_KEEP_IDLE; /* max idle time in persist */
int tcp_maxidle;
#endif /* TUBA_INCLUDE */
/*
@@ -162,6 +163,8 @@
int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
{ 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
+int tcp_totbackoff = 511; /* sum of tcp_backoff[] */
+
/*
* TCP timer processing.
*/
@@ -265,6 +268,20 @@
*/
case TCPT_PERSIST:
tcpstat.tcps_persisttimeo++;
+ /*
+ * Hack: if the peer is dead/unreachable, we do not
+ * time out if the window is closed. After a full
+ * backoff, drop the connection if the idle time
+ * (no responses to probes) reaches the maximum
+ * backoff that we would use if retransmitting.
+ */
+ if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
+ (tp->t_idle >= tcp_maxpersistidle ||
+ tp->t_idle >= TCP_REXMTVAL(tp) * tcp_totbackoff)) {
+ tcpstat.tcps_persistdrop++;
+ tp = tcp_drop(tp, ETIMEDOUT);
+ break;
+ }
tcp_setpersist(tp);
tp->t_force = 1;
(void) tcp_output(tp);
>Audit-Trail:
>Unformatted: