Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/in6_pcb.c
Show First 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | |||||
#include <netinet6/ip6_var.h> | #include <netinet6/ip6_var.h> | ||||
#include <netinet6/nd6.h> | #include <netinet6/nd6.h> | ||||
#include <netinet/in_pcb.h> | #include <netinet/in_pcb.h> | ||||
#include <netinet6/in6_pcb.h> | #include <netinet6/in6_pcb.h> | ||||
#include <netinet6/scope6_var.h> | #include <netinet6/scope6_var.h> | ||||
static struct inpcb *in6_pcblookup_hash_locked(struct inpcbinfo *, | static struct inpcb *in6_pcblookup_hash_locked(struct inpcbinfo *, | ||||
struct in6_addr *, u_int, struct in6_addr *, u_int, int, struct ifnet *); | struct in6_addr *, u_int, struct in6_addr *, u_int, int, struct ifnet *, int); | ||||
int | int | ||||
in6_pcbbind(struct inpcb *inp, struct sockaddr *nam, | in6_pcbbind(struct inpcb *inp, struct sockaddr *nam, | ||||
struct ucred *cred) | struct ucred *cred) | ||||
{ | { | ||||
struct socket *so = inp->inp_socket; | struct socket *so = inp->inp_socket; | ||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL; | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL; | ||||
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; | struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; | ||||
▲ Show 20 Lines • Show All 303 Lines • ▼ Show 20 Lines | in6_pcbconnect_mbuf(struct inpcb *inp, struct sockaddr *nam, | ||||
*/ | */ | ||||
if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0) | if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0) | ||||
return (error); | return (error); | ||||
if (in6_pcblookup_hash_locked(pcbinfo, &sin6->sin6_addr, | if (in6_pcblookup_hash_locked(pcbinfo, &sin6->sin6_addr, | ||||
sin6->sin6_port, | sin6->sin6_port, | ||||
IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) | IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) | ||||
? &addr6 : &inp->in6p_laddr, | ? &addr6 : &inp->in6p_laddr, | ||||
inp->inp_lport, 0, NULL) != NULL) { | inp->inp_lport, 0, NULL, M_NODOM) != NULL) { | ||||
return (EADDRINUSE); | return (EADDRINUSE); | ||||
} | } | ||||
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { | if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { | ||||
if (inp->inp_lport == 0) { | if (inp->inp_lport == 0) { | ||||
error = in6_pcbbind(inp, (struct sockaddr *)0, cred); | error = in6_pcbbind(inp, (struct sockaddr *)0, cred); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 422 Lines • ▼ Show 20 Lines | in6_rtchange(struct inpcb *inp, int errno __unused) | ||||
RO_INVALIDATE_CACHE(&inp->inp_route6); | RO_INVALIDATE_CACHE(&inp->inp_route6); | ||||
return inp; | return inp; | ||||
} | } | ||||
static struct inpcb * | static struct inpcb * | ||||
in6_pcblookup_lbgroup(const struct inpcbinfo *pcbinfo, | in6_pcblookup_lbgroup(const struct inpcbinfo *pcbinfo, | ||||
const struct in6_addr *laddr, uint16_t lport, const struct in6_addr *faddr, | const struct in6_addr *laddr, uint16_t lport, const struct in6_addr *faddr, | ||||
uint16_t fport, int lookupflags) | uint16_t fport, int lookupflags, int numa_domain) | ||||
{ | { | ||||
struct inpcb *local_wild; | struct inpcb *local_wild, *numa_wild; | ||||
const struct inpcblbgrouphead *hdr; | const struct inpcblbgrouphead *hdr; | ||||
struct inpcblbgroup *grp; | struct inpcblbgroup *grp; | ||||
uint32_t idx; | uint32_t idx; | ||||
INP_HASH_LOCK_ASSERT(pcbinfo); | INP_HASH_LOCK_ASSERT(pcbinfo); | ||||
hdr = &pcbinfo->ipi_lbgrouphashbase[ | hdr = &pcbinfo->ipi_lbgrouphashbase[ | ||||
INP_PCBPORTHASH(lport, pcbinfo->ipi_lbgrouphashmask)]; | INP_PCBPORTHASH(lport, pcbinfo->ipi_lbgrouphashmask)]; | ||||
/* | /* | ||||
* Order of socket selection: | * Order of socket selection: | ||||
* 1. non-wild. | * 1. non-wild. | ||||
* 2. wild (if lookupflags contains INPLOOKUP_WILDCARD). | * 2. wild (if lookupflags contains INPLOOKUP_WILDCARD). | ||||
* | * | ||||
* NOTE: | * NOTE: | ||||
* - Load balanced group does not contain jailed sockets. | * - Load balanced group does not contain jailed sockets. | ||||
* - Load balanced does not contain IPv4 mapped INET6 wild sockets. | * - Load balanced does not contain IPv4 mapped INET6 wild sockets. | ||||
*/ | */ | ||||
local_wild = NULL; | local_wild = NULL; | ||||
numa_wild = NULL; | |||||
CK_LIST_FOREACH(grp, hdr, il_list) { | CK_LIST_FOREACH(grp, hdr, il_list) { | ||||
#ifdef INET | #ifdef INET | ||||
if (!(grp->il_vflag & INP_IPV6)) | if (!(grp->il_vflag & INP_IPV6)) | ||||
continue; | continue; | ||||
#endif | #endif | ||||
if (grp->il_lport != lport) | if (grp->il_lport != lport) | ||||
continue; | continue; | ||||
idx = INP_PCBLBGROUP_PKTHASH(INP6_PCBHASHKEY(faddr), lport, | idx = INP_PCBLBGROUP_PKTHASH(INP6_PCBHASHKEY(faddr), lport, | ||||
fport) % grp->il_inpcnt; | fport) % grp->il_inpcnt; | ||||
if (IN6_ARE_ADDR_EQUAL(&grp->il6_laddr, laddr)) | if (IN6_ARE_ADDR_EQUAL(&grp->il6_laddr, laddr)) { | ||||
if (numa_domain == M_NODOM || | |||||
grp->il_numa_domain == numa_domain) { | |||||
return (grp->il_inp[idx]); | return (grp->il_inp[idx]); | ||||
} | |||||
else | |||||
numa_wild = grp->il_inp[idx]; | |||||
} | |||||
if (IN6_IS_ADDR_UNSPECIFIED(&grp->il6_laddr) && | if (IN6_IS_ADDR_UNSPECIFIED(&grp->il6_laddr) && | ||||
(lookupflags & INPLOOKUP_WILDCARD) != 0) | (lookupflags & INPLOOKUP_WILDCARD) != 0) { | ||||
if (local_wild == NULL || numa_domain == M_NODOM) | |||||
local_wild = grp->il_inp[idx]; | local_wild = grp->il_inp[idx]; | ||||
if (grp->il_numa_domain == numa_domain) | |||||
local_wild = grp->il_inp[idx]; | |||||
bz: See netinet comment. | |||||
} | } | ||||
} | |||||
if (numa_wild != NULL) | |||||
return (numa_wild); | |||||
return (local_wild); | return (local_wild); | ||||
} | } | ||||
#ifdef PCBGROUP | #ifdef PCBGROUP | ||||
/* | /* | ||||
* Lookup PCB in hash list, using pcbgroup tables. | * Lookup PCB in hash list, using pcbgroup tables. | ||||
*/ | */ | ||||
static struct inpcb * | static struct inpcb * | ||||
▲ Show 20 Lines • Show All 194 Lines • ▼ Show 20 Lines | |||||
#endif /* PCBGROUP */ | #endif /* PCBGROUP */ | ||||
/* | /* | ||||
* Lookup PCB in hash list. | * Lookup PCB in hash list. | ||||
*/ | */ | ||||
static struct inpcb * | static struct inpcb * | ||||
in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, | in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, | ||||
u_int fport_arg, struct in6_addr *laddr, u_int lport_arg, | u_int fport_arg, struct in6_addr *laddr, u_int lport_arg, | ||||
int lookupflags, struct ifnet *ifp) | int lookupflags, struct ifnet *ifp, int numa_domain) | ||||
{ | { | ||||
struct inpcbhead *head; | struct inpcbhead *head; | ||||
struct inpcb *inp, *tmpinp; | struct inpcb *inp, *tmpinp; | ||||
u_short fport = fport_arg, lport = lport_arg; | u_short fport = fport_arg, lport = lport_arg; | ||||
KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0, | KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0, | ||||
("%s: invalid lookup flags %d", __func__, lookupflags)); | ("%s: invalid lookup flags %d", __func__, lookupflags)); | ||||
Show All 27 Lines | in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, | ||||
if (tmpinp != NULL) | if (tmpinp != NULL) | ||||
return (tmpinp); | return (tmpinp); | ||||
/* | /* | ||||
* Then look in lb group (for wildcard match). | * Then look in lb group (for wildcard match). | ||||
*/ | */ | ||||
if ((lookupflags & INPLOOKUP_WILDCARD) != 0) { | if ((lookupflags & INPLOOKUP_WILDCARD) != 0) { | ||||
inp = in6_pcblookup_lbgroup(pcbinfo, laddr, lport, faddr, | inp = in6_pcblookup_lbgroup(pcbinfo, laddr, lport, faddr, | ||||
fport, lookupflags); | fport, lookupflags, numa_domain); | ||||
if (inp != NULL) | if (inp != NULL) | ||||
return (inp); | return (inp); | ||||
} | } | ||||
/* | /* | ||||
* Then look for a wildcard match, if requested. | * Then look for a wildcard match, if requested. | ||||
*/ | */ | ||||
if ((lookupflags & INPLOOKUP_WILDCARD) != 0) { | if ((lookupflags & INPLOOKUP_WILDCARD) != 0) { | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Lookup PCB in hash list, using pcbinfo tables. This variation locks the | * Lookup PCB in hash list, using pcbinfo tables. This variation locks the | ||||
* hash list lock, and will return the inpcb locked (i.e., requires | * hash list lock, and will return the inpcb locked (i.e., requires | ||||
* INPLOOKUP_LOCKPCB). | * INPLOOKUP_LOCKPCB). | ||||
*/ | */ | ||||
static struct inpcb * | static struct inpcb * | ||||
in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, | in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, | ||||
u_int fport, struct in6_addr *laddr, u_int lport, int lookupflags, | u_int fport, struct in6_addr *laddr, u_int lport, int lookupflags, | ||||
struct ifnet *ifp) | struct ifnet *ifp, int numa_domain) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
INP_HASH_RLOCK(pcbinfo); | INP_HASH_RLOCK(pcbinfo); | ||||
inp = in6_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport, | inp = in6_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport, | ||||
(lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp); | (lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp, | ||||
numa_domain); | |||||
if (inp != NULL) { | if (inp != NULL) { | ||||
if (lookupflags & INPLOOKUP_WLOCKPCB) { | if (lookupflags & INPLOOKUP_WLOCKPCB) { | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
if (__predict_false(inp->inp_flags2 & INP_FREED)) { | if (__predict_false(inp->inp_flags2 & INP_FREED)) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
inp = NULL; | inp = NULL; | ||||
} | } | ||||
} else if (lookupflags & INPLOOKUP_RLOCKPCB) { | } else if (lookupflags & INPLOOKUP_RLOCKPCB) { | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | #if defined(PCBGROUP) && !defined(RSS) | ||||
if (in_pcbgroup_enabled(pcbinfo)) { | if (in_pcbgroup_enabled(pcbinfo)) { | ||||
pcbgroup = in6_pcbgroup_bytuple(pcbinfo, laddr, lport, faddr, | pcbgroup = in6_pcbgroup_bytuple(pcbinfo, laddr, lport, faddr, | ||||
fport); | fport); | ||||
return (in6_pcblookup_group(pcbinfo, pcbgroup, faddr, fport, | return (in6_pcblookup_group(pcbinfo, pcbgroup, faddr, fport, | ||||
laddr, lport, lookupflags, ifp)); | laddr, lport, lookupflags, ifp)); | ||||
} | } | ||||
#endif | #endif | ||||
return (in6_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport, | return (in6_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport, | ||||
lookupflags, ifp)); | lookupflags, ifp, M_NODOM)); | ||||
} | } | ||||
struct inpcb * | struct inpcb * | ||||
in6_pcblookup_mbuf(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, | in6_pcblookup_mbuf(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, | ||||
u_int fport, struct in6_addr *laddr, u_int lport, int lookupflags, | u_int fport, struct in6_addr *laddr, u_int lport, int lookupflags, | ||||
struct ifnet *ifp, struct mbuf *m) | struct ifnet *ifp, struct mbuf *m) | ||||
{ | { | ||||
#ifdef PCBGROUP | #ifdef PCBGROUP | ||||
Show All 25 Lines | #ifndef RSS | ||||
pcbgroup = in6_pcbgroup_bytuple(pcbinfo, laddr, lport, faddr, | pcbgroup = in6_pcbgroup_bytuple(pcbinfo, laddr, lport, faddr, | ||||
fport); | fport); | ||||
return (in6_pcblookup_group(pcbinfo, pcbgroup, faddr, fport, | return (in6_pcblookup_group(pcbinfo, pcbgroup, faddr, fport, | ||||
laddr, lport, lookupflags, ifp)); | laddr, lport, lookupflags, ifp)); | ||||
#endif | #endif | ||||
} | } | ||||
#endif | #endif | ||||
return (in6_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport, | return (in6_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport, | ||||
lookupflags, ifp)); | lookupflags, ifp, m->m_pkthdr.numa_domain)); | ||||
} | } | ||||
void | void | ||||
init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m, int srcordst) | init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m, int srcordst) | ||||
{ | { | ||||
struct ip6_hdr *ip; | struct ip6_hdr *ip; | ||||
ip = mtod(m, struct ip6_hdr *); | ip = mtod(m, struct ip6_hdr *); | ||||
Show All 9 Lines |
See netinet comment.