X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/6ef5977b2515c6d1ad78df0d688ca3f1f4ddd925..93bffecadc0caefc46f12b736eab0e62c2b6f42e:/sys/netinet/ip_divert.c diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index 07b2c473be..c714e71bdb 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -126,6 +127,8 @@ static u_long div_recvspace = DIVRCVQ; /* XXX sysctl ? */ static struct mbuf *ip_divert(struct mbuf *, int, int); +static struct lwkt_token div_token = LWKT_TOKEN_MP_INITIALIZER(div_token); + /* * Initialize divert connection block queue. */ @@ -215,7 +218,16 @@ div_soport(struct socket *so, struct sockaddr *nam, struct mbuf **mptr) m->m_pkthdr.rcvif = ifa->ifa_ifp; } - return ip_mport(mptr, dir); + /* + * Recalculate the protocol thread. + */ + ip_cpufn(mptr, 0, dir); + m = *mptr; + if (m) { + KKASSERT(m->m_flags & M_HASH); + return(cpu_portfn(m->m_pkthdr.hash)); + } + return(NULL); } /* @@ -298,7 +310,7 @@ div_packet(struct mbuf *m, int incoming, int port) * saving/testing the socket pointer is not MPSAFE. So we still * need to hold BGL here. */ - get_mplock(); + lwkt_gettoken(&div_token); LIST_FOREACH(inp, &divcbinfo.pcblisthead, inp_list) { if (inp->inp_flags & INP_PLACEMARKER) continue; @@ -306,18 +318,18 @@ div_packet(struct mbuf *m, int incoming, int port) sa = inp->inp_socket; } if (sa) { - if (ssb_appendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc, m, - NULL) == 0) + lwkt_gettoken(&sa->so_rcv.ssb_token); + if (ssb_appendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc, m, NULL) == 0) m_freem(m); else sorwakeup(sa); - rel_mplock(); + lwkt_reltoken(&sa->so_rcv.ssb_token); } else { - rel_mplock(); m_freem(m); ipstat.ips_noproto++; ipstat.ips_delivered--; } + lwkt_reltoken(&div_token); } #ifdef SMP @@ -369,7 +381,7 @@ divert_packet(struct mbuf *m, int incoming) nmp = &m->m_hdr.mh_netmsg; netmsg_init(&nmp->nm_netmsg, NULL, &netisr_apanic_rport, - MSGF_MPSAFE, div_packet_handler); + 0, div_packet_handler); nmp->nm_packet = m; msg = &nmp->nm_netmsg.nm_lmsg; @@ -467,9 +479,12 @@ div_attach(struct socket *so, int proto, struct pru_attach_info *ai) error = soreserve(so, div_sendspace, div_recvspace, ai->sb_rlimit); if (error) return error; + lwkt_gettoken(&div_token); error = in_pcballoc(so, &divcbinfo); - if (error) + if (error) { + lwkt_reltoken(&div_token); return error; + } inp = (struct inpcb *)so->so_pcb; inp->inp_ip_p = proto; inp->inp_vflag |= INP_IPV4; @@ -479,7 +494,8 @@ div_attach(struct socket *so, int proto, struct pru_attach_info *ai) * we always know "where" to send the packet. */ so->so_port = cpu0_soport(so, NULL, NULL); - so->so_state |= SS_ISCONNECTED; + sosetstate(so, SS_ISCONNECTED); + lwkt_reltoken(&div_token); return 0; } @@ -495,19 +511,33 @@ div_detach(struct socket *so) return 0; } +/* + * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort() + * will sofree() it when we return. + */ static int div_abort(struct socket *so) { + int error; + soisdisconnected(so); - return div_detach(so); + error = div_detach(so); + + return error; } static int div_disconnect(struct socket *so) { + int error; + if (!(so->so_state & SS_ISCONNECTED)) return ENOTCONN; - return div_abort(so); + soreference(so); + error = div_abort(so); + sofree(so); + + return error; } static int @@ -543,7 +573,7 @@ static int div_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct thread *td) { - /* Length check already done in ip_mport() */ + /* Length check already done in ip_cpufn() */ KASSERT(m->m_len >= sizeof(struct ip), ("IP header not in one mbuf")); /* Send packet */