Improved in_pcblookuphash() to support wildcarding, and changed relavent

callers of it to take advantage of this. This reduces new connection
request overhead in the face of a large number of PCBs in the system.
Thanks to David Filo <filo@yahoo.com> for suggesting this and providing
a sample implementation (which wasn't used, but showed that it could be
done).

Reviewed by:	wollman
This commit is contained in:
David Greenman 1996-10-07 19:06:12 +00:00
parent 545c48b83a
commit 6d6a026b47
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=18795
6 changed files with 60 additions and 67 deletions

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)in_pcb.c 8.4 (Berkeley) 5/24/95
* $Id: in_pcb.c,v 1.20 1996/08/12 14:05:54 peter Exp $
* $Id: in_pcb.c,v 1.21 1996/08/23 18:59:05 phk Exp $
*/
#include <sys/param.h>
@ -140,7 +140,6 @@ in_pcbbind(inp, nam)
struct mbuf *nam;
{
register struct socket *so = inp->inp_socket;
struct inpcbhead *head = inp->inp_pcbinfo->listhead;
unsigned short *lastport = &inp->inp_pcbinfo->lastport;
struct sockaddr_in *sin;
struct proc *p = curproc; /* XXX */
@ -155,7 +154,7 @@ in_pcbbind(inp, nam)
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
(so->so_options & SO_ACCEPTCONN) == 0))
wild = INPLOOKUP_WILDCARD;
wild = 1;
if (nam) {
sin = mtod(nam, struct sockaddr_in *);
if (nam->m_len != sizeof (*sin))
@ -191,7 +190,7 @@ in_pcbbind(inp, nam)
if (ntohs(lport) < IPPORT_RESERVED &&
(error = suser(p->p_ucred, &p->p_acflag)))
return (EACCES);
t = in_pcblookup(head, zeroin_addr, 0,
t = in_pcblookup(inp->inp_pcbinfo, zeroin_addr, 0,
sin->sin_addr, lport, wild);
if (t && (reuseport & t->inp_socket->so_options) == 0)
return (EADDRINUSE);
@ -236,7 +235,7 @@ in_pcbbind(inp, nam)
if (*lastport > first || *lastport < last)
*lastport = first;
lport = htons(*lastport);
} while (in_pcblookup(head,
} while (in_pcblookup(inp->inp_pcbinfo,
zeroin_addr, 0, inp->inp_laddr, lport, wild));
} else {
/*
@ -251,7 +250,7 @@ in_pcbbind(inp, nam)
if (*lastport < first || *lastport > last)
*lastport = first;
lport = htons(*lastport);
} while (in_pcblookup(head,
} while (in_pcblookup(inp->inp_pcbinfo,
zeroin_addr, 0, inp->inp_laddr, lport, wild));
}
}
@ -405,7 +404,7 @@ in_pcbconnect(inp, nam)
if (in_pcblookuphash(inp->inp_pcbinfo, sin->sin_addr, sin->sin_port,
inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
inp->inp_lport) != NULL)
inp->inp_lport, 0) != NULL)
return (EADDRINUSE);
if (inp->inp_laddr.s_addr == INADDR_ANY) {
if (inp->inp_lport == 0)
@ -601,11 +600,11 @@ in_rtchange(inp, errno)
}
struct inpcb *
in_pcblookup(head, faddr, fport_arg, laddr, lport_arg, flags)
struct inpcbhead *head;
in_pcblookup(pcbinfo, faddr, fport_arg, laddr, lport_arg, wild_okay)
struct inpcbinfo *pcbinfo;
struct in_addr faddr, laddr;
u_int fport_arg, lport_arg;
int flags;
int wild_okay;
{
register struct inpcb *inp, *match = NULL;
int matchwild = 3, wildcard;
@ -614,7 +613,7 @@ in_pcblookup(head, faddr, fport_arg, laddr, lport_arg, flags)
s = splnet();
for (inp = head->lh_first; inp != NULL; inp = inp->inp_list.le_next) {
for (inp = pcbinfo->listhead->lh_first; inp != NULL; inp = inp->inp_list.le_next) {
if (inp->inp_lport != lport)
continue;
wildcard = 0;
@ -637,7 +636,7 @@ in_pcblookup(head, faddr, fport_arg, laddr, lport_arg, flags)
if (laddr.s_addr != INADDR_ANY)
wildcard++;
}
if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
if (wildcard && wild_okay == 0)
continue;
if (wildcard < matchwild) {
match = inp;
@ -655,10 +654,11 @@ in_pcblookup(head, faddr, fport_arg, laddr, lport_arg, flags)
* Lookup PCB in hash list.
*/
struct inpcb *
in_pcblookuphash(pcbinfo, faddr, fport_arg, laddr, lport_arg)
in_pcblookuphash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard)
struct inpcbinfo *pcbinfo;
struct in_addr faddr, laddr;
u_int fport_arg, lport_arg;
int wildcard;
{
struct inpcbhead *head;
register struct inpcb *inp;
@ -670,22 +670,43 @@ in_pcblookuphash(pcbinfo, faddr, fport_arg, laddr, lport_arg)
* First look for an exact match.
*/
head = &pcbinfo->hashbase[(faddr.s_addr + lport + fport) % pcbinfo->hashsize];
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)
continue;
/*
* Move PCB to head of this hash chain so that it can be
* found more quickly in the future.
*/
if (inp != head->lh_first) {
LIST_REMOVE(inp, inp_hash);
LIST_INSERT_HEAD(head, inp, inp_hash);
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)
goto found;
}
if (wildcard) {
struct inpcb *local_wild = NULL;
head = &pcbinfo->hashbase[(INADDR_ANY + lport) % pcbinfo->hashsize];
for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
if (inp->inp_faddr.s_addr == INADDR_ANY &&
inp->inp_fport == 0 && inp->inp_lport == lport) {
if (inp->inp_laddr.s_addr == laddr.s_addr)
goto found;
else if (inp->inp_laddr.s_addr == INADDR_ANY)
local_wild = inp;
}
}
break;
if (local_wild != NULL) {
inp = local_wild;
goto found;
}
}
splx(s);
return (NULL);
found:
/*
* Move PCB to head of this hash chain so that it can be
* found more quickly in the future.
* XXX - this is a pessimization on machines with few
* concurrent connections.
*/
if (inp != head->lh_first) {
LIST_REMOVE(inp, inp_hash);
LIST_INSERT_HEAD(head, inp, inp_hash);
}
splx(s);
return (inp);

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)in_pcb.h 8.1 (Berkeley) 6/10/93
* $Id: in_pcb.h,v 1.11 1996/02/22 21:32:22 peter Exp $
* $Id: in_pcb.h,v 1.12 1996/08/23 18:59:07 phk Exp $
*/
#ifndef _NETINET_IN_PCB_H_
@ -96,11 +96,11 @@ void in_pcbdisconnect __P((struct inpcb *));
int in_pcbladdr __P((struct inpcb *, struct mbuf *,
struct sockaddr_in **));
struct inpcb *
in_pcblookup __P((struct inpcbhead *,
in_pcblookup __P((struct inpcbinfo *,
struct in_addr, u_int, struct in_addr, u_int, int));
struct inpcb *
in_pcblookuphash __P((struct inpcbinfo *,
struct in_addr, u_int, struct in_addr, u_int));
struct in_addr, u_int, struct in_addr, u_int, int));
void in_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int)));
void in_pcbrehash __P((struct inpcb *));

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
* $Id: tcp_input.c,v 1.51 1996/09/21 06:39:20 pst Exp $
* $Id: tcp_input.c,v 1.52 1996/10/07 04:32:39 pst Exp $
*/
#ifndef TUBA_INCLUDE
@ -357,18 +357,8 @@ tcp_input(m, iphlen)
* Locate pcb for segment.
*/
findpcb:
/*
* First look for an exact match.
*/
inp = in_pcblookuphash(&tcbinfo, ti->ti_src, ti->ti_sport,
ti->ti_dst, ti->ti_dport);
/*
* ...and if that fails, do a wildcard search.
*/
if (inp == NULL) {
inp = in_pcblookup(&tcb, ti->ti_src, ti->ti_sport,
ti->ti_dst, ti->ti_dport, INPLOOKUP_WILDCARD);
}
ti->ti_dst, ti->ti_dport, 1);
/*
* If the state is CLOSED (i.e., TCB does not exist) then

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
* $Id: tcp_input.c,v 1.51 1996/09/21 06:39:20 pst Exp $
* $Id: tcp_input.c,v 1.52 1996/10/07 04:32:39 pst Exp $
*/
#ifndef TUBA_INCLUDE
@ -357,18 +357,8 @@ tcp_input(m, iphlen)
* Locate pcb for segment.
*/
findpcb:
/*
* First look for an exact match.
*/
inp = in_pcblookuphash(&tcbinfo, ti->ti_src, ti->ti_sport,
ti->ti_dst, ti->ti_dport);
/*
* ...and if that fails, do a wildcard search.
*/
if (inp == NULL) {
inp = in_pcblookup(&tcb, ti->ti_src, ti->ti_sport,
ti->ti_dst, ti->ti_dport, INPLOOKUP_WILDCARD);
}
ti->ti_dst, ti->ti_dport, 1);
/*
* If the state is CLOSED (i.e., TCB does not exist) then

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
* $Id: tcp_usrreq.c,v 1.24 1996/07/12 17:28:47 davidg Exp $
* $Id: tcp_usrreq.c,v 1.25 1996/09/13 23:51:44 pst Exp $
*/
#include <sys/param.h>
@ -857,7 +857,7 @@ tcp_connect(tp, nam)
error = in_pcbladdr(inp, nam, &ifaddr);
if (error)
return error;
oinp = in_pcblookup(inp->inp_pcbinfo->listhead,
oinp = in_pcblookuphash(inp->inp_pcbinfo,
sin->sin_addr, sin->sin_port,
inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr
: ifaddr->sin_addr,

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
* $Id: udp_usrreq.c,v 1.27 1996/06/05 17:20:35 wollman Exp $
* $Id: udp_usrreq.c,v 1.28 1996/06/08 08:19:03 bde Exp $
*/
#include <sys/param.h>
@ -268,18 +268,10 @@ udp_input(m, iphlen)
return;
}
/*
* Locate pcb for datagram. First look for an exact match.
* Locate pcb for datagram.
*/
inp = in_pcblookuphash(&udbinfo, ip->ip_src, uh->uh_sport,
ip->ip_dst, uh->uh_dport);
/*
* ...and if that fails, do a wildcard search.
*/
if (inp == NULL) {
udpstat.udpps_pcbhashmiss++;
inp = in_pcblookup(&udb, ip->ip_src, uh->uh_sport, ip->ip_dst,
uh->uh_dport, INPLOOKUP_WILDCARD);
}
ip->ip_dst, uh->uh_dport, 1);
if (inp == NULL) {
if (log_in_vain) {
char buf[4*sizeof "123"];