Build a hash table of PCBs. Hash function needs tweaking.
This commit is contained in:
parent
b050cf3d61
commit
67e78477db
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 *));
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue