diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -463,7 +463,8 @@ struct inpcbhead *ipi_hash_exact; /* (r:e/w:h) */ struct inpcbhead *ipi_hash_wild; /* (r:e/w:h) */ u_long ipi_hashmask; /* (c) */ - u_long ipi_porthashmask; /* (h) */ + u_long ipi_porthashmask; /* (c) */ + u_long ipi_lbgrouphashmask; /* (c) */ /* * Global hash of inpcbs, hashed by only local port number. @@ -644,7 +645,7 @@ #define V_ipport_randomized VNET(ipport_randomized) void in_pcbinfo_init(struct inpcbinfo *, struct inpcbstorage *, - u_int, u_int); + u_int, u_int, u_int); void in_pcbinfo_destroy(struct inpcbinfo *); void in_pcbstorage_init(void *); void in_pcbstorage_destroy(void *); diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -302,7 +302,7 @@ INP_HASH_LOCK_ASSERT(pcbinfo); hdr = &pcbinfo->ipi_lbgrouphashbase[ - INP_PCBPORTHASH(inp->inp_lport, pcbinfo->ipi_porthashmask)]; + INP_PCBPORTHASH(inp->inp_lport, pcbinfo->ipi_lbgrouphashmask)]; CK_LIST_FOREACH(grp, hdr, il_list) { struct inpcb *inp1; @@ -410,7 +410,7 @@ } #endif - idx = INP_PCBPORTHASH(inp->inp_lport, pcbinfo->ipi_porthashmask); + idx = INP_PCBPORTHASH(inp->inp_lport, pcbinfo->ipi_lbgrouphashmask); hdr = &pcbinfo->ipi_lbgrouphashbase[idx]; CK_LIST_FOREACH(grp, hdr, il_list) { if (grp->il_cred->cr_prison == inp->inp_cred->cr_prison && @@ -471,7 +471,7 @@ INP_HASH_WLOCK_ASSERT(pcbinfo); hdr = &pcbinfo->ipi_lbgrouphashbase[ - INP_PCBPORTHASH(inp->inp_lport, pcbinfo->ipi_porthashmask)]; + INP_PCBPORTHASH(inp->inp_lport, pcbinfo->ipi_lbgrouphashmask)]; CK_LIST_FOREACH(grp, hdr, il_list) { for (i = 0; i < grp->il_inpcnt; ++i) { if (grp->il_inp[i] != inp) @@ -547,7 +547,7 @@ */ void in_pcbinfo_init(struct inpcbinfo *pcbinfo, struct inpcbstorage *pcbstor, - u_int hash_nelements, u_int porthash_nelements) + u_int hash_nelements, u_int porthash_nelements, u_int lbgrouphash_nelements) { struct hashalloc_args ha = { .mtype = M_PCB, @@ -565,10 +565,18 @@ pcbinfo->ipi_hash_wild = hashalloc(&ha); pcbinfo->ipi_hashmask = ha.size - 1; - ha.size = imin(porthash_nelements, IPPORT_MAX + 1); - pcbinfo->ipi_porthashbase = hashalloc(&ha); - pcbinfo->ipi_lbgrouphashbase = hashalloc(&ha); - pcbinfo->ipi_porthashmask = ha.size - 1; + if (porthash_nelements > 0) { + ha.size = imin(porthash_nelements, IPPORT_MAX + 1); + pcbinfo->ipi_porthashbase = hashalloc(&ha); + pcbinfo->ipi_porthashmask = ha.size - 1; + } else + pcbinfo->ipi_porthashbase = NULL; + if (lbgrouphash_nelements > 0) { + ha.size = imin(lbgrouphash_nelements, IPPORT_MAX + 1); + pcbinfo->ipi_lbgrouphashbase = hashalloc(&ha); + pcbinfo->ipi_lbgrouphashmask = ha.size - 1; + } else + pcbinfo->ipi_lbgrouphashbase = NULL; pcbinfo->ipi_zone = pcbstor->ips_zone; pcbinfo->ipi_smr = uma_zone_get_smr(pcbinfo->ipi_zone); @@ -591,9 +599,14 @@ ha.size = pcbinfo->ipi_hashmask + 1; hashfree(pcbinfo->ipi_hash_exact, &ha); hashfree(pcbinfo->ipi_hash_wild, &ha); - ha.size = pcbinfo->ipi_porthashmask + 1; - hashfree(pcbinfo->ipi_porthashbase, &ha); - hashfree(pcbinfo->ipi_lbgrouphashbase, &ha); + if (pcbinfo->ipi_porthashbase != NULL) { + ha.size = pcbinfo->ipi_porthashmask + 1; + hashfree(pcbinfo->ipi_porthashbase, &ha); + } + if (pcbinfo->ipi_lbgrouphashbase != NULL) { + ha.size = pcbinfo->ipi_lbgrouphashmask + 1; + hashfree(pcbinfo->ipi_lbgrouphashbase, &ha); + } mtx_destroy(&pcbinfo->ipi_hash_lock); } @@ -2154,7 +2167,7 @@ NET_EPOCH_ASSERT(); hdr = &pcbinfo->ipi_lbgrouphashbase[ - INP_PCBPORTHASH(lport, pcbinfo->ipi_porthashmask)]; + INP_PCBPORTHASH(lport, pcbinfo->ipi_lbgrouphashmask)]; /* * Search for an LB group match based on the following criteria: diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -147,7 +147,7 @@ rip_init(void *arg __unused) { #define INP_PCBHASH_RAW_SIZE 256 - in_pcbinfo_init(&V_ripcbinfo, &ripcbstor, INP_PCBHASH_RAW_SIZE, 1); + in_pcbinfo_init(&V_ripcbinfo, &ripcbstor, INP_PCBHASH_RAW_SIZE, 0, 0); } VNET_SYSINIT(rip_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rip_init, NULL); diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1454,7 +1454,7 @@ __func__); #endif in_pcbinfo_init(&V_tcbinfo, &tcpcbstor, tcp_tcbhashsize, - tcp_tcbhashsize); + tcp_tcbhashsize, tcp_tcbhashsize); syncache_init(); tcp_hc_init(); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -180,10 +180,11 @@ * Once we can calculate the flowid that way and re-establish * a 4-tuple, flip this to 4-tuple. */ - in_pcbinfo_init(&V_udbinfo, &udpcbstor, UDBHASHSIZE, UDBHASHSIZE); + in_pcbinfo_init(&V_udbinfo, &udpcbstor, UDBHASHSIZE, UDBHASHSIZE, + UDBHASHSIZE); /* Additional pcbinfo for UDP-Lite */ in_pcbinfo_init(&V_ulitecbinfo, &udplitecbstor, UDBHASHSIZE, - UDBHASHSIZE); + UDBHASHSIZE, UDBHASHSIZE); } VNET_SYSINIT(udp_vnet_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, udp_vnet_init, NULL);