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.

(currently I have no idea for sb_max.)

comments?

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        17 Jun 2014 03:36:35 -0000
@@ -118,6 +118,8 @@ struct baddynamicports baddynamicports;
 struct pool inpcb_pool;
 int inpcb_pool_initialized = 0;
 
+int in_pcbresize (struct inpcbtable *, int);
+
 #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 +146,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 +194,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++ > (table->inpt_hash * 3) / 4)
+               (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 +508,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 +885,38 @@ 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        17 Jun 2014 03:36:35 -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: */

Reply via email to