use a hash table to bind to local ports; suggested by markus friedl

approved: fvdl@
This commit is contained in:
provos 2003-10-28 17:18:37 +00:00
parent aaff23d58d
commit 57755c156a
2 changed files with 19 additions and 4 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_pcb.c,v 1.89 2003/10/23 20:55:08 mycroft Exp $ */
/* $NetBSD: in_pcb.c,v 1.90 2003/10/28 17:18:37 provos Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -98,7 +98,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.89 2003/10/23 20:55:08 mycroft Exp $");
__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.90 2003/10/28 17:18:37 provos Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -142,6 +142,8 @@ __KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.89 2003/10/23 20:55:08 mycroft Exp $");
struct in_addr zeroin_addr;
#define INPCBHASH_PORT(table, lport) \
&(table)->inpt_porthashtbl[ ntohs(lport) & (table)->inpt_porthash]
#define INPCBHASH_BIND(table, laddr, lport) \
&(table)->inpt_bindhashtbl[ \
((ntohl((laddr).s_addr) + ntohs(lport))) & (table)->inpt_bindhash]
@ -171,6 +173,8 @@ in_pcbinit(table, bindhashsize, connecthashsize)
}
CIRCLEQ_INIT(&table->inpt_queue);
table->inpt_porthashtbl = hashinit(bindhashsize, HASH_LIST, M_PCB,
M_WAITOK, &table->inpt_porthash);
table->inpt_bindhashtbl = hashinit(bindhashsize, HASH_LIST, M_PCB,
M_WAITOK, &table->inpt_bindhash);
table->inpt_connecthashtbl = hashinit(connecthashsize, HASH_LIST,
@ -210,6 +214,8 @@ in_pcballoc(so, v)
s = splnet();
CIRCLEQ_INSERT_HEAD(&table->inpt_queue, &inp->inp_head,
inph_queue);
LIST_INSERT_HEAD(INPCBHASH_PORT(table, inp->inp_lport), &inp->inp_head,
inph_lhash);
in_pcbstate(inp, INP_ATTACHED);
splx(s);
return (0);
@ -351,6 +357,9 @@ noname:
lport = htons(lport);
}
inp->inp_lport = lport;
LIST_REMOVE(&inp->inp_head, inph_lhash);
LIST_INSERT_HEAD(INPCBHASH_PORT(table, inp->inp_lport), &inp->inp_head,
inph_lhash);
in_pcbstate(inp, INP_BOUND);
return (0);
}
@ -500,6 +509,7 @@ in_pcbdetach(v)
ip_freemoptions(inp->inp_moptions);
s = splnet();
in_pcbstate(inp, INP_ATTACHED);
LIST_REMOVE(&inp->inp_head, inph_lhash);
CIRCLEQ_REMOVE(&inp->inp_table->inpt_queue, &inp->inp_head,
inph_queue);
splx(s);
@ -739,12 +749,14 @@ in_pcblookup_port(table, laddr, lport_arg, lookup_wildcard)
u_int lport_arg;
int lookup_wildcard;
{
struct inpcbhead *head;
struct inpcb_hdr *inph;
struct inpcb *inp, *match = 0;
int matchwild = 3, wildcard;
u_int16_t lport = lport_arg;
CIRCLEQ_FOREACH(inph, &table->inpt_queue, inph_queue) {
head = INPCBHASH_PORT(table, lport);
LIST_FOREACH(inph, head, inph_lhash) {
inp = (struct inpcb *)inph;
if (inp->inp_af != AF_INET)
continue;

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_pcb_hdr.h,v 1.1 2003/09/04 09:16:58 itojun Exp $ */
/* $NetBSD: in_pcb_hdr.h,v 1.2 2003/10/28 17:18:37 provos Exp $ */
/*
* Copyright (C) 2003 WIDE Project.
@ -72,6 +72,7 @@ struct inpcbpolicy;
*/
struct inpcb_hdr {
LIST_ENTRY(inpcb_hdr) inph_hash;
LIST_ENTRY(inpcb_hdr) inph_lhash;
CIRCLEQ_ENTRY(inpcb_hdr) inph_queue;
int inph_af; /* address family - AF_INET */
caddr_t inph_ppcb; /* pointer to per-protocol pcb */
@ -87,8 +88,10 @@ LIST_HEAD(inpcbhead, inpcb_hdr);
struct inpcbtable {
CIRCLEQ_HEAD(, inpcb_hdr) inpt_queue;
struct inpcbhead *inpt_porthashtbl;
struct inpcbhead *inpt_bindhashtbl;
struct inpcbhead *inpt_connecthashtbl;
u_long inpt_porthash;
u_long inpt_bindhash;
u_long inpt_connecthash;
u_int16_t inpt_lastport;