Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/in_pcb.c
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#include "opt_ipsec.h" | #include "opt_ipsec.h" | ||||
#include "opt_inet.h" | #include "opt_inet.h" | ||||
#include "opt_inet6.h" | #include "opt_inet6.h" | ||||
#include "opt_ratelimit.h" | #include "opt_ratelimit.h" | ||||
#include "opt_route.h" | #include "opt_route.h" | ||||
#include "opt_rss.h" | #include "opt_rss.h" | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/hash.h> | |||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/libkern.h> | |||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
#include <sys/callout.h> | #include <sys/callout.h> | ||||
#include <sys/eventhandler.h> | #include <sys/eventhandler.h> | ||||
#include <sys/domain.h> | #include <sys/domain.h> | ||||
#include <sys/protosw.h> | #include <sys/protosw.h> | ||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
▲ Show 20 Lines • Show All 180 Lines • ▼ Show 20 Lines | SYSCTL_COUNTER_U64(_net_inet_ip_rl, OID_AUTO, newrl, CTLFLAG_RD, | ||||
&rate_limit_new, "Total Rate limit new attempts"); | &rate_limit_new, "Total Rate limit new attempts"); | ||||
SYSCTL_COUNTER_U64(_net_inet_ip_rl, OID_AUTO, chgrl, CTLFLAG_RD, | SYSCTL_COUNTER_U64(_net_inet_ip_rl, OID_AUTO, chgrl, CTLFLAG_RD, | ||||
&rate_limit_chg, "Total Rate limited change attempts"); | &rate_limit_chg, "Total Rate limited change attempts"); | ||||
#endif /* RATELIMIT */ | #endif /* RATELIMIT */ | ||||
#endif /* INET */ | #endif /* INET */ | ||||
VNET_DEFINE(uint32_t, in_pcbhashseed); | |||||
static void | |||||
in_pcbhashseed_init(void) | |||||
{ | |||||
V_in_pcbhashseed = arc4random(); | |||||
} | |||||
VNET_SYSINIT(in_pcbhashseed_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, | |||||
in_pcbhashseed_init, 0); | |||||
/* | /* | ||||
* in_pcb.c: manage the Protocol Control Blocks. | * in_pcb.c: manage the Protocol Control Blocks. | ||||
* | * | ||||
* NOTE: It is assumed that most of these functions will be called with | * NOTE: It is assumed that most of these functions will be called with | ||||
* the pcbinfo lock held, and often, the inpcb lock held, as these utility | * the pcbinfo lock held, and often, the inpcb lock held, as these utility | ||||
* functions often modify hash chains or addresses in pcbs. | * functions often modify hash chains or addresses in pcbs. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 1,823 Lines • ▼ Show 20 Lines | #endif | ||||
INP_HASH_LOCK_ASSERT(pcbinfo); | INP_HASH_LOCK_ASSERT(pcbinfo); | ||||
if ((lookupflags & INPLOOKUP_WILDCARD) == 0) { | if ((lookupflags & INPLOOKUP_WILDCARD) == 0) { | ||||
struct inpcbhead *head; | struct inpcbhead *head; | ||||
/* | /* | ||||
* Look for an unconnected (wildcard foreign addr) PCB that | * Look for an unconnected (wildcard foreign addr) PCB that | ||||
* matches the local address and port we're looking for. | * matches the local address and port we're looking for. | ||||
*/ | */ | ||||
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport, | head = &pcbinfo->ipi_hashbase[INP_PCBHASH_WILD(lport, | ||||
0, pcbinfo->ipi_hashmask)]; | pcbinfo->ipi_hashmask)]; | ||||
CK_LIST_FOREACH(inp, head, inp_hash) { | CK_LIST_FOREACH(inp, head, inp_hash) { | ||||
#ifdef INET6 | #ifdef INET6 | ||||
/* XXX inp locking */ | /* XXX inp locking */ | ||||
if ((inp->inp_vflag & INP_IPV4) == 0) | if ((inp->inp_vflag & INP_IPV4) == 0) | ||||
continue; | continue; | ||||
#endif | #endif | ||||
if (inp->inp_faddr.s_addr == INADDR_ANY && | if (inp->inp_faddr.s_addr == INADDR_ANY && | ||||
inp->inp_laddr.s_addr == laddr.s_addr && | inp->inp_laddr.s_addr == laddr.s_addr && | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | in_pcblookup_lbgroup(const struct inpcbinfo *pcbinfo, | ||||
CK_LIST_FOREACH(grp, hdr, il_list) { | CK_LIST_FOREACH(grp, hdr, il_list) { | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (!(grp->il_vflag & INP_IPV4)) | if (!(grp->il_vflag & INP_IPV4)) | ||||
continue; | continue; | ||||
#endif | #endif | ||||
if (grp->il_lport != lport) | if (grp->il_lport != lport) | ||||
continue; | continue; | ||||
idx = INP_PCBLBGROUP_PKTHASH(faddr->s_addr, lport, fport) % | idx = INP_PCBLBGROUP_PKTHASH(faddr, lport, fport) % | ||||
grp->il_inpcnt; | grp->il_inpcnt; | ||||
if (grp->il_laddr.s_addr == laddr->s_addr) { | if (grp->il_laddr.s_addr == laddr->s_addr) { | ||||
if (numa_domain == M_NODOM || | if (numa_domain == M_NODOM || | ||||
grp->il_numa_domain == numa_domain) { | grp->il_numa_domain == numa_domain) { | ||||
return (grp->il_inp[idx]); | return (grp->il_inp[idx]); | ||||
} else { | } else { | ||||
numa_wild = grp->il_inp[idx]; | numa_wild = grp->il_inp[idx]; | ||||
} | } | ||||
Show All 29 Lines | in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in_addr faddr, | ||||
KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0, | KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0, | ||||
("%s: invalid lookup flags %d", __func__, lookupflags)); | ("%s: invalid lookup flags %d", __func__, lookupflags)); | ||||
INP_HASH_LOCK_ASSERT(pcbinfo); | INP_HASH_LOCK_ASSERT(pcbinfo); | ||||
/* | /* | ||||
* First look for an exact match. | * First look for an exact match. | ||||
*/ | */ | ||||
tmpinp = NULL; | tmpinp = NULL; | ||||
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, | head = &pcbinfo->ipi_hashbase[INP_PCBHASH(&faddr, lport, fport, | ||||
pcbinfo->ipi_hashmask)]; | pcbinfo->ipi_hashmask)]; | ||||
CK_LIST_FOREACH(inp, head, inp_hash) { | CK_LIST_FOREACH(inp, head, inp_hash) { | ||||
#ifdef INET6 | #ifdef INET6 | ||||
/* XXX inp locking */ | /* XXX inp locking */ | ||||
if ((inp->inp_vflag & INP_IPV4) == 0) | if ((inp->inp_vflag & INP_IPV4) == 0) | ||||
continue; | continue; | ||||
#endif | #endif | ||||
if (inp->inp_faddr.s_addr == faddr.s_addr && | if (inp->inp_faddr.s_addr == faddr.s_addr && | ||||
Show All 38 Lines | #endif | ||||
/* | /* | ||||
* Order of socket selection - we always prefer jails. | * Order of socket selection - we always prefer jails. | ||||
* 1. jailed, non-wild. | * 1. jailed, non-wild. | ||||
* 2. jailed, wild. | * 2. jailed, wild. | ||||
* 3. non-jailed, non-wild. | * 3. non-jailed, non-wild. | ||||
* 4. non-jailed, wild. | * 4. non-jailed, wild. | ||||
*/ | */ | ||||
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport, | head = &pcbinfo->ipi_hashbase[INP_PCBHASH_WILD(lport, | ||||
0, pcbinfo->ipi_hashmask)]; | pcbinfo->ipi_hashmask)]; | ||||
CK_LIST_FOREACH(inp, head, inp_hash) { | CK_LIST_FOREACH(inp, head, inp_hash) { | ||||
#ifdef INET6 | #ifdef INET6 | ||||
/* XXX inp locking */ | /* XXX inp locking */ | ||||
if ((inp->inp_vflag & INP_IPV4) == 0) | if ((inp->inp_vflag & INP_IPV4) == 0) | ||||
continue; | continue; | ||||
#endif | #endif | ||||
if (inp->inp_faddr.s_addr != INADDR_ANY || | if (inp->inp_faddr.s_addr != INADDR_ANY || | ||||
inp->inp_lport != lport) | inp->inp_lport != lport) | ||||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
int | int | ||||
in_pcbinshash(struct inpcb *inp) | in_pcbinshash(struct inpcb *inp) | ||||
{ | { | ||||
struct inpcbhead *pcbhash; | struct inpcbhead *pcbhash; | ||||
struct inpcbporthead *pcbporthash; | struct inpcbporthead *pcbporthash; | ||||
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; | struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; | ||||
struct inpcbport *phd; | struct inpcbport *phd; | ||||
u_int32_t hashkey_faddr; | |||||
int so_options; | int so_options; | ||||
INP_WLOCK_ASSERT(inp); | INP_WLOCK_ASSERT(inp); | ||||
INP_HASH_WLOCK_ASSERT(pcbinfo); | INP_HASH_WLOCK_ASSERT(pcbinfo); | ||||
KASSERT((inp->inp_flags & INP_INHASHLIST) == 0, | KASSERT((inp->inp_flags & INP_INHASHLIST) == 0, | ||||
("in_pcbinshash: INP_INHASHLIST")); | ("in_pcbinshash: INP_INHASHLIST")); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (inp->inp_vflag & INP_IPV6) | if (inp->inp_vflag & INP_IPV6) | ||||
hashkey_faddr = INP6_PCBHASHKEY(&inp->in6p_faddr); | pcbhash = &pcbinfo->ipi_hashbase[INP6_PCBHASH(&inp->in6p_faddr, | ||||
inp->inp_lport, inp->inp_fport, pcbinfo->ipi_hashmask)]; | |||||
else | else | ||||
#endif | #endif | ||||
hashkey_faddr = inp->inp_faddr.s_addr; | pcbhash = &pcbinfo->ipi_hashbase[INP_PCBHASH(&inp->inp_faddr, | ||||
pcbhash = &pcbinfo->ipi_hashbase[INP_PCBHASH(hashkey_faddr, | |||||
inp->inp_lport, inp->inp_fport, pcbinfo->ipi_hashmask)]; | inp->inp_lport, inp->inp_fport, pcbinfo->ipi_hashmask)]; | ||||
pcbporthash = &pcbinfo->ipi_porthashbase[ | pcbporthash = &pcbinfo->ipi_porthashbase[ | ||||
INP_PCBPORTHASH(inp->inp_lport, pcbinfo->ipi_porthashmask)]; | INP_PCBPORTHASH(inp->inp_lport, pcbinfo->ipi_porthashmask)]; | ||||
/* | /* | ||||
* Add entry to load balance group. | * Add entry to load balance group. | ||||
* Only do this if SO_REUSEPORT_LB is set. | * Only do this if SO_REUSEPORT_LB is set. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
* will lead to iterator traversing a possibly wrong hash list. However, | * will lead to iterator traversing a possibly wrong hash list. However, | ||||
* this race should have been here since change from rwlock to epoch. | * this race should have been here since change from rwlock to epoch. | ||||
*/ | */ | ||||
void | void | ||||
in_pcbrehash(struct inpcb *inp) | in_pcbrehash(struct inpcb *inp) | ||||
{ | { | ||||
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; | struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; | ||||
struct inpcbhead *head; | struct inpcbhead *head; | ||||
u_int32_t hashkey_faddr; | |||||
INP_WLOCK_ASSERT(inp); | INP_WLOCK_ASSERT(inp); | ||||
INP_HASH_WLOCK_ASSERT(pcbinfo); | INP_HASH_WLOCK_ASSERT(pcbinfo); | ||||
KASSERT(inp->inp_flags & INP_INHASHLIST, | KASSERT(inp->inp_flags & INP_INHASHLIST, | ||||
("in_pcbrehash: !INP_INHASHLIST")); | ("in_pcbrehash: !INP_INHASHLIST")); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (inp->inp_vflag & INP_IPV6) | if (inp->inp_vflag & INP_IPV6) | ||||
hashkey_faddr = INP6_PCBHASHKEY(&inp->in6p_faddr); | head = &pcbinfo->ipi_hashbase[INP6_PCBHASH(&inp->in6p_faddr, | ||||
inp->inp_lport, inp->inp_fport, pcbinfo->ipi_hashmask)]; | |||||
else | else | ||||
#endif | #endif | ||||
hashkey_faddr = inp->inp_faddr.s_addr; | head = &pcbinfo->ipi_hashbase[INP_PCBHASH(&inp->inp_faddr, | ||||
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(hashkey_faddr, | |||||
inp->inp_lport, inp->inp_fport, pcbinfo->ipi_hashmask)]; | inp->inp_lport, inp->inp_fport, pcbinfo->ipi_hashmask)]; | ||||
CK_LIST_REMOVE(inp, inp_hash); | CK_LIST_REMOVE(inp, inp_hash); | ||||
CK_LIST_INSERT_HEAD(head, inp, inp_hash); | CK_LIST_INSERT_HEAD(head, inp, inp_hash); | ||||
} | } | ||||
/* | /* | ||||
* Check for alternatives when higher level complains | * Check for alternatives when higher level complains | ||||
* about service problems. For now, invalidate cached | * about service problems. For now, invalidate cached | ||||
▲ Show 20 Lines • Show All 779 Lines • Show Last 20 Lines |