/* * Update the pcbgroup of an inpcb, which might include removing an old * pcbgroup reference and/or adding a new one. Wildcard processing is not * performed here, although ideally we'll never install a pcbgroup for a * wildcard inpcb (asserted below). */ static void in_pcbgroup_update_internal(struct inpcbinfo *pcbinfo, struct inpcbgroup *newpcbgroup, struct inpcb *inp) { struct inpcbgroup *oldpcbgroup; struct inpcbhead *pcbhash; uint32_t hashkey_faddr; INP_WLOCK_ASSERT(inp); oldpcbgroup = inp->inp_pcbgroup; if (oldpcbgroup != NULL && oldpcbgroup != newpcbgroup) { INP_GROUP_LOCK(oldpcbgroup); LIST_REMOVE(inp, inp_pcbgrouphash); inp->inp_pcbgroup = NULL; INP_GROUP_UNLOCK(oldpcbgroup); } if (newpcbgroup != NULL && oldpcbgroup != newpcbgroup) { #ifdef INET6 if (inp->inp_vflag & INP_IPV6) hashkey_faddr = INP6_PCBHASHKEY(&inp->in6p_faddr); else #endif hashkey_faddr = inp->inp_faddr.s_addr; INP_GROUP_LOCK(newpcbgroup); /* * If the inp is an RSS bucket wildcard entry, ensure * that the PCB hash is calculated correctly. * * The wildcard hash calculation differs from the * non-wildcard definition. The source address is * INADDR_ANY and the far port is 0. */ if (inp->inp_flags2 & INP_RSS_BUCKET_SET) { pcbhash = &newpcbgroup->ipg_hashbase[ INP_PCBHASH(INADDR_ANY, inp->inp_lport, 0, newpcbgroup->ipg_hashmask)]; } else { pcbhash = &newpcbgroup->ipg_hashbase[ INP_PCBHASH(hashkey_faddr, inp->inp_lport, inp->inp_fport, newpcbgroup->ipg_hashmask)]; } LIST_INSERT_HEAD(pcbhash, inp, inp_pcbgrouphash); inp->inp_pcbgroup = newpcbgroup; INP_GROUP_UNLOCK(newpcbgroup); } KASSERT(!(newpcbgroup != NULL && in_pcbwild_needed(inp)), ("%s: pcbgroup and wildcard!", __func__)); }
/* * Update the pcbgroup of an inpcb, which might include removing an old * pcbgroup reference and/or adding a new one. Wildcard processing is not * performed here, although ideally we'll never install a pcbgroup for a * wildcard inpcb (asserted below). */ static void in_pcbgroup_update_internal(struct inpcbinfo *pcbinfo, struct inpcbgroup *newpcbgroup, struct inpcb *inp) { struct inpcbgroup *oldpcbgroup; struct inpcbhead *pcbhash; uint32_t hashkey_faddr; INP_WLOCK_ASSERT(inp); oldpcbgroup = inp->inp_pcbgroup; if (oldpcbgroup != NULL && oldpcbgroup != newpcbgroup) { INP_GROUP_LOCK(oldpcbgroup); LIST_REMOVE(inp, inp_pcbgrouphash); inp->inp_pcbgroup = NULL; INP_GROUP_UNLOCK(oldpcbgroup); } if (newpcbgroup != NULL && oldpcbgroup != newpcbgroup) { #ifdef INET6 if (inp->inp_vflag & INP_IPV6) hashkey_faddr = inp->in6p_faddr.s6_addr32[3]; /* XXX */ else #endif hashkey_faddr = inp->inp_faddr.s_addr; INP_GROUP_LOCK(newpcbgroup); pcbhash = &newpcbgroup->ipg_hashbase[ INP_PCBHASH(hashkey_faddr, inp->inp_lport, inp->inp_fport, newpcbgroup->ipg_hashmask)]; LIST_INSERT_HEAD(pcbhash, inp, inp_pcbgrouphash); inp->inp_pcbgroup = newpcbgroup; INP_GROUP_UNLOCK(newpcbgroup); } KASSERT(!(newpcbgroup != NULL && in_pcbwild_needed(inp)), ("%s: pcbgroup and wildcard!", __func__)); }
static void in_pcbwild_remove(struct inpcb *inp) { struct inpcbinfo *pcbinfo; u_int pgn; INP_WLOCK_ASSERT(inp); KASSERT((inp->inp_flags2 & INP_PCBGROUPWILD), ("%s: not wild", __func__)); pcbinfo = inp->inp_pcbinfo; for (pgn = 0; pgn < pcbinfo->ipi_npcbgroups; pgn++) INP_GROUP_LOCK(&pcbinfo->ipi_pcbgroups[pgn]); LIST_REMOVE(inp, inp_pcbgroup_wild); for (pgn = 0; pgn < pcbinfo->ipi_npcbgroups; pgn++) INP_GROUP_UNLOCK(&pcbinfo->ipi_pcbgroups[pgn]); inp->inp_flags2 &= ~INP_PCBGROUPWILD; }
/* * Remove pcbgroup entry and optional pcbgroup wildcard entry for this inpcb. */ void in_pcbgroup_remove(struct inpcb *inp) { struct inpcbgroup *pcbgroup; INP_WLOCK_ASSERT(inp); if (!in_pcbgroup_enabled(inp->inp_pcbinfo)) return; if (inp->inp_flags2 & INP_PCBGROUPWILD) in_pcbwild_remove(inp); pcbgroup = inp->inp_pcbgroup; if (pcbgroup != NULL) { INP_GROUP_LOCK(pcbgroup); LIST_REMOVE(inp, inp_pcbgrouphash); inp->inp_pcbgroup = NULL; INP_GROUP_UNLOCK(pcbgroup); } }
static void in_pcbwild_add(struct inpcb *inp) { struct inpcbinfo *pcbinfo; struct inpcbhead *head; u_int pgn; INP_WLOCK_ASSERT(inp); KASSERT(!(inp->inp_flags2 & INP_PCBGROUPWILD), ("%s: is wild",__func__)); pcbinfo = inp->inp_pcbinfo; for (pgn = 0; pgn < pcbinfo->ipi_npcbgroups; pgn++) INP_GROUP_LOCK(&pcbinfo->ipi_pcbgroups[pgn]); head = &pcbinfo->ipi_wildbase[INP_PCBHASH(INADDR_ANY, inp->inp_lport, 0, pcbinfo->ipi_wildmask)]; LIST_INSERT_HEAD(head, inp, inp_pcbgroup_wild); inp->inp_flags2 |= INP_PCBGROUPWILD; for (pgn = 0; pgn < pcbinfo->ipi_npcbgroups; pgn++) INP_GROUP_UNLOCK(&pcbinfo->ipi_pcbgroups[pgn]); }