Build a hash table of PCBs. Hash function needs tweaking.

This commit is contained in:
mycroft 1996-01-31 03:49:23 +00:00
parent b050cf3d61
commit 67e78477db
8 changed files with 130 additions and 55 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_pcb.c,v 1.23 1995/08/17 02:57:27 mycroft Exp $ */
/* $NetBSD: in_pcb.c,v 1.24 1996/01/31 03:49:23 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1991, 1993
@ -59,12 +59,17 @@
struct in_addr zeroin_addr;
#define INPCBHASH(table, faddr, fport, laddr, lport) \
&(table)->inpt_hashtbl[(ntohl((faddr)->s_addr) + ntohs((fport)) + ntohs((lport))) & (table->inpt_hash)]
void
in_pcbinit(table)
in_pcbinit(table, hashsize)
struct inpcbtable *table;
int hashsize;
{
CIRCLEQ_INIT(&table->inpt_queue);
table->inpt_hashtbl = hashinit(hashsize, M_PCB, &table->inpt_hash);
table->inpt_lastport = 0;
}
@ -74,6 +79,7 @@ in_pcballoc(so, table)
struct inpcbtable *table;
{
register struct inpcb *inp;
int s;
MALLOC(inp, struct inpcb *, sizeof(*inp), M_PCB, M_WAITOK);
if (inp == NULL)
@ -81,7 +87,11 @@ in_pcballoc(so, table)
bzero((caddr_t)inp, sizeof(*inp));
inp->inp_table = table;
inp->inp_socket = so;
s = splnet();
CIRCLEQ_INSERT_HEAD(&table->inpt_queue, inp, inp_queue);
LIST_INSERT_HEAD(INPCBHASH(table, &inp->inp_faddr, inp->inp_fport,
&inp->inp_laddr, inp->inp_lport), inp, inp_hash);
splx(s);
so->so_pcb = inp;
return (0);
}
@ -158,6 +168,7 @@ in_pcbbind(inp, nam)
} while (in_pcblookup(table,
zeroin_addr, 0, inp->inp_laddr, lport, wild));
inp->inp_lport = lport;
in_pcbrehash(inp);
return (0);
}
@ -265,12 +276,9 @@ in_pcbconnect(inp, nam)
}
ifaddr = satosin(&ia->ia_addr);
}
if (in_pcblookup(inp->inp_table,
sin->sin_addr,
sin->sin_port,
if (in_pcbhashlookup(inp->inp_table, sin->sin_addr, sin->sin_port,
inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
inp->inp_lport,
0))
inp->inp_lport) != 0)
return (EADDRINUSE);
if (inp->inp_laddr.s_addr == INADDR_ANY) {
if (inp->inp_lport == 0)
@ -279,6 +287,7 @@ in_pcbconnect(inp, nam)
}
inp->inp_faddr = sin->sin_addr;
inp->inp_fport = sin->sin_port;
in_pcbrehash(inp);
return (0);
}
@ -289,6 +298,7 @@ in_pcbdisconnect(inp)
inp->inp_faddr.s_addr = INADDR_ANY;
inp->inp_fport = 0;
in_pcbrehash(inp);
if (inp->inp_socket->so_state & SS_NOFDREF)
in_pcbdetach(inp);
}
@ -298,6 +308,7 @@ in_pcbdetach(inp)
struct inpcb *inp;
{
struct socket *so = inp->inp_socket;
int s;
so->so_pcb = 0;
sofree(so);
@ -306,7 +317,10 @@ in_pcbdetach(inp)
if (inp->inp_route.ro_rt)
rtfree(inp->inp_route.ro_rt);
ip_freemoptions(inp->inp_moptions);
s = splnet();
LIST_REMOVE(inp, inp_hash);
CIRCLEQ_REMOVE(&inp->inp_table->inpt_queue, inp, inp_queue);
splx(s);
FREE(inp, M_PCB);
}
@ -488,15 +502,6 @@ in_pcblookup(table, faddr, fport_arg, laddr, lport_arg, flags)
if (inp->inp_lport != lport)
continue;
wildcard = 0;
if (inp->inp_laddr.s_addr != INADDR_ANY) {
if (laddr.s_addr == INADDR_ANY)
wildcard++;
else if (inp->inp_laddr.s_addr != laddr.s_addr)
continue;
} else {
if (laddr.s_addr != INADDR_ANY)
wildcard++;
}
if (inp->inp_faddr.s_addr != INADDR_ANY) {
if (faddr.s_addr == INADDR_ANY)
wildcard++;
@ -507,6 +512,15 @@ in_pcblookup(table, faddr, fport_arg, laddr, lport_arg, flags)
if (faddr.s_addr != INADDR_ANY)
wildcard++;
}
if (inp->inp_laddr.s_addr != INADDR_ANY) {
if (laddr.s_addr == INADDR_ANY)
wildcard++;
else if (inp->inp_laddr.s_addr != laddr.s_addr)
continue;
} else {
if (laddr.s_addr != INADDR_ANY)
wildcard++;
}
if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
continue;
if (wildcard < matchwild) {
@ -518,3 +532,59 @@ in_pcblookup(table, faddr, fport_arg, laddr, lport_arg, flags)
}
return (match);
}
void
in_pcbrehash(inp)
struct inpcb *inp;
{
struct inpcbtable *table = inp->inp_table;
int s;
s = splnet();
LIST_REMOVE(inp, inp_hash);
LIST_INSERT_HEAD(INPCBHASH(table, &inp->inp_faddr, inp->inp_fport,
&inp->inp_laddr, inp->inp_lport), inp, inp_hash);
splx(s);
}
#ifdef DIAGNOSTIC
int in_pcbnotifymiss = 0;
#endif
struct inpcb *
in_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg)
struct inpcbtable *table;
struct in_addr faddr, laddr;
u_int fport_arg, lport_arg;
{
struct inpcbhead *head;
register struct inpcb *inp;
u_int16_t fport = fport_arg, lport = lport_arg;
head = INPCBHASH(table, &faddr, fport, &laddr, lport);
for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
if (inp->inp_faddr.s_addr == faddr.s_addr &&
inp->inp_fport == fport &&
inp->inp_lport == lport &&
inp->inp_laddr.s_addr == laddr.s_addr) {
/*
* Move this PCB to the head of hash chain so that
* repeated accesses are quicker. This is analogous to
* the historic single-entry PCB cache.
*/
if (inp != head->lh_first) {
LIST_REMOVE(inp, inp_hash);
LIST_INSERT_HEAD(head, inp, inp_hash);
}
break;
}
}
#ifdef DIAGNOSTIC
if (inp == NULL && in_pcbnotifymiss) {
printf("in_pcbhashlookup: faddr=%08x fport=%d laddr=%08x lport=%d\n",
ntohl(faddr.s_addr), ntohs(fport),
ntohl(laddr.s_addr), ntohs(lport));
}
#endif
return (inp);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_pcb.h,v 1.12 1995/06/18 20:01:13 cgd Exp $ */
/* $NetBSD: in_pcb.h,v 1.13 1996/01/31 03:49:30 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1990, 1993
@ -45,6 +45,7 @@
* control block.
*/
struct inpcb {
LIST_ENTRY(inpcb) inp_hash;
CIRCLEQ_ENTRY(inpcb) inp_queue;
struct inpcbtable *inp_table;
struct in_addr inp_faddr; /* foreign host table entry */
@ -61,7 +62,9 @@ struct inpcb {
};
struct inpcbtable {
CIRCLEQ_HEAD(inpcbhead, inpcb) inpt_queue;
CIRCLEQ_HEAD(, inpcb) inpt_queue;
LIST_HEAD(inpcbhead, inpcb) *inpt_hashtbl;
u_long inpt_hash;
u_int16_t inpt_lastport;
};
@ -84,7 +87,10 @@ int in_pcbbind __P((struct inpcb *, struct mbuf *));
int in_pcbconnect __P((struct inpcb *, struct mbuf *));
int in_pcbdetach __P((struct inpcb *));
int in_pcbdisconnect __P((struct inpcb *));
void in_pcbinit __P((struct inpcbtable *));
struct inpcb *
in_pcbhashlookup __P((struct inpcbtable *,
struct in_addr, u_int, struct in_addr, u_int));
void in_pcbinit __P((struct inpcbtable *, int));
struct inpcb *
in_pcblookup __P((struct inpcbtable *,
struct in_addr, u_int, struct in_addr, u_int, int));
@ -92,6 +98,7 @@ void in_pcbnotify __P((struct inpcbtable *, struct sockaddr *,
u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int)));
void in_pcbnotifyall __P((struct inpcbtable *, struct sockaddr *,
int, void (*)(struct inpcb *, int)));
void in_pcbrehash __P((struct inpcb *));
void in_rtchange __P((struct inpcb *, int));
int in_setpeeraddr __P((struct inpcb *, struct mbuf *));
int in_setsockaddr __P((struct inpcb *, struct mbuf *));

View File

@ -1,4 +1,4 @@
/* $NetBSD: raw_ip.c,v 1.22 1995/11/30 16:42:18 pk Exp $ */
/* $NetBSD: raw_ip.c,v 1.23 1996/01/31 03:49:31 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1988, 1993
@ -73,7 +73,7 @@ void
rip_init()
{
in_pcbinit(&rawcbtable);
in_pcbinit(&rawcbtable, 1);
}
struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_input.c,v 1.20 1995/11/21 01:07:39 cgd Exp $ */
/* $NetBSD: tcp_input.c,v 1.21 1996/01/31 03:49:33 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994
@ -63,7 +63,6 @@
int tcprexmtthresh = 3;
struct tcpiphdr tcp_saveti;
struct inpcb *tcp_last_inpcb = 0;
extern u_long sb_max;
@ -338,13 +337,10 @@ tcp_input(m, iphlen)
* Locate pcb for segment.
*/
findpcb:
inp = tcp_last_inpcb;
if (inp == 0 ||
inp->inp_lport != ti->ti_dport ||
inp->inp_fport != ti->ti_sport ||
inp->inp_faddr.s_addr != ti->ti_src.s_addr ||
inp->inp_laddr.s_addr != ti->ti_dst.s_addr) {
++tcpstat.tcps_pcbcachemiss;
inp = in_pcbhashlookup(&tcbtable, ti->ti_src, ti->ti_sport,
ti->ti_dst, ti->ti_dport);
if (inp == 0) {
++tcpstat.tcps_pcbhashmiss;
inp = in_pcblookup(&tcbtable, ti->ti_src, ti->ti_sport,
ti->ti_dst, ti->ti_dport, INPLOOKUP_WILDCARD);
/*
@ -353,9 +349,10 @@ findpcb:
* If the TCB exists but is in CLOSED state, it is embryonic,
* but should either do a listen or a connect soon.
*/
if (inp == 0)
if (inp == 0) {
++tcpstat.tcps_noport;
goto dropwithreset;
tcp_last_inpcb = inp;
}
}
tp = intotcpcb(inp);
@ -395,6 +392,7 @@ findpcb:
inp = (struct inpcb *)so->so_pcb;
inp->inp_laddr = ti->ti_dst;
inp->inp_lport = ti->ti_dport;
in_pcbrehash(inp);
#if BSD>=43
inp->inp_options = ip_srcroute();
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_subr.c,v 1.20 1995/11/21 01:07:41 cgd Exp $ */
/* $NetBSD: tcp_subr.c,v 1.21 1996/01/31 03:49:35 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1988, 1990, 1993
@ -66,7 +66,10 @@ int tcp_mssdflt = TCP_MSS;
int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
int tcp_do_rfc1323 = 1;
extern struct inpcb *tcp_last_inpcb;
#ifndef TCBHASHSIZE
#define TCBHASHSIZE 128
#endif
int tcbhashsize = TCBHASHSIZE;
/*
* Tcp initialization
@ -76,7 +79,7 @@ tcp_init()
{
tcp_iss = 1; /* wrong */
in_pcbinit(&tcbtable);
in_pcbinit(&tcbtable, tcbhashsize);
if (max_protohdr < sizeof(struct tcpiphdr))
max_protohdr = sizeof(struct tcpiphdr);
if (max_linkhdr + sizeof(struct tcpiphdr) > MHLEN)
@ -354,9 +357,6 @@ tcp_close(tp)
free(tp, M_PCB);
inp->inp_ppcb = 0;
soisdisconnected(so);
/* clobber input pcb cache if we're closing the cached connection */
if (inp == tcp_last_inpcb)
tcp_last_inpcb = 0;
in_pcbdetach(inp);
tcpstat.tcps_closed++;
return ((struct tcpcb *)0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_var.h,v 1.15 1995/11/21 01:07:43 cgd Exp $ */
/* $NetBSD: tcp_var.h,v 1.16 1996/01/31 03:49:36 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1993, 1994
@ -220,7 +220,9 @@ struct tcpstat {
u_long tcps_pawsdrop; /* segments dropped due to PAWS */
u_long tcps_predack; /* times hdr predict ok for acks */
u_long tcps_preddat; /* times hdr predict ok for data pkts */
u_long tcps_pcbcachemiss;
u_long tcps_pcbhashmiss; /* input packets missing pcb hash */
u_long tcps_noport; /* no socket on port */
};
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: udp_usrreq.c,v 1.25 1995/11/21 01:07:46 cgd Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.26 1996/01/31 03:49:38 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1988, 1990, 1993
@ -68,17 +68,21 @@ int udpcksum = 0; /* XXX */
#endif
struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
struct inpcb *udp_last_inpcb = 0;
static void udp_detach __P((struct inpcb *));
static void udp_notify __P((struct inpcb *, int));
static struct mbuf *udp_saveopt __P((caddr_t, int, int));
#ifndef UDBHASHSIZE
#define UDBHASHSIZE 128
#endif
int udbhashsize = UDBHASHSIZE;
void
udp_init()
{
in_pcbinit(&udbtable);
in_pcbinit(&udbtable, udbhashsize);
}
void
@ -246,13 +250,10 @@ udp_input(m, iphlen)
/*
* Locate pcb for datagram.
*/
inp = udp_last_inpcb;
if (inp == 0 ||
inp->inp_lport != uh->uh_dport ||
inp->inp_fport != uh->uh_sport ||
inp->inp_faddr.s_addr != ip->ip_src.s_addr ||
inp->inp_laddr.s_addr != ip->ip_dst.s_addr) {
udpstat.udpps_pcbcachemiss++;
inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport,
ip->ip_dst, uh->uh_dport);
if (inp == 0) {
++udpstat.udps_pcbhashmiss;
inp = in_pcblookup(&udbtable, ip->ip_src, uh->uh_sport,
ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD);
if (inp == 0) {
@ -266,7 +267,6 @@ udp_input(m, iphlen)
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
return;
}
udp_last_inpcb = inp;
}
/*
@ -621,8 +621,6 @@ udp_detach(inp)
{
int s = splsoftnet();
if (inp == udp_last_inpcb)
udp_last_inpcb = 0;
in_pcbdetach(inp);
splx(s);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: udp_var.h,v 1.10 1995/11/21 01:07:48 cgd Exp $ */
/* $NetBSD: udp_var.h,v 1.11 1996/01/31 03:49:39 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -61,7 +61,7 @@ struct udpstat {
u_long udps_noport; /* no socket on port */
u_long udps_noportbcast; /* of above, arrived as broadcast */
u_long udps_fullsock; /* not delivered, input socket full */
u_long udpps_pcbcachemiss; /* input packets missing pcb cache */
u_long udps_pcbhashmiss; /* input packets missing pcb hash */
/* output statistics: */
u_long udps_opackets; /* total output packets */
};