diff options
author | silby <silby@FreeBSD.org> | 2006-09-29 06:24:26 +0000 |
---|---|---|
committer | silby <silby@FreeBSD.org> | 2006-09-29 06:24:26 +0000 |
commit | f7318c47987822b71ad390b7534bf8fd7d7e2d69 (patch) | |
tree | de708660fc91dfa648669dfcc7ec71e2fd24e9cd | |
parent | 92c53717674e99dc7941484cdefd7da4d9cfbab3 (diff) | |
download | FreeBSD-src-f7318c47987822b71ad390b7534bf8fd7d7e2d69.zip FreeBSD-src-f7318c47987822b71ad390b7534bf8fd7d7e2d69.tar.gz |
Rather than autoscaling the number of TIME_WAIT sockets to maxsockets / 5,
scale it to min(ephemeral port range / 2, maxsockets / 5) so that people
with large gobs of memory and/or large maxsockets settings will not
exhaust their entire ephemeral port range with sockets in the TIME_WAIT
state during periods of heavy load.
Those who wish to tweak the size of the TIME_WAIT zone can still do so with
net.inet.tcp.maxtcptw.
Reviewed by: glebius, ru
-rw-r--r-- | sys/netinet/tcp_subr.c | 32 | ||||
-rw-r--r-- | sys/netinet/tcp_timewait.c | 32 |
2 files changed, 48 insertions, 16 deletions
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index fb0fba5..81f0afd 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -179,23 +179,39 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_RW, static uma_zone_t tcptw_zone; static int maxtcptw; + +static int +tcptw_auto_size(void) +{ + int halfrange; + + /* + * Max out at half the ephemeral port range so that TIME_WAIT + * sockets don't tie up too many ephemeral ports. + */ + if (ipport_lastauto > ipport_firstauto) + halfrange = (ipport_lastauto - ipport_firstauto) / 2; + else + halfrange = (ipport_firstauto - ipport_lastauto) / 2; + /* Protect against goofy port ranges smaller than 32. */ + return (imin(imax(halfrange, 32), maxsockets / 5)); +} + static int sysctl_maxtcptw(SYSCTL_HANDLER_ARGS) { int error, new; if (maxtcptw == 0) - new = maxsockets / 5; + new = tcptw_auto_size(); else new = maxtcptw; error = sysctl_handle_int(oidp, &new, sizeof(int), req); - if (error == 0 && req->newptr) { - if (new > maxtcptw) { + if (error == 0 && req->newptr) + if (new >= 32) { maxtcptw = new; uma_zone_set_max(tcptw_zone, maxtcptw); - } else - error = EINVAL; - } + } return (error); } SYSCTL_PROC(_net_inet_tcp, OID_AUTO, maxtcptw, CTLTYPE_INT|CTLFLAG_RW, @@ -285,7 +301,7 @@ tcp_zone_change(void *tag) uma_zone_set_max(tcbinfo.ipi_zone, maxsockets); uma_zone_set_max(tcpcb_zone, maxsockets); if (maxtcptw == 0) - uma_zone_set_max(tcptw_zone, maxsockets / 5); + uma_zone_set_max(tcptw_zone, tcptw_auto_size()); } static int @@ -346,7 +362,7 @@ tcp_init(void) NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); TUNABLE_INT_FETCH("net.inet.tcp.maxtcptw", &maxtcptw); if (maxtcptw == 0) - uma_zone_set_max(tcptw_zone, maxsockets / 5); + uma_zone_set_max(tcptw_zone, tcptw_auto_size()); else uma_zone_set_max(tcptw_zone, maxtcptw); tcp_timer_init(); diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index fb0fba5..81f0afd 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -179,23 +179,39 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_RW, static uma_zone_t tcptw_zone; static int maxtcptw; + +static int +tcptw_auto_size(void) +{ + int halfrange; + + /* + * Max out at half the ephemeral port range so that TIME_WAIT + * sockets don't tie up too many ephemeral ports. + */ + if (ipport_lastauto > ipport_firstauto) + halfrange = (ipport_lastauto - ipport_firstauto) / 2; + else + halfrange = (ipport_firstauto - ipport_lastauto) / 2; + /* Protect against goofy port ranges smaller than 32. */ + return (imin(imax(halfrange, 32), maxsockets / 5)); +} + static int sysctl_maxtcptw(SYSCTL_HANDLER_ARGS) { int error, new; if (maxtcptw == 0) - new = maxsockets / 5; + new = tcptw_auto_size(); else new = maxtcptw; error = sysctl_handle_int(oidp, &new, sizeof(int), req); - if (error == 0 && req->newptr) { - if (new > maxtcptw) { + if (error == 0 && req->newptr) + if (new >= 32) { maxtcptw = new; uma_zone_set_max(tcptw_zone, maxtcptw); - } else - error = EINVAL; - } + } return (error); } SYSCTL_PROC(_net_inet_tcp, OID_AUTO, maxtcptw, CTLTYPE_INT|CTLFLAG_RW, @@ -285,7 +301,7 @@ tcp_zone_change(void *tag) uma_zone_set_max(tcbinfo.ipi_zone, maxsockets); uma_zone_set_max(tcpcb_zone, maxsockets); if (maxtcptw == 0) - uma_zone_set_max(tcptw_zone, maxsockets / 5); + uma_zone_set_max(tcptw_zone, tcptw_auto_size()); } static int @@ -346,7 +362,7 @@ tcp_init(void) NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); TUNABLE_INT_FETCH("net.inet.tcp.maxtcptw", &maxtcptw); if (maxtcptw == 0) - uma_zone_set_max(tcptw_zone, maxsockets / 5); + uma_zone_set_max(tcptw_zone, tcptw_auto_size()); else uma_zone_set_max(tcptw_zone, maxtcptw); tcp_timer_init(); |