From: bluhm Date: Tue, 30 Aug 2022 11:53:03 +0000 (+0000) Subject: Refactor internet PCB lookup function. Rename in_pcbhashlookup() X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=a6b8fd29c9fca9cf5e0c486549ff4cfaed27a25e;p=openbsd Refactor internet PCB lookup function. Rename in_pcbhashlookup() so the public API is in_pcblookup() and in_pcblookup_listen(). For internal use introduce in_pcbhash_insert() and in_pcbhash_lookup() to avoid code duplication. Routing domain is unsigned, change the type to u_int. OK mvs@ --- diff --git a/sys/net/pf.c b/sys/net/pf.c index f23968f07c7..81a53fed2b0 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.1137 2022/08/08 12:06:30 bluhm Exp $ */ +/* $OpenBSD: pf.c,v 1.1138 2022/08/30 11:53:03 bluhm Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -3348,7 +3348,7 @@ pf_socket_lookup(struct pf_pdesc *pd) * Fails when rtable is changed while evaluating the ruleset * The socket looked up will not match the one hit in the end. */ - inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport, + inp = in_pcblookup(tb, saddr->v4, sport, daddr->v4, dport, pd->rdomain); if (inp == NULL) { inp = in_pcblookup_listen(tb, daddr->v4, dport, @@ -3359,7 +3359,7 @@ pf_socket_lookup(struct pf_pdesc *pd) break; #ifdef INET6 case AF_INET6: - inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6, + inp = in6_pcblookup(tb, &saddr->v6, sport, &daddr->v6, dport, pd->rdomain); if (inp == NULL) { inp = in6_pcblookup_listen(tb, &daddr->v6, dport, diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index d145fb69c36..b326f3f14df 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.272 2022/08/22 10:37:27 bluhm Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.273 2022/08/30 11:53:04 bluhm Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -120,14 +120,16 @@ struct baddynamicports baddynamicports; struct baddynamicports rootonlyports; struct pool inpcb_pool; -void in_pcbrehash_locked(struct inpcb *); +void in_pcbhash_insert(struct inpcb *); +struct inpcb *in_pcbhash_lookup(struct inpcbtable *, u_int, + const struct in_addr *, u_short, const struct in_addr *, u_short); int in_pcbresize(struct inpcbtable *, int); #define INPCBHASH_LOADFACTOR(_x) (((_x) * 3) / 4) -struct inpcbhead *in_pcbhash(struct inpcbtable *, int, +struct inpcbhead *in_pcbhash(struct inpcbtable *, u_int, const struct in_addr *, u_short, const struct in_addr *, u_short); -struct inpcbhead *in_pcblhash(struct inpcbtable *, int, u_short); +struct inpcbhead *in_pcblhash(struct inpcbtable *, u_int, u_short); /* * in_pcb is used for inet and inet6. in6_pcb only contains special @@ -141,12 +143,12 @@ in_init(void) } struct inpcbhead * -in_pcbhash(struct inpcbtable *table, int rdom, +in_pcbhash(struct inpcbtable *table, u_int rdomain, const struct in_addr *faddr, u_short fport, const struct in_addr *laddr, u_short lport) { SIPHASH_CTX ctx; - u_int32_t nrdom = htonl(rdom); + u_int32_t nrdom = htonl(rdomain); SipHash24_Init(&ctx, &table->inpt_key); SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); @@ -159,10 +161,10 @@ in_pcbhash(struct inpcbtable *table, int rdom, } struct inpcbhead * -in_pcblhash(struct inpcbtable *table, int rdom, u_short lport) +in_pcblhash(struct inpcbtable *table, u_int rdomain, u_short lport) { SIPHASH_CTX ctx; - u_int32_t nrdom = htonl(rdom); + u_int32_t nrdom = htonl(rdomain); SipHash24_Init(&ctx, &table->inpt_lkey); SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); @@ -227,9 +229,6 @@ int in_pcballoc(struct socket *so, struct inpcbtable *table) { struct inpcb *inp; - struct inpcbhead *head; - - NET_ASSERT_LOCKED(); inp = pool_get(&inpcb_pool, PR_NOWAIT|PR_ZERO); if (inp == NULL) @@ -259,19 +258,7 @@ in_pcballoc(struct socket *so, struct inpcbtable *table) if (table->inpt_count++ > INPCBHASH_LOADFACTOR(table->inpt_size)) (void)in_pcbresize(table, table->inpt_size * 2); TAILQ_INSERT_HEAD(&table->inpt_queue, inp, inp_queue); - head = in_pcblhash(table, inp->inp_rtableid, inp->inp_lport); - LIST_INSERT_HEAD(head, inp, inp_lhash); -#ifdef INET6 - if (sotopf(so) == PF_INET6) - head = in6_pcbhash(table, rtable_l2(inp->inp_rtableid), - &inp->inp_faddr6, inp->inp_fport, - &inp->inp_laddr6, inp->inp_lport); - else -#endif /* INET6 */ - head = in_pcbhash(table, rtable_l2(inp->inp_rtableid), - &inp->inp_faddr, inp->inp_fport, - &inp->inp_laddr, inp->inp_lport); - LIST_INSERT_HEAD(head, inp, inp_hash); + in_pcbhash_insert(inp); mtx_leave(&table->inpt_mtx); so->so_pcb = inp; @@ -513,7 +500,7 @@ in_pcbconnect(struct inpcb *inp, struct mbuf *nam) if (error) return (error); - t = in_pcbhashlookup(inp->inp_table, sin->sin_addr, sin->sin_port, + t = in_pcblookup(inp->inp_table, sin->sin_addr, sin->sin_port, ina, inp->inp_lport, inp->inp_rtableid); if (t != NULL) { in_pcbunref(t); @@ -527,7 +514,7 @@ in_pcbconnect(struct inpcb *inp, struct mbuf *nam) error = in_pcbbind(inp, NULL, curproc); if (error) return (error); - t = in_pcbhashlookup(inp->inp_table, sin->sin_addr, + t = in_pcblookup(inp->inp_table, sin->sin_addr, sin->sin_port, ina, inp->inp_lport, inp->inp_rtableid); if (t != NULL) { @@ -582,8 +569,6 @@ in_pcbdetach(struct inpcb *inp) struct socket *so = inp->inp_socket; struct inpcbtable *table = inp->inp_table; - NET_ASSERT_LOCKED(); - so->so_pcb = NULL; /* * As long as the NET_LOCK() is the default lock for Internet @@ -1037,12 +1022,14 @@ in_pcbrehash(struct inpcb *inp) struct inpcbtable *table = inp->inp_table; mtx_enter(&table->inpt_mtx); - in_pcbrehash_locked(inp); + LIST_REMOVE(inp, inp_lhash); + LIST_REMOVE(inp, inp_hash); + in_pcbhash_insert(inp); mtx_leave(&table->inpt_mtx); } void -in_pcbrehash_locked(struct inpcb *inp) +in_pcbhash_insert(struct inpcb *inp) { struct inpcbtable *table = inp->inp_table; struct inpcbhead *head; @@ -1050,10 +1037,8 @@ in_pcbrehash_locked(struct inpcb *inp) NET_ASSERT_LOCKED(); MUTEX_ASSERT_LOCKED(&table->inpt_mtx); - LIST_REMOVE(inp, inp_lhash); head = in_pcblhash(table, inp->inp_rtableid, inp->inp_lport); LIST_INSERT_HEAD(head, inp, inp_lhash); - LIST_REMOVE(inp, inp_hash); #ifdef INET6 if (inp->inp_flags & INP_IPV6) head = in6_pcbhash(table, rtable_l2(inp->inp_rtableid), @@ -1067,6 +1052,44 @@ in_pcbrehash_locked(struct inpcb *inp) LIST_INSERT_HEAD(head, inp, inp_hash); } +struct inpcb * +in_pcbhash_lookup(struct inpcbtable *table, u_int rdomain, + const struct in_addr *faddr, u_short fport, + const struct in_addr *laddr, u_short lport) +{ + struct inpcbhead *head; + struct inpcb *inp; + + NET_ASSERT_LOCKED(); + MUTEX_ASSERT_LOCKED(&table->inpt_mtx); + + head = in_pcbhash(table, rdomain, faddr, fport, laddr, lport); + LIST_FOREACH(inp, head, inp_hash) { +#ifdef INET6 + if (ISSET(inp->inp_flags, INP_IPV6)) + continue; +#endif + if (inp->inp_fport == fport && inp->inp_lport == lport && + inp->inp_faddr.s_addr == faddr->s_addr && + inp->inp_laddr.s_addr == laddr->s_addr && + rtable_l2(inp->inp_rtableid) == rdomain) { + break; + } + } + if (inp != NULL) { + /* + * 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 != LIST_FIRST(head)) { + LIST_REMOVE(inp, inp_hash); + LIST_INSERT_HEAD(head, inp, inp_hash); + } + } + return (inp); +} + int in_pcbresize(struct inpcbtable *table, int hashsize) { @@ -1098,7 +1121,9 @@ in_pcbresize(struct inpcbtable *table, int hashsize) arc4random_buf(&table->inpt_lkey, sizeof(table->inpt_lkey)); TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) { - in_pcbrehash_locked(inp); + LIST_REMOVE(inp, inp_lhash); + LIST_REMOVE(inp, inp_hash); + in_pcbhash_insert(inp); } hashfree(ohashtbl, osize, M_PCB); hashfree(olhashtbl, osize, M_PCB); @@ -1111,7 +1136,7 @@ int in_pcbnotifymiss = 0; #endif /* - * The in(6)_pcbhashlookup functions are used to locate connected sockets + * The in(6)_pcblookup functions are used to locate connected sockets * quickly: * faddr.fport <-> laddr.lport * No wildcard matching is done so that listening sockets are not found. @@ -1120,38 +1145,15 @@ int in_pcbnotifymiss = 0; * After those two lookups no other are necessary. */ struct inpcb * -in_pcbhashlookup(struct inpcbtable *table, struct in_addr faddr, - u_int fport_arg, struct in_addr laddr, u_int lport_arg, u_int rtable) +in_pcblookup(struct inpcbtable *table, struct in_addr faddr, + u_int fport, struct in_addr laddr, u_int lport, u_int rtable) { - struct inpcbhead *head; struct inpcb *inp; - u_int16_t fport = fport_arg, lport = lport_arg; u_int rdomain; rdomain = rtable_l2(rtable); mtx_enter(&table->inpt_mtx); - head = in_pcbhash(table, rdomain, &faddr, fport, &laddr, lport); - LIST_FOREACH(inp, head, inp_hash) { -#ifdef INET6 - if (inp->inp_flags & INP_IPV6) - continue; /*XXX*/ -#endif - 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 && - rtable_l2(inp->inp_rtableid) == rdomain) { - /* - * 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 != LIST_FIRST(head)) { - LIST_REMOVE(inp, inp_hash); - LIST_INSERT_HEAD(head, inp, inp_hash); - } - break; - } - } + inp = in_pcbhash_lookup(table, rdomain, &faddr, fport, &laddr, lport); in_pcbref(inp); mtx_leave(&table->inpt_mtx); #ifdef DIAGNOSTIC @@ -1175,7 +1177,6 @@ struct inpcb * in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr, u_int lport_arg, struct mbuf *m, u_int rtable) { - struct inpcbhead *head; const struct in_addr *key1, *key2; struct inpcb *inp; u_int16_t lport = lport_arg; @@ -1216,41 +1217,10 @@ in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr, rdomain = rtable_l2(rtable); mtx_enter(&table->inpt_mtx); - head = in_pcbhash(table, rdomain, &zeroin_addr, 0, key1, 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 == key1->s_addr && - inp->inp_faddr.s_addr == INADDR_ANY && - rtable_l2(inp->inp_rtableid) == rdomain) - break; - } + inp = in_pcbhash_lookup(table, rdomain, &zeroin_addr, 0, key1, lport); if (inp == NULL && key1->s_addr != key2->s_addr) { - head = in_pcbhash(table, rdomain, + inp = in_pcbhash_lookup(table, rdomain, &zeroin_addr, 0, key2, 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 == key2->s_addr && - inp->inp_faddr.s_addr == INADDR_ANY && - rtable_l2(inp->inp_rtableid) == rdomain) - break; - } - } - /* - * 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 != LIST_FIRST(head)) { - LIST_REMOVE(inp, inp_hash); - LIST_INSERT_HEAD(head, inp, inp_hash); } in_pcbref(inp); mtx_leave(&table->inpt_mtx); diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index cc262a292b0..4726009ac25 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.h,v 1.131 2022/08/22 10:37:27 bluhm Exp $ */ +/* $OpenBSD: in_pcb.h,v 1.132 2022/08/30 11:53:04 bluhm Exp $ */ /* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */ /* @@ -288,17 +288,17 @@ struct inpcb * void in_pcbunref(struct inpcb *); void in_pcbdisconnect(struct inpcb *); struct inpcb * - in_pcbhashlookup(struct inpcbtable *, struct in_addr, + in_pcblookup(struct inpcbtable *, struct in_addr, u_int, struct in_addr, u_int, u_int); struct inpcb * in_pcblookup_listen(struct inpcbtable *, struct in_addr, u_int, struct mbuf *, u_int); #ifdef INET6 struct inpcbhead * - in6_pcbhash(struct inpcbtable *, int, const struct in6_addr *, + in6_pcbhash(struct inpcbtable *, u_int, const struct in6_addr *, u_short, const struct in6_addr *, u_short); struct inpcb * - in6_pcbhashlookup(struct inpcbtable *, const struct in6_addr *, + in6_pcblookup(struct inpcbtable *, const struct in6_addr *, u_int, const struct in6_addr *, u_int, u_int); struct inpcb * in6_pcblookup_listen(struct inpcbtable *, struct in6_addr *, u_int, diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index a6c59623c38..59ef806c645 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.378 2022/08/21 16:22:17 mvs Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.379 2022/08/30 11:53:04 bluhm Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -531,13 +531,13 @@ findpcb: switch (af) { #ifdef INET6 case AF_INET6: - inp = in6_pcbhashlookup(&tcbtable, &ip6->ip6_src, + inp = in6_pcblookup(&tcbtable, &ip6->ip6_src, th->th_sport, &ip6->ip6_dst, th->th_dport, m->m_pkthdr.ph_rtableid); break; #endif case AF_INET: - inp = in_pcbhashlookup(&tcbtable, ip->ip_src, + inp = in_pcblookup(&tcbtable, ip->ip_src, th->th_sport, ip->ip_dst, th->th_dport, m->m_pkthdr.ph_rtableid); break; diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index b7d5eb22dec..53be81074b0 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_subr.c,v 1.185 2022/08/08 12:06:30 bluhm Exp $ */ +/* $OpenBSD: tcp_subr.c,v 1.186 2022/08/30 11:53:04 bluhm Exp $ */ /* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */ /* @@ -661,7 +661,7 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d) * corresponding to the address in the ICMPv6 message * payload. */ - inp = in6_pcbhashlookup(&tcbtable, &sa6->sin6_addr, + inp = in6_pcblookup(&tcbtable, &sa6->sin6_addr, th.th_dport, &sa6_src->sin6_addr, th.th_sport, rdomain); if (cmd == PRC_MSGSIZE) { /* @@ -733,7 +733,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) */ th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); seq = ntohl(th->th_seq); - inp = in_pcbhashlookup(&tcbtable, + inp = in_pcblookup(&tcbtable, ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport, rdomain); if (inp && (tp = intotcpcb(inp)) && @@ -798,7 +798,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) if (ip) { th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); - inp = in_pcbhashlookup(&tcbtable, + inp = in_pcblookup(&tcbtable, ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport, rdomain); if (inp) { diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 44722fd86c5..539c08653a1 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.200 2022/08/29 09:50:38 mbuhl Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.201 2022/08/30 11:53:04 bluhm Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -1156,12 +1156,12 @@ tcp_ident(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int dodrop) switch (tir.faddr.ss_family) { #ifdef INET6 case AF_INET6: - inp = in6_pcbhashlookup(&tcbtable, &f6, + inp = in6_pcblookup(&tcbtable, &f6, fin6->sin6_port, &l6, lin6->sin6_port, tir.rdomain); break; #endif case AF_INET: - inp = in_pcbhashlookup(&tcbtable, fin->sin_addr, + inp = in_pcblookup(&tcbtable, fin->sin_addr, fin->sin_port, lin->sin_addr, lin->sin_port, tir.rdomain); break; default: diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index ea39aaa96f6..938df27724c 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.295 2022/08/30 09:35:24 bluhm Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.296 2022/08/30 11:53:04 bluhm Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -488,12 +488,12 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af) if (inp == NULL) { #ifdef INET6 if (ip6) - inp = in6_pcbhashlookup(&udbtable, &ip6->ip6_src, + inp = in6_pcblookup(&udbtable, &ip6->ip6_src, uh->uh_sport, &ip6->ip6_dst, uh->uh_dport, m->m_pkthdr.ph_rtableid); else #endif /* INET6 */ - inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport, + inp = in_pcblookup(&udbtable, ip->ip_src, uh->uh_sport, ip->ip_dst, uh->uh_dport, m->m_pkthdr.ph_rtableid); } if (inp == NULL) { @@ -789,7 +789,7 @@ udp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d) * corresponding to the address in the ICMPv6 message * payload. */ - inp = in6_pcbhashlookup(&udbtable, &sa6.sin6_addr, + inp = in6_pcblookup(&udbtable, &sa6.sin6_addr, uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport, rdomain); #if 0 @@ -875,7 +875,7 @@ udp_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) return; } #endif - inp = in_pcbhashlookup(&udbtable, + inp = in_pcblookup(&udbtable, ip->ip_dst, uhp->uh_dport, ip->ip_src, uhp->uh_sport, rdomain); if (inp && inp->inp_socket != NULL) diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 471a9614fea..8825c7ffa5b 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_pcb.c,v 1.120 2022/08/22 10:37:27 bluhm Exp $ */ +/* $OpenBSD: in6_pcb.c,v 1.121 2022/08/30 11:53:04 bluhm Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -126,13 +126,16 @@ const struct in6_addr zeroin6_addr; +struct inpcb *in6_pcbhash_lookup(struct inpcbtable *, u_int, + const struct in6_addr *, u_short, const struct in6_addr *, u_short); + struct inpcbhead * -in6_pcbhash(struct inpcbtable *table, int rdom, +in6_pcbhash(struct inpcbtable *table, u_int rdomain, const struct in6_addr *faddr, u_short fport, const struct in6_addr *laddr, u_short lport) { SIPHASH_CTX ctx; - u_int32_t nrdom = htonl(rdom); + u_int32_t nrdom = htonl(rdomain); SipHash24_Init(&ctx, &table->inpt_key); SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); @@ -280,7 +283,7 @@ in6_pcbconnect(struct inpcb *inp, struct mbuf *nam) inp->inp_ipv6.ip6_hlim = (u_int8_t)in6_selecthlim(inp); - t = in6_pcbhashlookup(inp->inp_table, &sin6->sin6_addr, sin6->sin6_port, + t = in6_pcblookup(inp->inp_table, &sin6->sin6_addr, sin6->sin6_port, IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) ? in6a : &inp->inp_laddr6, inp->inp_lport, inp->inp_rtableid); if (t != NULL) { @@ -295,7 +298,7 @@ in6_pcbconnect(struct inpcb *inp, struct mbuf *nam) error = in_pcbbind(inp, NULL, curproc); if (error) return (error); - t = in6_pcbhashlookup(inp->inp_table, &sin6->sin6_addr, + t = in6_pcblookup(inp->inp_table, &sin6->sin6_addr, sin6->sin6_port, in6a, inp->inp_lport, inp->inp_rtableid); if (t != NULL) { @@ -516,37 +519,51 @@ in6_pcbnotify(struct inpcbtable *table, struct sockaddr_in6 *dst, } struct inpcb * -in6_pcbhashlookup(struct inpcbtable *table, const struct in6_addr *faddr, - u_int fport_arg, const struct in6_addr *laddr, u_int lport_arg, - u_int rtable) +in6_pcbhash_lookup(struct inpcbtable *table, u_int rdomain, + const struct in6_addr *faddr, u_short fport, + const struct in6_addr *laddr, u_short lport) { struct inpcbhead *head; struct inpcb *inp; - u_int16_t fport = fport_arg, lport = lport_arg; - u_int rdomain; - rdomain = rtable_l2(rtable); - mtx_enter(&table->inpt_mtx); + NET_ASSERT_LOCKED(); + MUTEX_ASSERT_LOCKED(&table->inpt_mtx); + head = in6_pcbhash(table, rdomain, faddr, fport, laddr, lport); LIST_FOREACH(inp, head, inp_hash) { - if (!(inp->inp_flags & INP_IPV6)) + if (!ISSET(inp->inp_flags, INP_IPV6)) continue; - if (IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, faddr) && - inp->inp_fport == fport && inp->inp_lport == lport && + if (inp->inp_fport == fport && inp->inp_lport == lport && + IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, faddr) && IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr) && rtable_l2(inp->inp_rtableid) == rdomain) { - /* - * 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 != LIST_FIRST(head)) { - LIST_REMOVE(inp, inp_hash); - LIST_INSERT_HEAD(head, inp, inp_hash); - } break; } } + if (inp != NULL) { + /* + * 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 != LIST_FIRST(head)) { + LIST_REMOVE(inp, inp_hash); + LIST_INSERT_HEAD(head, inp, inp_hash); + } + } + return (inp); +} + +struct inpcb * +in6_pcblookup(struct inpcbtable *table, const struct in6_addr *faddr, + u_int fport, const struct in6_addr *laddr, u_int lport, u_int rtable) +{ + struct inpcb *inp; + u_int rdomain; + + rdomain = rtable_l2(rtable); + mtx_enter(&table->inpt_mtx); + inp = in6_pcbhash_lookup(table, rdomain, faddr, fport, laddr, lport); in_pcbref(inp); mtx_leave(&table->inpt_mtx); #ifdef DIAGNOSTIC @@ -560,12 +577,10 @@ in6_pcbhashlookup(struct inpcbtable *table, const struct in6_addr *faddr, struct inpcb * in6_pcblookup_listen(struct inpcbtable *table, struct in6_addr *laddr, - u_int lport_arg, struct mbuf *m, u_int rtable) + u_int lport, struct mbuf *m, u_int rtable) { - struct inpcbhead *head; const struct in6_addr *key1, *key2; struct inpcb *inp; - u_int16_t lport = lport_arg; u_int rdomain; key1 = laddr; @@ -600,37 +615,10 @@ in6_pcblookup_listen(struct inpcbtable *table, struct in6_addr *laddr, rdomain = rtable_l2(rtable); mtx_enter(&table->inpt_mtx); - head = in6_pcbhash(table, rdomain, &zeroin6_addr, 0, key1, 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, key1) && - IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6) && - rtable_l2(inp->inp_rtableid) == rdomain) - break; - } + inp = in6_pcbhash_lookup(table, rdomain, &zeroin6_addr, 0, key1, lport); if (inp == NULL && ! IN6_ARE_ADDR_EQUAL(key1, key2)) { - head = in6_pcbhash(table, rdomain, + inp = in6_pcbhash_lookup(table, rdomain, &zeroin6_addr, 0, key2, 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, key2) && - IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6) && - rtable_l2(inp->inp_rtableid) == rdomain) - break; - } - } - /* - * 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 != LIST_FIRST(head)) { - LIST_REMOVE(inp, inp_hash); - LIST_INSERT_HEAD(head, inp, inp_hash); } in_pcbref(inp); mtx_leave(&table->inpt_mtx); diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 00fe9192d44..bd50d72cf2a 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip6.c,v 1.162 2022/08/29 08:08:17 mvs Exp $ */ +/* $OpenBSD: raw_ip6.c,v 1.163 2022/08/30 11:53:04 bluhm Exp $ */ /* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */ /* @@ -331,7 +331,7 @@ rip6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d) * XXX chase extension headers, or pass final nxt value * from icmp6_notify_error() */ - in6p = in6_pcbhashlookup(&rawin6pcbtable, &sa6->sin6_addr, 0, + in6p = in6_pcblookup(&rawin6pcbtable, &sa6->sin6_addr, 0, &sa6_src->sin6_addr, 0, rdomain); if (in6p && in6p->inp_ipv6.ip6_nxt &&