summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsilby <silby@FreeBSD.org>2006-09-29 06:24:26 +0000
committersilby <silby@FreeBSD.org>2006-09-29 06:24:26 +0000
commitf7318c47987822b71ad390b7534bf8fd7d7e2d69 (patch)
treede708660fc91dfa648669dfcc7ec71e2fd24e9cd
parent92c53717674e99dc7941484cdefd7da4d9cfbab3 (diff)
downloadFreeBSD-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.c32
-rw-r--r--sys/netinet/tcp_timewait.c32
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();
OpenPOWER on IntegriCloud