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 *);
> 

Reply via email to