mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-04 01:38:57 +00:00
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:
parent
545c48b83a
commit
6d6a026b47
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=18795
@ -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);
|
||||
|
@ -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 *));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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"];
|
||||
|
Loading…
Reference in New Issue
Block a user