ok mvs@
> On 23 Jul 2022, at 03:15, Alexander Bluhm <[email protected]> wrote:
>
> Hi,
>
> The IPv6 reassembly code looks 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.
>
> ok?
>
> bluhm
>
> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.372
> diff -u -p -r1.372 ip_input.c
> --- netinet/ip_input.c 29 Jun 2022 09:01:48 -0000 1.372
> +++ netinet/ip_input.c 22 Jul 2022 21:59:38 -0000
> @@ -142,6 +142,11 @@ int ip_local(struct mbuf **, 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,14 +559,29 @@ ip_input_if(struct mbuf **mp, int *offp,
> 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;
> +
> + NET_ASSERT_WLOCKED();
> +
> + 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;
>
> - NET_ASSERT_WLOCKED();
> -
> + ip = mtod(*mp, struct ip *);
> hlen = ip->ip_hl << 2;
>
> /*
> @@ -568,12 +592,12 @@ ip_local(struct mbuf **mp, int *offp, in
> * 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);
> @@ -630,28 +654,26 @@ ip_local(struct mbuf **mp, int *offp, in
> }
> 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);
> Index: netinet/ip_var.h
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_var.h,v
> retrieving revision 1.93
> diff -u -p -r1.93 ip_var.h
> --- netinet/ip_var.h 5 May 2022 13:57:40 -0000 1.93
> +++ netinet/ip_var.h 22 Jul 2022 21:39:01 -0000
> @@ -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 i
> 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 *);
>