Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/in6_pcb.c
Show First 20 Lines • Show All 440 Lines • ▼ Show 20 Lines | #endif | ||||
*/ | */ | ||||
if ((error = in6_pcbladdr(inp, nam, &laddr6.sin6_addr)) != 0) | if ((error = in6_pcbladdr(inp, nam, &laddr6.sin6_addr)) != 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) | ||||
? &laddr6.sin6_addr : &inp->in6p_laddr, | ? &laddr6.sin6_addr : &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) { | ||||
/* | /* | ||||
* rehash was required to be true in the past for | * rehash was required to be true in the past for | ||||
* this case; retain that convention. However, | * this case; retain that convention. However, | ||||
* we now call in_pcb_lport_dest rather than | * we now call in_pcb_lport_dest rather than | ||||
▲ Show 20 Lines • Show All 440 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, uint8_t 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 && | ||||
(local_wild == NULL || numa_domain == M_NODOM || | |||||
grp->il_numa_domain == numa_domain)) { | |||||
local_wild = grp->il_inp[idx]; | local_wild = grp->il_inp[idx]; | ||||
} | } | ||||
} | |||||
if (numa_wild != NULL) | |||||
return (numa_wild); | |||||
bz: See netinet comment. | |||||
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. Used in in_pcb.c as well as here. | * Lookup PCB in hash list. Used in in_pcb.c as well as here. | ||||
*/ | */ | ||||
struct inpcb * | 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, uint8_t 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, uint8_t numa_domain) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
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 49 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.