Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!ames!elroy!mahendo!wlbr!wlv.imsd.contel.com!sms From: sms@wlv.imsd.contel.com (Steven M. Schultz(Y)) Newsgroups: comp.bugs.2bsd Subject: TIME_WAIT sockets clog system (part 1) Keywords: mbufs time_wait ftp Message-ID: <33129@wlbr.IMSD.CONTEL.COM> Date: 29 Jun 89 05:44:57 GMT Sender: news@wlbr.IMSD.CONTEL.COM Reply-To: sms@wlv.imsd.contel.com (Steven M. Schultz(Y)) Organization: Contel Federal Systems Lines: 62 Subject: TIME_WAIT sockets clog system (part 1) Index: sys/netinet/tcp_subr.c 2.10BSD Description: Sockets in a TIME_WAIT state can constipate the networking buffer memory when generated in rapid succession by, for example, an "mget" in an ftp session. If more than a dozen or so small files are transferred in rapid succession over an ethernet, all the mbufs in the system will be taken up by sockets in a TIME_WAIT state (from the socket opened for each data transfer). Repeat-By: ftp in to a 2.10.1BSD system, do an "mget *" in a largish directory. note that the transfer will hang/develope problems after about a dozen to twenty files. the 2.10.1BSD system has run out of mbufs and will recover in a minute or so (hopefully). Fix: Apply this patch to netinet/tcp_subr.c, this fix implements a tcp_drain() function that actually does something (the original 4.3BSD tcp_drain() was a null function). The other half of this fix will follow shortly and consists of a small modification to uipc_mbuf to invoke the drain routine at the appropriate time. The comment in the function pretty much sums the situation up. *** tcp_subr.c.old Thu Apr 28 16:22:56 1988 --- tcp_subr.c Fri Jun 9 13:57:29 1989 *************** *** 251,257 **** --- 251,279 ---- tcp_drain() { + register struct inpcb *ip, *ipnxt; + register struct tcpcb *tp; + int s = splimp(); + /* + * Search through tcb's and look for TIME_WAIT states to liberate, + * these are due to go away soon anyhow and we're short of space or + * we wouldn't be here... + */ + ip = tcb.inp_next; + if (ip == 0) { + splx(s); + return; + } + for (; ip != &tcb; ip = ipnxt) { + ipnxt = ip->inp_next; + tp = intotcpcb(ip); + if (tp == 0) + continue; + if (tp->t_state == TCPS_TIME_WAIT) + tcp_close(tp); + } + splx(s); } /*