Hi,
On Tue, 17 Jun 2014 12:48:24 +0900 (JST)
YASUOKA Masahiko <[email protected]> wrote:
> On Mon, 16 Jun 2014 11:35:07 -0600
> Theo de Raadt <[email protected]> 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