-.\" $OpenBSD: sysctl.3,v 1.266 2016/07/14 17:34:06 jmc Exp $
+.\" $OpenBSD: sysctl.3,v 1.267 2016/07/20 09:15:28 bluhm Exp $
.\"
.\" Copyright (c) 1993
.\" The Regents of the University of California. All rights reserved.
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd $Mdocdate: July 14 2016 $
+.Dd $Mdocdate: July 20 2016 $
.Dt SYSCTL 3
.Os
.Sh NAME
.It tcp Ta stats Ta structure Ta no
.It tcp Ta synbucketlimit Ta integer Ta yes
.It tcp Ta syncachelimit Ta integer Ta yes
+.It tcp Ta synhashsize Ta integer Ta yes
.It tcp Ta synuselimit Ta integer Ta yes
.It udp Ta baddynamic Ta array Ta yes
.It udp Ta checksum Ta integer Ta yes
The maximum number of entries allowed per hash bucket in the TCP SYN cache.
.It Li tcp.syncachelimit
The maximum number of entries allowed in the TCP SYN cache.
+.It Li tcp.synhashsize
+The number of buckets in the TCP SYN cache hash array.
+After the value is set, the actual size changes when the alternative
+SYN cache becomes empty and both SYN caches are swapped.
.It Li tcp.synuselimit
The minimum number of times the hash function for the TCP SYN cache is used
before it is reseeded.
-.\" $OpenBSD: sysctl.8,v 1.202 2016/07/05 17:41:59 tim Exp $
+.\" $OpenBSD: sysctl.8,v 1.203 2016/07/20 09:15:28 bluhm Exp $
.\" $NetBSD: sysctl.8,v 1.4 1995/09/30 07:12:49 thorpej Exp $
.\"
.\" Copyright (c) 1993
.\"
.\" @(#)sysctl.8 8.2 (Berkeley) 5/9/95
.\"
-.Dd $Mdocdate: July 5 2016 $
+.Dd $Mdocdate: July 20 2016 $
.Dt SYSCTL 8
.Os
.Sh NAME
.It net.inet.tcp.keepinittime Ta integer Ta yes
.It net.inet.tcp.keepidle Ta integer Ta yes
.It net.inet.tcp.keepintvl Ta integer Ta yes
-.It net.inet.tcp.always_keepalive Ta integer Ta yes
.It net.inet.tcp.slowhz Ta integer Ta no
.It net.inet.tcp.baddynamic Ta array Ta yes
.It net.inet.tcp.sack Ta integer Ta yes
.It net.inet.tcp.ecn Ta integer Ta yes
.It net.inet.tcp.syncachelimit Ta integer Ta yes
.It net.inet.tcp.synbucketlimit Ta integer Ta yes
-.It net.inet.tcp.synuselimit Ta integer Ta yes
.It net.inet.tcp.rfc3390 Ta integer Ta yes
.It net.inet.tcp.reasslimit Ta integer Ta yes
+.It net.inet.tcp.sackholelimit Ta integer Ta yes
+.It net.inet.tcp.always_keepalive Ta integer Ta yes
+.It net.inet.tcp.synuselimit Ta integer Ta yes
.It net.inet.tcp.rootonly Ta array Ta yes
+.It net.inet.tcp.synhashsize Ta integer Ta yes
.It net.inet.udp.checksum Ta integer Ta yes
.It net.inet.udp.baddynamic Ta array Ta yes
.It net.inet.udp.recvspace Ta integer Ta yes
-/* $OpenBSD: tcp_input.c,v 1.324 2016/07/01 18:37:15 jca Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.325 2016/07/20 09:15:28 bluhm Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
*/
/* syn hash parameters */
-int tcp_syn_cache_size = TCP_SYN_HASH_SIZE;
+int tcp_syn_hash_size = TCP_SYN_HASH_SIZE;
int tcp_syn_cache_limit = TCP_SYN_HASH_SIZE*TCP_SYN_BUCKET_SIZE;
int tcp_syn_bucket_limit = 3*TCP_SYN_BUCKET_SIZE;
int tcp_syn_use_limit = 100000;
int i;
/* Initialize the hash buckets. */
- for (i = 0; i < tcp_syn_cache_size; i++) {
+ tcp_syn_cache[0].scs_buckethead = mallocarray(tcp_syn_hash_size,
+ sizeof(struct syn_cache_head), M_SYNCACHE, M_WAITOK|M_ZERO);
+ tcp_syn_cache[1].scs_buckethead = mallocarray(tcp_syn_hash_size,
+ sizeof(struct syn_cache_head), M_SYNCACHE, M_WAITOK|M_ZERO);
+ tcp_syn_cache[0].scs_size = tcp_syn_hash_size;
+ tcp_syn_cache[1].scs_size = tcp_syn_hash_size;
+ for (i = 0; i < tcp_syn_hash_size; i++) {
TAILQ_INIT(&tcp_syn_cache[0].scs_buckethead[i].sch_bucket);
TAILQ_INIT(&tcp_syn_cache[1].scs_buckethead[i].sch_bucket);
}
struct syn_cache_set *set = &tcp_syn_cache[tcp_syn_cache_active];
struct syn_cache_head *scp;
struct syn_cache *sc2;
- int s;
+ int i, s;
s = splsoftnet();
* If there are no entries in the hash table, reinitialize
* the hash secrets. To avoid useless cache swaps and
* reinitialization, use it until the limit is reached.
+ * An emtpy cache is also the oportunity to resize the hash.
*/
if (set->scs_count == 0 && set->scs_use <= 0) {
- arc4random_buf(set->scs_random, sizeof(set->scs_random));
set->scs_use = tcp_syn_use_limit;
+ if (set->scs_size != tcp_syn_hash_size) {
+ scp = mallocarray(tcp_syn_hash_size, sizeof(struct
+ syn_cache_head), M_SYNCACHE, M_NOWAIT|M_ZERO);
+ if (scp == NULL) {
+ /* Try again next time. */
+ set->scs_use = 0;
+ } else {
+ free(set->scs_buckethead, M_SYNCACHE,
+ set->scs_size *
+ sizeof(struct syn_cache_head));
+ set->scs_buckethead = scp;
+ set->scs_size = tcp_syn_hash_size;
+ for (i = 0; i < tcp_syn_hash_size; i++)
+ TAILQ_INIT(&scp[i].sch_bucket);
+ }
+ }
+ arc4random_buf(set->scs_random, sizeof(set->scs_random));
tcpstat.tcps_sc_seedrandom++;
}
SYN_HASHALL(sc->sc_hash, &sc->sc_src.sa, &sc->sc_dst.sa,
set->scs_random);
- scp = &set->scs_buckethead[sc->sc_hash % tcp_syn_cache_size];
+ scp = &set->scs_buckethead[sc->sc_hash % set->scs_size];
sc->sc_buckethead = scp;
/*
*/
scp2 = scp;
if (TAILQ_EMPTY(&scp2->sch_bucket)) {
- sce = &set->scs_buckethead[tcp_syn_cache_size];
+ sce = &set->scs_buckethead[set->scs_size];
for (++scp2; scp2 != scp; scp2++) {
if (scp2 >= sce)
scp2 = &set->scs_buckethead[0];
if (sets[i]->scs_count == 0)
continue;
SYN_HASHALL(hash, src, dst, sets[i]->scs_random);
- scp = &sets[i]->scs_buckethead[hash % tcp_syn_cache_size];
+ scp = &sets[i]->scs_buckethead[hash % sets[i]->scs_size];
*headp = scp;
TAILQ_FOREACH(sc, &scp->sch_bucket, sc_bucketq) {
if (sc->sc_hash != hash)
-/* $OpenBSD: tcp_usrreq.c,v 1.132 2016/07/11 10:35:43 mpi Exp $ */
+/* $OpenBSD: tcp_usrreq.c,v 1.133 2016/07/20 09:15:28 bluhm Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
/*
}
return (0);
+ case TCPCTL_SYN_HASH_SIZE:
+ nval = tcp_syn_hash_size;
+ error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
+ if (error)
+ return (error);
+ if (nval != tcp_syn_hash_size) {
+ if (nval < 1 || nval > 100000)
+ return (EINVAL);
+ /*
+ * If global hash size has been changed, switch sets as
+ * soon as possible. Then the actual hash array will
+ * be reallocated.
+ */
+ if (tcp_syn_cache[0].scs_size != nval)
+ tcp_syn_cache[0].scs_use = 0;
+ if (tcp_syn_cache[1].scs_size != nval)
+ tcp_syn_cache[1].scs_use = 0;
+ tcp_syn_hash_size = nval;
+ }
+ return (0);
+
default:
if (name[0] < TCPCTL_MAXID)
return (sysctl_int_arr(tcpctl_vars, name, namelen,
-/* $OpenBSD: tcp_var.h,v 1.113 2016/06/18 10:36:13 vgross Exp $ */
+/* $OpenBSD: tcp_var.h,v 1.114 2016/07/20 09:15:28 bluhm Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
};
struct syn_cache_set {
- struct syn_cache_head scs_buckethead[TCP_SYN_HASH_SIZE];
- int scs_count;
- int scs_use;
- u_int32_t scs_random[5];
+ struct syn_cache_head *scs_buckethead;
+ int scs_size;
+ int scs_count;
+ int scs_use;
+ u_int32_t scs_random[5];
};
#endif /* _KERNEL */
#define TCPCTL_ALWAYS_KEEPALIVE 22 /* assume SO_KEEPALIVE is always set */
#define TCPCTL_SYN_USE_LIMIT 23 /* number of uses before reseeding hash */
#define TCPCTL_ROOTONLY 24 /* return root only port bitmap */
-#define TCPCTL_MAXID 25
+#define TCPCTL_SYN_HASH_SIZE 25 /* number of buckets in the hash */
+#define TCPCTL_MAXID 26
#define TCPCTL_NAMES { \
{ 0, 0 }, \
{ "always_keepalive", CTLTYPE_INT }, \
{ "synuselimit", CTLTYPE_INT }, \
{ "rootonly", CTLTYPE_STRUCT }, \
+ { "synhashsize", CTLTYPE_INT }, \
}
#define TCPCTL_VARS { \
NULL, \
NULL, \
NULL, \
+ NULL, \
NULL \
}
extern struct pool tcpqe_pool;
extern int tcp_reass_limit; /* max entries for tcp reass queues */
+extern int tcp_syn_hash_size; /* adjustable size of the hash array */
extern int tcp_syn_cache_limit; /* max entries for compressed state engine */
extern int tcp_syn_bucket_limit;/* max entries per hash bucket */
extern int tcp_syn_use_limit; /* number of uses before reseeding hash */
-/* $OpenBSD: malloc.h,v 1.112 2015/08/24 15:33:49 mpi Exp $ */
+/* $OpenBSD: malloc.h,v 1.113 2016/07/20 09:15:28 bluhm Exp $ */
/* $NetBSD: malloc.h,v 1.39 1998/07/12 19:52:01 augustss Exp $ */
/*
#define M_KEVENT 137 /* kqueue related */
/* 138 free */
- /* 139 free */
+#define M_SYNCACHE 139 /* syn cache hash array */
#define M_UDFMOUNT 140 /* UDF mount */
#define M_UDFFENTRY 141 /* UDF file entry */
"NTFS vrun", /* 136 M_NTFSRUN */ \
"kqueue", /* 137 M_KEVENT */ \
NULL, /* 138 free */ \
- "NULL", \
+ "SYN cache", /* 139 M_SYNCACHE */ \
"UDF mount", /* 140 M_UDFMOUNT */ \
"UDF file entry", /* 141 M_UDFFENTRY */ \
"UDF file id", /* 142 M_UDFFID */ \