Resize the pcb hashtable automatically. The table size will be doubled
authoryasuoka <yasuoka@openbsd.org>
Sat, 12 Jul 2014 21:06:34 +0000 (21:06 +0000)
committeryasuoka <yasuoka@openbsd.org>
Sat, 12 Jul 2014 21:06:34 +0000 (21:06 +0000)
when the number of the hash entries reaches 75% of the table size.

ok dlg henning, 'commit in' claudio

sys/netinet/in_pcb.c
sys/netinet/in_pcb.h
sys/netinet/tcp_subr.c
sys/netinet/udp_usrreq.c

index 6bc1601..24305d9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in_pcb.c,v 1.156 2014/06/04 13:45:47 mpi Exp $        */
+/*     $OpenBSD: in_pcb.c,v 1.157 2014/07/12 21:06:34 yasuoka Exp $    */
 /*     $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $     */
 
 /*
@@ -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 hashsize)
        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 inpcbtable *table)
        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);
 }
@@ -880,6 +889,39 @@ in_pcbrehash(struct inpcb *inp)
        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, 0);
+               if (nlhashtbl != NULL)
+                       free(nlhashtbl, M_PCB, 0);
+               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, 0);
+       free(olhashtbl, M_PCB, 0);
+
+       return (0);
+}
+
 #ifdef DIAGNOSTIC
 int    in_pcbnotifymiss = 0;
 #endif
index 0c27f51..4923eac 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in_pcb.h,v 1.85 2014/04/18 10:48:29 jca Exp $ */
+/*     $OpenBSD: in_pcb.h,v 1.86 2014/07/12 21:06:34 yasuoka Exp $     */
 /*     $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $     */
 
 /*
@@ -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 74d8d72..72ea22b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tcp_subr.c,v 1.130 2014/07/12 18:44:23 tedu Exp $     */
+/*     $OpenBSD: tcp_subr.c,v 1.131 2014/07/12 21:06:34 yasuoka Exp $  */
 /*     $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $   */
 
 /*
@@ -118,10 +118,9 @@ int        tcp_do_rfc3390 = 2;     /* Increase TCP's Initial Window to 10*mss */
 
 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 e553b4a..162f7be 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: udp_usrreq.c,v 1.187 2014/07/11 13:15:34 bluhm Exp $  */
+/*     $OpenBSD: udp_usrreq.c,v 1.188 2014/07/12 21:06:34 yasuoka Exp $        */
 /*     $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
 
 /*
@@ -139,15 +139,14 @@ int       udp_output(struct inpcb *, struct mbuf *, struct mbuf *, struct mbuf *);
 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