diff options
author | mohans <mohans@FreeBSD.org> | 2007-02-26 22:25:21 +0000 |
---|---|---|
committer | mohans <mohans@FreeBSD.org> | 2007-02-26 22:25:21 +0000 |
commit | 384aeb29f6100b5e13581c56efdea6d423675769 (patch) | |
tree | 21cfa3a2368a7f712458dfdd8d3485b03c0c6fa7 /sys/netinet/tcp_timer.c | |
parent | 2bd7382fdc16aa04088cebb691546535c56c484b (diff) | |
download | FreeBSD-src-384aeb29f6100b5e13581c56efdea6d423675769.zip FreeBSD-src-384aeb29f6100b5e13581c56efdea6d423675769.tar.gz |
Reap FIN_WAIT_2 connections marked SOCANTRCVMORE faster. This mitigate
potential issues where the peer does not close, potentially leaving
thousands of connections in FIN_WAIT_2. This is controlled by a new sysctl
fast_finwait2_recycle, which is disabled by default.
Reviewed by: gnn, silby.
Diffstat (limited to 'sys/netinet/tcp_timer.c')
-rw-r--r-- | sys/netinet/tcp_timer.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 86d9c6a..33e4806 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -96,6 +96,15 @@ static int always_keepalive = 1; SYSCTL_INT(_net_inet_tcp, OID_AUTO, always_keepalive, CTLFLAG_RW, &always_keepalive , 0, "Assume SO_KEEPALIVE on all TCP connections"); +int tcp_fast_finwait2_recycle = 0; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, fast_finwait2_recycle, CTLFLAG_RW, + &tcp_fast_finwait2_recycle, 0, "Recycle closed FIN_WAIT_2 connections faster"); + +int tcp_finwait2_timeout; +SYSCTL_PROC(_net_inet_tcp, OID_AUTO, finwait2_timeout, CTLTYPE_INT|CTLFLAG_RW, + &tcp_finwait2_timeout, 0, sysctl_msec_to_ticks, "I", ""); + + static int tcp_keepcnt = TCPTV_KEEPCNT; /* max idle probes */ int tcp_maxpersistidle; @@ -211,13 +220,24 @@ tcp_timer_2msl(xtp) * still waiting for peer to close and connection has been idle * too long, or if 2MSL time is up from TIME_WAIT, delete connection * control block. Otherwise, check again in a bit. + * + * If fastrecycle of FIN_WAIT_2, in FIN_WAIT_2 and receiver has closed, + * there's no point in hanging onto FIN_WAIT_2 socket. Just close it. + * Ignore fact that there were recent incoming segments. */ - if (tp->t_state != TCPS_TIME_WAIT && - (ticks - tp->t_rcvtime) <= tcp_maxidle) - callout_reset(tp->tt_2msl, tcp_keepintvl, - tcp_timer_2msl, tp); - else - tp = tcp_close(tp); + if (tcp_fast_finwait2_recycle && tp->t_state == TCPS_FIN_WAIT_2 && + tp->t_inpcb && tp->t_inpcb->inp_socket && + (tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) { + tcpstat.tcps_finwait2_drops++; + tp = tcp_close(tp); + } else { + if (tp->t_state != TCPS_TIME_WAIT && + (ticks - tp->t_rcvtime) <= tcp_maxidle) + callout_reset(tp->tt_2msl, tcp_keepintvl, + tcp_timer_2msl, tp); + else + tp = tcp_close(tp); + } #ifdef TCPDEBUG if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) |