Hi, On Tue, 17 Jun 2014 12:48:24 +0900 (JST) YASUOKA Masahiko <yasu...@yasuoka.net> wrote: > On Mon, 16 Jun 2014 11:35:07 -0600 > Theo de Raadt <dera...@cvs.openbsd.org> wrote: >>> > Followings are our kernel variables' default: >>> > >>> > - sb_max: 256K >>> > - tcbhash_size: 128 >>> > - udbhash_size: 128 >>> > >>> > These variables are sometime too small for busy server or gateway. >>> > >>> > I'd like to modify config(8) to customize these variables without >>> > recompiling the kernel. >>> >>> If we go this route, I would rather have a generic command (such as "set >>> <kernel variable name> <value>") to change kernel variables. >>> >>> The list of said variables would still be restricted to what a given >>> config(8) knows, to prevent people from tinkering with things they are >>> not supposed to touch. >> >> I quite dislike the direction this is going. >> >> It seems like you have found 3 variables which should auto-tune. >> So why not write kernel code to auto-tune them? > > I didn't notice that way, but auto-tune seems better. > > I modified in_pcbtable to resize automatically if the number of pcb > entries beyonds 75% of the hash size. I'm testing this.
I've tested and any problem was not found. As far as my test, this improved relayd's HTTP connection relay rate from 5000 conn/sec to 8000 conn/sec on Core2 Duo. ok? Resize the pcb hashtable automatically. The table size will be doubled when the number of the hash entries reaches 75% of the table size. Index: sys/netinet/in_pcb.c =================================================================== RCS file: /disk/cvs/openbsd/src/sys/netinet/in_pcb.c,v retrieving revision 1.156 diff -u -p -r1.156 in_pcb.c --- sys/netinet/in_pcb.c 4 Jun 2014 13:45:47 -0000 1.156 +++ sys/netinet/in_pcb.c 27 Jun 2014 09:53:27 -0000 @@ -118,6 +118,10 @@ struct baddynamicports baddynamicports; struct pool inpcb_pool; int inpcb_pool_initialized = 0; +int in_pcbresize (struct inpcbtable *, int); + +#define INPCBHASH_LOADFACTOR(_x) (((_x) * 3) / 4) + #define INPCBHASH(table, faddr, fport, laddr, lport, rdom) \ &(table)->inpt_hashtbl[(ntohl((faddr)->s_addr) + \ ntohs((fport)) + ntohs((lport)) + (rdom)) & (table->inpt_hash)] @@ -144,6 +148,7 @@ in_pcbinit(struct inpcbtable *table, int if (table->inpt_lhashtbl == NULL) panic("in_pcbinit: hashinit failed for lport"); table->inpt_lastport = 0; + table->inpt_count = 0; } /* @@ -191,6 +196,9 @@ in_pcballoc(struct socket *so, struct in inp->inp_seclevel[SL_IPCOMP] = IPSEC_IPCOMP_LEVEL_DEFAULT; inp->inp_rtableid = curproc->p_p->ps_rtableid; s = splnet(); + if (table->inpt_hash != 0 && + table->inpt_count++ > INPCBHASH_LOADFACTOR(table->inpt_hash)) + (void)in_pcbresize(table, (table->inpt_hash + 1) * 2); TAILQ_INSERT_HEAD(&table->inpt_queue, inp, inp_queue); LIST_INSERT_HEAD(INPCBLHASH(table, inp->inp_lport, inp->inp_rtableid), inp, inp_lhash); @@ -502,6 +510,7 @@ in_pcbdetach(struct inpcb *inp) LIST_REMOVE(inp, inp_lhash); LIST_REMOVE(inp, inp_hash); TAILQ_REMOVE(&inp->inp_table->inpt_queue, inp, inp_queue); + inp->inp_table->inpt_count--; splx(s); pool_put(&inpcb_pool, inp); } @@ -878,6 +887,39 @@ in_pcbrehash(struct inpcb *inp) } #endif /* INET6 */ splx(s); +} + +int +in_pcbresize(struct inpcbtable *table, int hashsize) +{ + u_long nhash, nlhash; + void *nhashtbl, *nlhashtbl, *ohashtbl, *olhashtbl; + struct inpcb *inp0, *inp1; + + ohashtbl = table->inpt_hashtbl; + olhashtbl = table->inpt_lhashtbl; + + nhashtbl = hashinit(hashsize, M_PCB, M_NOWAIT, &nhash); + nlhashtbl = hashinit(hashsize, M_PCB, M_NOWAIT, &nlhash); + if (nhashtbl == NULL || nlhashtbl == NULL) { + if (nhashtbl != NULL) + free(nhashtbl, M_PCB); + if (nlhashtbl != NULL) + free(nlhashtbl, M_PCB); + return (ENOBUFS); + } + table->inpt_hashtbl = nhashtbl; + table->inpt_lhashtbl = nlhashtbl; + table->inpt_hash = nhash; + table->inpt_lhash = nlhash; + + TAILQ_FOREACH_SAFE(inp0, &table->inpt_queue, inp_queue, inp1) { + in_pcbrehash(inp0); + } + free(ohashtbl, M_PCB); + free(olhashtbl, M_PCB); + + return (0); } #ifdef DIAGNOSTIC Index: sys/netinet/in_pcb.h =================================================================== RCS file: /disk/cvs/openbsd/src/sys/netinet/in_pcb.h,v retrieving revision 1.85 diff -u -p -r1.85 in_pcb.h --- sys/netinet/in_pcb.h 18 Apr 2014 10:48:29 -0000 1.85 +++ sys/netinet/in_pcb.h 27 Jun 2014 09:52:26 -0000 @@ -158,6 +158,7 @@ struct inpcbtable { LIST_HEAD(inpcbhead, inpcb) *inpt_hashtbl, *inpt_lhashtbl; u_long inpt_hash, inpt_lhash; u_int16_t inpt_lastport; + int inpt_count; }; /* flags in inp_flags: */ Index: sys/netinet/tcp_subr.c =================================================================== RCS file: /disk/cvs/openbsd/src/sys/netinet/tcp_subr.c,v retrieving revision 1.129 diff -u -p -r1.129 tcp_subr.c --- sys/netinet/tcp_subr.c 21 Apr 2014 12:22:26 -0000 1.129 +++ sys/netinet/tcp_subr.c 27 Jun 2014 09:52:26 -0000 @@ -118,10 +118,9 @@ int tcp_do_rfc3390 = 2; /* Increase TCP' u_int32_t tcp_now = 1; -#ifndef TCBHASHSIZE -#define TCBHASHSIZE 128 +#ifndef TCB_INITIAL_HASH_SIZE +#define TCB_INITIAL_HASH_SIZE 128 #endif -int tcbhashsize = TCBHASHSIZE; /* syn hash parameters */ #define TCP_SYN_HASH_SIZE 293 @@ -162,7 +161,7 @@ tcp_init() NULL); pool_sethardlimit(&sackhl_pool, tcp_sackhole_limit, NULL, 0); #endif /* TCP_SACK */ - in_pcbinit(&tcbtable, tcbhashsize); + in_pcbinit(&tcbtable, TCB_INITIAL_HASH_SIZE); #ifdef INET6 /* Index: sys/netinet/udp_usrreq.c =================================================================== RCS file: /disk/cvs/openbsd/src/sys/netinet/udp_usrreq.c,v retrieving revision 1.186 diff -u -p -r1.186 udp_usrreq.c --- sys/netinet/udp_usrreq.c 23 Jun 2014 22:48:33 -0000 1.186 +++ sys/netinet/udp_usrreq.c 27 Jun 2014 09:52:26 -0000 @@ -139,15 +139,14 @@ int udp_output(struct inpcb *, struct mb void udp_detach(struct inpcb *); void udp_notify(struct inpcb *, int); -#ifndef UDBHASHSIZE -#define UDBHASHSIZE 128 +#ifndef UDB_INITIAL_HASH_SIZE +#define UDB_INITIAL_HASH_SIZE 128 #endif -int udbhashsize = UDBHASHSIZE; void udp_init() { - in_pcbinit(&udbtable, udbhashsize); + in_pcbinit(&udbtable, UDB_INITIAL_HASH_SIZE); } #ifdef INET6