From: bluhm Date: Mon, 25 Jul 2022 23:19:34 +0000 (+0000) Subject: The IPv4 reassembly code is MP safe, so we can run it in parallel. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=3ab0b80351fa1da8906c5fdf2fae7995ad2e8d80;p=openbsd The IPv4 reassembly code is MP safe, so we can run it in parallel. Note that ip_ours() runs with shared netlock, while ip_local() has exclusive netlock after queuing. Move existing the code into function ip_fragcheck() and call it from ip_ours(). OK mvs@ --- diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 081ed006539..8ec2807459d 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.373 2022/07/24 22:38:25 bluhm Exp $ */ +/* $OpenBSD: ip_input.c,v 1.374 2022/07/25 23:19:34 bluhm Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -142,6 +142,11 @@ int ip_local(struct mbuf **, int *, int, int); int ip_dooptions(struct mbuf *, struct ifnet *); int in_ouraddr(struct mbuf *, struct ifnet *, struct rtentry **); +int ip_fragcheck(struct mbuf **, int *); +struct mbuf * ip_reass(struct ipqent *, struct ipq *); +void ip_freef(struct ipq *); +void ip_flush(void); + static void ip_send_dispatch(void *); static void ip_sendraw_dispatch(void *); static struct task ipsend_task = TASK_INITIALIZER(ip_send_dispatch, &ipsend_mq); @@ -234,6 +239,10 @@ ip_init(void) int ip_ours(struct mbuf **mp, int *offp, int nxt, int af) { + nxt = ip_fragcheck(mp, offp); + if (nxt == IPPROTO_DONE) + return IPPROTO_DONE; + /* We are already in a IPv4/IPv6 local deliver loop. */ if (af != AF_UNSPEC) return ip_local(mp, offp, nxt, af); @@ -550,12 +559,27 @@ ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) int ip_local(struct mbuf **mp, int *offp, int nxt, int af) { - struct mbuf *m = *mp; - struct ip *ip = mtod(m, struct ip *); + struct ip *ip; + + ip = mtod(*mp, struct ip *); + *offp = ip->ip_hl << 2; + nxt = ip->ip_p; + + /* Check whether we are already in a IPv4/IPv6 local deliver loop. */ + if (af == AF_UNSPEC) + nxt = ip_deliver(mp, offp, nxt, AF_INET); + return nxt; +} + +int +ip_fragcheck(struct mbuf **mp, int *offp) +{ + struct ip *ip; struct ipq *fp; struct ipqent *ipqe; int mff, hlen; + ip = mtod(*mp, struct ip *); hlen = ip->ip_hl << 2; /* @@ -566,12 +590,12 @@ ip_local(struct mbuf **mp, int *offp, int nxt, int af) * but it's not worth the time; just let them time out.) */ if (ip->ip_off &~ htons(IP_DF | IP_RF)) { - if (m->m_flags & M_EXT) { /* XXX */ - if ((m = *mp = m_pullup(m, hlen)) == NULL) { + if ((*mp)->m_flags & M_EXT) { /* XXX */ + if ((*mp = m_pullup(*mp, hlen)) == NULL) { ipstat_inc(ips_toosmall); return IPPROTO_DONE; } - ip = mtod(m, struct ip *); + ip = mtod(*mp, struct ip *); } mtx_enter(&ipq_mutex); @@ -628,28 +652,26 @@ ip_local(struct mbuf **mp, int *offp, int nxt, int af) } ip_frags++; ipqe->ipqe_mff = mff; - ipqe->ipqe_m = m; + ipqe->ipqe_m = *mp; ipqe->ipqe_ip = ip; - m = *mp = ip_reass(ipqe, fp); - if (m == NULL) + *mp = ip_reass(ipqe, fp); + if (*mp == NULL) goto bad; ipstat_inc(ips_reassembled); - ip = mtod(m, struct ip *); + ip = mtod(*mp, struct ip *); hlen = ip->ip_hl << 2; ip->ip_len = htons(ntohs(ip->ip_len) + hlen); - } else - if (fp) + } else { + if (fp != NULL) ip_freef(fp); + } mtx_leave(&ipq_mutex); } *offp = hlen; - nxt = ip->ip_p; - /* Check whether we are already in a IPv4/IPv6 local deliver loop. */ - if (af == AF_UNSPEC) - nxt = ip_deliver(mp, offp, nxt, AF_INET); - return nxt; + return ip->ip_p; + bad: mtx_leave(&ipq_mutex); m_freemp(mp); diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 3df8ffee7aa..f5e2a765e21 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.93 2022/05/05 13:57:40 claudio Exp $ */ +/* $OpenBSD: ip_var.h,v 1.94 2022/07/25 23:19:34 bluhm Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -223,9 +223,7 @@ struct route; struct inpcb; int ip_ctloutput(int, struct socket *, int, int, struct mbuf *); -void ip_flush(void); int ip_fragment(struct mbuf *, struct mbuf_list *, struct ifnet *, u_long); -void ip_freef(struct ipq *); void ip_freemoptions(struct ip_moptions *); int ip_getmoptions(int, struct ip_moptions *, struct mbuf *); void ip_init(void); @@ -235,8 +233,6 @@ int ip_mforward(struct mbuf *, struct ifnet *); int ip_optcopy(struct ip *, struct ip *); int ip_output(struct mbuf *, struct mbuf *, struct route *, int, struct ip_moptions *, struct inpcb *, u_int32_t); -struct mbuf * - ip_reass(struct ipqent *, struct ipq *); u_int16_t ip_randomid(void); void ip_send(struct mbuf *);