summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2003-11-04 21:43:17 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2003-11-04 21:43:17 +0000
commit294ba6e1f796fb9da4701923ee467469f6324633 (patch)
treeb3f4ddad2fd73ae44b7f292216c707cfff008521 /sys/netinet
parent81dab3d72aec5ca7f1ab6f8fed0d5683a5a5a986 (diff)
add in(6)_pcblookup_listen() and replace all calls to in_pcblookup()
with either in(6)_pcbhashlookup() or in(6)_pcblookup_listen(); in_pcblookup is now only used by bind(2); speeds up pcb lookup for listening sockets; from Claudio Jeker
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/in_pcb.c121
-rw-r--r--sys/netinet/in_pcb.h7
-rw-r--r--sys/netinet/tcp_input.c11
-rw-r--r--sys/netinet/tcp_subr.c16
-rw-r--r--sys/netinet/tcp_usrreq.c12
-rw-r--r--sys/netinet/udp_usrreq.c24
6 files changed, 150 insertions, 41 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 0ceb29fa4e6..5d8e28ff09c 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.c,v 1.68 2003/10/25 12:15:24 markus Exp $ */
+/* $OpenBSD: in_pcb.c,v 1.69 2003/11/04 21:43:16 markus Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
@@ -955,6 +955,15 @@ in_pcbrehash(inp)
int in_pcbnotifymiss = 0;
#endif
+/*
+ * The in(6)_pcbhashlookup functions are used to locate connected sockets
+ * quickly:
+ * faddr.fport <-> laddr.lport
+ * No wildcard matching is done so that listening sockets are not found.
+ * If the functions return NULL in(6)_pcblookup_listen can be used to
+ * find a listening/bound socket that may accept the connection.
+ * After those two lookups no other are necessary.
+ */
struct inpcb *
in_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg)
struct inpcbtable *table;
@@ -1029,7 +1038,7 @@ in6_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg)
}
#ifdef DIAGNOSTIC
if (inp == NULL && in_pcbnotifymiss) {
- printf("in6_pcblookup_connect: faddr=");
+ printf("in6_pcbhashlookup: faddr=");
printf(" fport=%d laddr=", ntohs(fport));
printf(" lport=%d\n", ntohs(lport));
}
@@ -1038,4 +1047,112 @@ in6_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg)
}
#endif /* INET6 */
+/*
+ * The in(6)_pcblookup_listen functions are used to locate listening
+ * sockets quickly. This are sockets with unspecified foreign address
+ * and port:
+ * *.* <-> laddr.lport
+ * *.* <-> *.lport
+ */
+struct inpcb *
+in_pcblookup_listen(table, laddr, lport_arg)
+ struct inpcbtable *table;
+ struct in_addr laddr;
+ u_int lport_arg;
+{
+ struct inpcbhead *head;
+ register struct inpcb *inp;
+ u_int16_t lport = lport_arg;
+
+ head = INPCBHASH(table, &zeroin_addr, 0, &laddr, lport);
+ LIST_FOREACH(inp, head, inp_hash) {
+#ifdef INET6
+ if (inp->inp_flags & INP_IPV6)
+ continue; /*XXX*/
+#endif
+ if (inp->inp_lport == lport && inp->inp_fport == 0 &&
+ inp->inp_laddr.s_addr == laddr.s_addr &&
+ inp->inp_faddr.s_addr == INADDR_ANY)
+ break;
+ }
+ if (inp == NULL && laddr.s_addr != INADDR_ANY) {
+ head = INPCBHASH(table, &zeroin_addr, 0, &zeroin_addr, lport);
+ LIST_FOREACH(inp, head, inp_hash) {
+#ifdef INET6
+ if (inp->inp_flags & INP_IPV6)
+ continue; /*XXX*/
+#endif
+ if (inp->inp_lport == lport && inp->inp_fport == 0 &&
+ inp->inp_laddr.s_addr == INADDR_ANY &&
+ inp->inp_faddr.s_addr == INADDR_ANY)
+ break;
+ }
+ }
+#ifdef DIAGNOSTIC
+ if (inp == NULL && in_pcbnotifymiss) {
+ printf("in_pcblookup_listen: laddr=%08x lport=%d\n",
+ ntohl(laddr.s_addr), ntohs(lport));
+ }
+#endif
+ /*
+ * 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 != NULL && inp != head->lh_first) {
+ LIST_REMOVE(inp, inp_hash);
+ LIST_INSERT_HEAD(head, inp, inp_hash);
+ }
+ return (inp);
+}
+
+#ifdef INET6
+struct inpcb *
+in6_pcblookup_listen(table, laddr, lport_arg)
+ struct inpcbtable *table;
+ struct in6_addr *laddr;
+ u_int lport_arg;
+{
+ struct inpcbhead *head;
+ register struct inpcb *inp;
+ u_int16_t lport = lport_arg;
+ head = IN6PCBHASH(table, &zeroin6_addr, 0, laddr, lport);
+ LIST_FOREACH(inp, head, inp_hash) {
+ if (!(inp->inp_flags & INP_IPV6))
+ continue;
+ if (inp->inp_lport == lport && inp->inp_fport == 0 &&
+ IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr) &&
+ IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
+ break;
+ }
+ if (inp == NULL && !IN6_IS_ADDR_UNSPECIFIED(laddr)) {
+ head = IN6PCBHASH(table, &zeroin6_addr, 0,
+ &zeroin6_addr, lport);
+ LIST_FOREACH(inp, head, inp_hash) {
+ if (!(inp->inp_flags & INP_IPV6))
+ continue;
+ if (inp->inp_lport == lport && inp->inp_fport == 0 &&
+ IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) &&
+ IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
+ break;
+ }
+ }
+#ifdef DIAGNOSTIC
+ if (inp == NULL && in_pcbnotifymiss) {
+ printf("in6_pcblookup_listen: laddr= lport=%d\n",
+ ntohs(lport));
+ }
+#endif
+ /*
+ * 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 != NULL && inp != head->lh_first) {
+ LIST_REMOVE(inp, inp_hash);
+ LIST_INSERT_HEAD(head, inp, inp_hash);
+ }
+ return (inp);
+}
+#endif /* INET6 */
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index 684c941b634..5f5ec71b589 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.h,v 1.46 2003/10/25 12:15:24 markus Exp $ */
+/* $OpenBSD: in_pcb.h,v 1.47 2003/11/04 21:43:16 markus Exp $ */
/* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */
/*
@@ -238,10 +238,15 @@ void in_pcbdisconnect(void *);
struct inpcb *
in_pcbhashlookup(struct inpcbtable *, struct in_addr,
u_int, struct in_addr, u_int);
+struct inpcb *
+ in_pcblookup_listen(struct inpcbtable *, struct in_addr, u_int);
#ifdef INET6
struct inpcb *
in6_pcbhashlookup(struct inpcbtable *, struct in6_addr *,
u_int, struct in6_addr *, u_int);
+struct inpcb *
+ in6_pcblookup_listen(struct inpcbtable *,
+ struct in6_addr *, u_int);
int in6_pcbbind(struct inpcb *, struct mbuf *);
int in6_pcbconnect(struct inpcb *, struct mbuf *);
int in6_setsockaddr(struct inpcb *, struct mbuf *);
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 5ceeb6ccc9b..a786851a75a 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.133 2003/10/01 21:41:05 itojun Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.134 2003/11/04 21:43:16 markus Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -670,14 +670,13 @@ findpcb:
switch (af) {
#ifdef INET6
case AF_INET6:
- inp = in_pcblookup(&tcbtable, &ip6->ip6_src,
- th->th_sport, &ip6->ip6_dst, th->th_dport,
- INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
+ inp = in6_pcblookup_listen(&tcbtable,
+ &ip6->ip6_dst, th->th_dport);
break;
#endif /* INET6 */
case AF_INET:
- inp = in_pcblookup(&tcbtable, &ip->ip_src, th->th_sport,
- &ip->ip_dst, th->th_dport, INPLOOKUP_WILDCARD);
+ inp = in_pcblookup_listen(&tcbtable,
+ ip->ip_dst, th->th_dport);
break;
}
/*
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index e5ecf5c0ee2..e2110b8b23a 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_subr.c,v 1.69 2003/10/01 21:41:05 itojun Exp $ */
+/* $OpenBSD: tcp_subr.c,v 1.70 2003/11/04 21:43:16 markus Exp $ */
/* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
/*
@@ -839,10 +839,6 @@ tcp6_ctlinput(cmd, sa, d)
th.th_dport, (struct in6_addr *)&sa6_src->sin6_addr,
th.th_sport))
valid++;
- else if (in_pcblookup(&tcbtable, &sa6->sin6_addr,
- th.th_dport, (struct in6_addr *)&sa6_src->sin6_addr,
- th.th_sport, INPLOOKUP_IPV6))
- valid++;
/*
* Depending on the value of "valid" and routing table
@@ -893,10 +889,12 @@ tcp_ctlinput(cmd, sa, v)
* Verify that the packet in the icmp payload refers
* to an existing TCP connection.
*/
- if (in_pcblookup(&tcbtable,
- &ip->ip_dst, th->th_dport,
- &ip->ip_src, th->th_sport,
- INPLOOKUP_WILDCARD)) {
+ /*
+ * XXX is it possible to get a valid PRC_MSGSIZE error for
+ * a non-established connection?
+ */
+ if (in_pcbhashlookup(&tcbtable,
+ ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport)) {
struct icmp *icp;
icp = (struct icmp *)((caddr_t)ip -
offsetof(struct icmp, icmp_ip));
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 501efc21a7b..ff9983289b7 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_usrreq.c,v 1.71 2003/06/09 07:40:25 itojun Exp $ */
+/* $OpenBSD: tcp_usrreq.c,v 1.72 2003/11/04 21:43:16 markus Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
/*
@@ -834,15 +834,13 @@ tcp_ident(oldp, oldlenp, newp, newlen)
switch (tir.faddr.ss_family) {
#ifdef INET6
case AF_INET6:
- inp = in_pcblookup(&tcbtable, &f6,
- fin6->sin6_port, &l6, lin6->sin6_port,
- INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
+ inp = in6_pcblookup_listen(&tcbtable,
+ &l6, lin6->sin6_port);
break;
#endif
case AF_INET:
- inp = in_pcblookup(&tcbtable, &fin->sin_addr,
- fin->sin_port, &lin->sin_addr, lin->sin_port,
- INPLOOKUP_WILDCARD);
+ inp = in_pcblookup_listen(&tcbtable,
+ lin->sin_addr, lin->sin_port);
break;
}
}
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 9e5842d6087..6a36106dafc 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_usrreq.c,v 1.91 2003/07/09 22:03:16 itojun Exp $ */
+/* $OpenBSD: udp_usrreq.c,v 1.92 2003/11/04 21:43:16 markus Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
/*
@@ -483,14 +483,12 @@ udp_input(struct mbuf *m, ...)
++udpstat.udps_pcbhashmiss;
#ifdef INET6
if (ip6) {
- inp = in_pcblookup(&udbtable,
- (struct in_addr *)&(ip6->ip6_src),
- uh->uh_sport, (struct in_addr *)&(ip6->ip6_dst),
- uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
+ inp = in6_pcblookup_listen(&udbtable,
+ &ip6->ip6_dst, uh->uh_dport);
} else
#endif /* INET6 */
- inp = in_pcblookup(&udbtable, &ip->ip_src, uh->uh_sport,
- &ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD);
+ inp = in_pcblookup_listen(&udbtable,
+ ip->ip_dst, uh->uh_dport);
if (inp == 0) {
udpstat.udps_noport++;
if (m->m_flags & (M_BCAST | M_MCAST)) {
@@ -665,7 +663,6 @@ udp6_ctlinput(cmd, sa, d)
int off;
void *cmdarg;
struct ip6ctlparam *ip6cp = NULL;
- struct in6_addr finaldst;
struct udp_portonly {
u_int16_t uh_sport;
u_int16_t uh_dport;
@@ -770,13 +767,9 @@ udp6_ctlinput(cmd, sa, d)
* corresponding to the address in the ICMPv6 message
* payload.
*/
- if (in6_pcbhashlookup(&udbtable, &finaldst,
+ if (in6_pcbhashlookup(&udbtable, &sa6.sin6_addr,
uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport))
valid = 1;
- else if (in_pcblookup(&udbtable, &sa6.sin6_addr,
- uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport,
- INPLOOKUP_IPV6))
- valid = 1;
#if 0
/*
* As the use of sendto(2) is fairly popular,
@@ -785,9 +778,8 @@ udp6_ctlinput(cmd, sa, d)
* We should at least check if the local address (= s)
* is really ours.
*/
- else if (in_pcblookup(&udbtable, &sa6.sin6_addr,
- uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport,
- INPLOOKUP_WILDCARD | INPLOOKUP_IPV6))
+ else if (in6_pcblookup_listen(&udbtable,
+ &sa6_src.sin6_addr, uh.uh_sport))
valid = 1;
#endif