Hi,

I preparation for my TSO in software diff, I would like to cleanup
the fragment code.  Both are very simmilar and I like consistency.

- Use if_output_ml() to send mbuf lists to interfaces.  This can
  be used for TSO, fragments, ARP and ND6.
- Rename variable fml to ml.  It will soon be used for TCP segments,
  no need to have the f for fragment in the name.
- In pf_route6() split the if else block, then tcp_chopper() can
  be easily put in there in the next diff.
- In ip_fragment() the if (hlen + firstlen < tlen) is a new safety
  check.  It makes the code correct for the case where the packet
  was to short to be fragmented.  This should not happen, but the
  other functions also have this logic.

No functional change intended.

ok?

bluhm

Index: net/if.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if.c,v
retrieving revision 1.694
diff -u -p -r1.694 if.c
--- net/if.c    26 Apr 2023 19:54:35 -0000      1.694
+++ net/if.c    5 May 2023 20:27:06 -0000
@@ -762,27 +762,6 @@ if_enqueue_ifq(struct ifnet *ifp, struct
 }
 
 void
-if_mqoutput(struct ifnet *ifp, struct mbuf_queue *mq, unsigned int *total,
-    struct sockaddr *dst, struct rtentry *rt)
-{
-       struct mbuf_list ml;
-       struct mbuf *m;
-       unsigned int len;
-
-       mq_delist(mq, &ml);
-       len = ml_len(&ml);
-       while ((m = ml_dequeue(&ml)) != NULL)
-               ifp->if_output(ifp, m, rt_key(rt), rt);
-
-       /* XXXSMP we also discard if other CPU enqueues */
-       if (mq_len(mq) > 0) {
-               /* mbuf is back in queue. Discard. */
-               atomic_sub_int(total, len + mq_purge(mq));
-       } else
-               atomic_sub_int(total, len);
-}
-
-void
 if_input(struct ifnet *ifp, struct mbuf_list *ml)
 {
        ifiq_input(&ifp->if_rcv, ml);
@@ -841,6 +820,46 @@ if_input_local(struct ifnet *ifp, struct
        }
 
        return (0);
+}
+
+int
+if_output_ml(struct ifnet *ifp, struct mbuf_list *ml,
+    struct sockaddr *dst, struct rtentry *rt)
+{
+       struct mbuf *m;
+       int error = 0;
+
+       while ((m = ml_dequeue(ml)) != NULL) {
+               error = ifp->if_output(ifp, m, dst, rt);
+               if (error)
+                       break;
+       }
+       if (error)
+               ml_purge(ml);
+
+       return error;
+}
+
+int
+if_output_mq(struct ifnet *ifp, struct mbuf_queue *mq, unsigned int *total,
+    struct sockaddr *dst, struct rtentry *rt)
+{
+       struct mbuf_list ml;
+       unsigned int len;
+       int error;
+
+       mq_delist(mq, &ml);
+       len = ml_len(&ml);
+       error = if_output_ml(ifp, &ml, dst, rt);
+
+       /* XXXSMP we also discard if other CPU enqueues */
+       if (mq_len(mq) > 0) {
+               /* mbuf is back in queue. Discard. */
+               atomic_sub_int(total, len + mq_purge(mq));
+       } else
+               atomic_sub_int(total, len);
+
+       return error;
 }
 
 int
Index: net/if_bridge.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if_bridge.c,v
retrieving revision 1.365
diff -u -p -r1.365 if_bridge.c
--- net/if_bridge.c     27 Feb 2023 09:35:32 -0000      1.365
+++ net/if_bridge.c     5 May 2023 20:38:22 -0000
@@ -1826,7 +1826,7 @@ bridge_fragment(struct ifnet *brifp, str
     struct mbuf *m)
 {
        struct llc llc;
-       struct mbuf_list fml;
+       struct mbuf_list ml;
        int error = 0;
        int hassnap = 0;
        u_int16_t etype;
@@ -1884,11 +1884,11 @@ bridge_fragment(struct ifnet *brifp, str
                return;
        }
 
-       error = ip_fragment(m, &fml, ifp, ifp->if_mtu);
+       error = ip_fragment(m, &ml, ifp, ifp->if_mtu);
        if (error)
                return;
 
-       while ((m = ml_dequeue(&fml)) != NULL) {
+       while ((m = ml_dequeue(&ml)) != NULL) {
                if (hassnap) {
                        M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
                        if (m == NULL) {
@@ -1908,7 +1908,7 @@ bridge_fragment(struct ifnet *brifp, str
                        break;
        }
        if (error)
-               ml_purge(&fml);
+               ml_purge(&ml);
        else
                ipstat_inc(ips_fragmented);
 
Index: net/if_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if_var.h,v
retrieving revision 1.125
diff -u -p -r1.125 if_var.h
--- net/if_var.h        18 Apr 2023 22:01:24 -0000      1.125
+++ net/if_var.h        5 May 2023 21:07:16 -0000
@@ -321,12 +321,14 @@ extern struct ifnet_head ifnetlist;
 void   if_start(struct ifnet *);
 int    if_enqueue(struct ifnet *, struct mbuf *);
 int    if_enqueue_ifq(struct ifnet *, struct mbuf *);
-void   if_mqoutput(struct ifnet *, struct mbuf_queue *, unsigned int *,
-           struct sockaddr *, struct rtentry *);
 void   if_input(struct ifnet *, struct mbuf_list *);
 void   if_vinput(struct ifnet *, struct mbuf *);
 void   if_input_process(struct ifnet *, struct mbuf_list *);
 int    if_input_local(struct ifnet *, struct mbuf *, sa_family_t);
+int    if_output_ml(struct ifnet *, struct mbuf_list *,
+           struct sockaddr *, struct rtentry *);
+int    if_output_mq(struct ifnet *, struct mbuf_queue *, unsigned int *,
+           struct sockaddr *, struct rtentry *);
 int    if_output_local(struct ifnet *, struct mbuf *, sa_family_t);
 void   if_rtrequest_dummy(struct ifnet *, int, struct rtentry *);
 void   p2p_rtrequest(struct ifnet *, int, struct rtentry *);
Index: net/pf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
retrieving revision 1.1175
diff -u -p -r1.1175 pf.c
--- net/pf.c    3 May 2023 10:32:47 -0000       1.1175
+++ net/pf.c    5 May 2023 20:38:22 -0000
@@ -6466,12 +6466,11 @@ void
 pf_route(struct pf_pdesc *pd, struct pf_state *st)
 {
        struct mbuf             *m0;
-       struct mbuf_list         fml;
+       struct mbuf_list         ml;
        struct sockaddr_in      *dst, sin;
        struct rtentry          *rt = NULL;
        struct ip               *ip;
        struct ifnet            *ifp = NULL;
-       int                      error = 0;
        unsigned int             rtableid;
 
        if (pd->m->m_pkthdr.pf.routed++ > 3) {
@@ -6559,7 +6558,7 @@ pf_route(struct pf_pdesc *pd, struct pf_
                        ipstat_inc(ips_outswcsum);
                        ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
                }
-               error = ifp->if_output(ifp, m0, sintosa(dst), rt);
+               ifp->if_output(ifp, m0, sintosa(dst), rt);
                goto done;
        }
 
@@ -6575,19 +6574,10 @@ pf_route(struct pf_pdesc *pd, struct pf_
                goto bad;
        }
 
-       error = ip_fragment(m0, &fml, ifp, ifp->if_mtu);
-       if (error)
+       if (ip_fragment(m0, &ml, ifp, ifp->if_mtu) ||
+           if_output_ml(ifp, &ml, sintosa(dst), rt))
                goto done;
-
-       while ((m0 = ml_dequeue(&fml)) != NULL) {
-               error = ifp->if_output(ifp, m0, sintosa(dst), rt);
-               if (error)
-                       break;
-       }
-       if (error)
-               ml_purge(&fml);
-       else
-               ipstat_inc(ips_fragmented);
+       ipstat_inc(ips_fragmented);
 
 done:
        if_put(ifp);
@@ -6695,15 +6685,19 @@ pf_route6(struct pf_pdesc *pd, struct pf
         */
        if ((mtag = m_tag_find(m0, PACKET_TAG_PF_REASSEMBLED, NULL))) {
                (void) pf_refragment6(&m0, mtag, dst, ifp, rt);
-       } else if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
+               goto done;
+       }
+
+       if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
                ifp->if_output(ifp, m0, sin6tosa(dst), rt);
-       } else {
-               ip6stat_inc(ip6s_cantfrag);
-               if (st->rt != PF_DUPTO)
-                       pf_send_icmp(m0, ICMP6_PACKET_TOO_BIG, 0,
-                           ifp->if_mtu, pd->af, st->rule.ptr, pd->rdomain);
-               goto bad;
+               goto done;
        }
+
+       ip6stat_inc(ip6s_cantfrag);
+       if (st->rt != PF_DUPTO)
+               pf_send_icmp(m0, ICMP6_PACKET_TOO_BIG, 0,
+                   ifp->if_mtu, pd->af, st->rule.ptr, pd->rdomain);
+       goto bad;
 
 done:
        if_put(ifp);
Index: net/pf_norm.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.226
diff -u -p -r1.226 pf_norm.c
--- net/pf_norm.c       6 Nov 2022 18:05:05 -0000       1.226
+++ net/pf_norm.c       5 May 2023 20:38:22 -0000
@@ -954,7 +954,7 @@ pf_refragment6(struct mbuf **m0, struct 
     struct ifnet *ifp, struct rtentry *rt)
 {
        struct mbuf             *m = *m0;
-       struct mbuf_list         fml;
+       struct mbuf_list         ml;
        struct pf_fragment_tag  *ftag = (struct pf_fragment_tag *)(mtag + 1);
        u_int32_t                mtu;
        u_int16_t                hdrlen, extoff, maxlen;
@@ -997,14 +997,14 @@ pf_refragment6(struct mbuf **m0, struct 
         * we drop the packet.
         */
        mtu = hdrlen + sizeof(struct ip6_frag) + maxlen;
-       error = ip6_fragment(m, &fml, hdrlen, proto, mtu);
+       error = ip6_fragment(m, &ml, hdrlen, proto, mtu);
        *m0 = NULL;     /* ip6_fragment() has consumed original packet. */
        if (error) {
                DPFPRINTF(LOG_NOTICE, "refragment error %d", error);
                return (PF_DROP);
        }
 
-       while ((m = ml_dequeue(&fml)) != NULL) {
+       while ((m = ml_dequeue(&ml)) != NULL) {
                m->m_pkthdr.pf.flags |= PF_TAG_REFRAGMENTED;
                if (ifp == NULL) {
                        ip6_forward(m, NULL, 0);
Index: netinet/if_ether.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/if_ether.c,v
retrieving revision 1.263
diff -u -p -r1.263 if_ether.c
--- netinet/if_ether.c  25 Apr 2023 16:24:25 -0000      1.263
+++ netinet/if_ether.c  5 May 2023 20:27:06 -0000
@@ -723,7 +723,7 @@ arpcache(struct ifnet *ifp, struct ether
 
        la->la_asked = 0;
        la->la_refreshed = 0;
-       if_mqoutput(ifp, &la->la_mq, &la_hold_total, rt_key(rt), rt);
+       if_output_mq(ifp, &la->la_mq, &la_hold_total, rt_key(rt), rt);
 
        return (0);
 }
Index: netinet/ip_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.382
diff -u -p -r1.382 ip_output.c
--- netinet/ip_output.c 12 Aug 2022 17:04:16 -0000      1.382
+++ netinet/ip_output.c 5 May 2023 20:44:45 -0000
@@ -104,7 +104,7 @@ ip_output(struct mbuf *m, struct mbuf *o
 {
        struct ip *ip;
        struct ifnet *ifp = NULL;
-       struct mbuf_list fml;
+       struct mbuf_list ml;
        int hlen = sizeof (struct ip);
        int error = 0;
        struct route iproute;
@@ -505,19 +505,10 @@ sendit:
                goto bad;
        }
 
-       error = ip_fragment(m, &fml, ifp, mtu);
-       if (error)
+       if ((error = ip_fragment(m, &ml, ifp, mtu)) ||
+           (error = if_output_ml(ifp, &ml, sintosa(dst), ro->ro_rt)))
                goto done;
-
-       while ((m = ml_dequeue(&fml)) != NULL) {
-               error = ifp->if_output(ifp, m, sintosa(dst), ro->ro_rt);
-               if (error)
-                       break;
-       }
-       if (error)
-               ml_purge(&fml);
-       else
-               ipstat_inc(ips_fragmented);
+       ipstat_inc(ips_fragmented);
 
 done:
        if (ro == &iproute && ro->ro_rt)
@@ -677,16 +668,15 @@ ip_output_ipsec_send(struct tdb *tdb, st
 #endif /* IPSEC */
 
 int
-ip_fragment(struct mbuf *m0, struct mbuf_list *fml, struct ifnet *ifp,
+ip_fragment(struct mbuf *m0, struct mbuf_list *ml, struct ifnet *ifp,
     u_long mtu)
 {
-       struct mbuf *m;
        struct ip *ip;
        int firstlen, hlen, tlen, len, off;
        int error;
 
-       ml_init(fml);
-       ml_enqueue(fml, m0);
+       ml_init(ml);
+       ml_enqueue(ml, m0);
 
        ip = mtod(m0, struct ip *);
        hlen = ip->ip_hl << 2;
@@ -705,10 +695,11 @@ ip_fragment(struct mbuf *m0, struct mbuf
        in_proto_cksum_out(m0, NULL);
 
        /*
-        * Loop through length of segment after first fragment,
+        * Loop through length of payload after first fragment,
         * make new header and copy data of each part and link onto chain.
         */
        for (off = hlen + firstlen; off < tlen; off += len) {
+               struct mbuf *m;
                struct ip *mhip;
                int mhlen;
 
@@ -717,8 +708,7 @@ ip_fragment(struct mbuf *m0, struct mbuf
                        error = ENOBUFS;
                        goto bad;
                }
-               ml_enqueue(fml, m);
-
+               ml_enqueue(ml, m);
                if ((error = m_dup_pkthdr(m, m0, M_DONTWAIT)) != 0)
                        goto bad;
                m->m_data += max_linkhdr;
@@ -762,25 +752,26 @@ ip_fragment(struct mbuf *m0, struct mbuf
         * Update first fragment by trimming what's been copied out
         * and updating header, then send each fragment (in order).
         */
-       m = m0;
-       m_adj(m, hlen + firstlen - tlen);
-       ip->ip_off |= htons(IP_MF);
-       ip->ip_len = htons(m->m_pkthdr.len);
+       if (hlen + firstlen < tlen) {
+               m_adj(m0, hlen + firstlen - tlen);
+               ip->ip_off |= htons(IP_MF);
+       }
+       ip->ip_len = htons(m0->m_pkthdr.len);
 
        ip->ip_sum = 0;
-       if (in_ifcap_cksum(m, ifp, IFCAP_CSUM_IPv4))
-               m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
+       if (in_ifcap_cksum(m0, ifp, IFCAP_CSUM_IPv4))
+               m0->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
        else {
                ipstat_inc(ips_outswcsum);
-               ip->ip_sum = in_cksum(m, hlen);
+               ip->ip_sum = in_cksum(m0, hlen);
        }
 
-       ipstat_add(ips_ofragments, ml_len(fml));
+       ipstat_add(ips_ofragments, ml_len(ml));
        return (0);
 
 bad:
        ipstat_inc(ips_odropped);
-       ml_purge(fml);
+       ml_purge(ml);
        return (error);
 }
 
Index: netinet6/ip6_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.272
diff -u -p -r1.272 ip6_output.c
--- netinet6/ip6_output.c       12 Nov 2022 02:50:59 -0000      1.272
+++ netinet6/ip6_output.c       5 May 2023 20:41:23 -0000
@@ -165,7 +165,7 @@ ip6_output(struct mbuf *m, struct ip6_pk
 {
        struct ip6_hdr *ip6;
        struct ifnet *ifp = NULL;
-       struct mbuf_list fml;
+       struct mbuf_list ml;
        int hlen, tlen;
        struct route_in6 ip6route;
        struct rtentry *rt = NULL;
@@ -751,19 +751,10 @@ reroute:
                ip6->ip6_nxt = IPPROTO_FRAGMENT;
        }
 
-       error = ip6_fragment(m, &fml, hlen, nextproto, mtu);
-       if (error)
+       if ((error = ip6_fragment(m, &ml, hlen, nextproto, mtu)) ||
+           (error = if_output_ml(ifp, &ml, sin6tosa(dst), ro->ro_rt)))
                goto done;
-
-       while ((m = ml_dequeue(&fml)) != NULL) {
-               error = ifp->if_output(ifp, m, sin6tosa(dst), ro->ro_rt);
-               if (error)
-                       break;
-       }
-       if (error)
-               ml_purge(&fml);
-       else
-               ip6stat_inc(ip6s_fragmented);
+       ip6stat_inc(ip6s_fragmented);
 
 done:
        if (ro == &ip6route && ro->ro_rt) {
@@ -789,16 +780,15 @@ bad:
 }
 
 int
-ip6_fragment(struct mbuf *m0, struct mbuf_list *fml, int hlen,
-    u_char nextproto, u_long mtu)
+ip6_fragment(struct mbuf *m0, struct mbuf_list *ml, int hlen, u_char nextproto,
+    u_long mtu)
 {
-       struct mbuf *m;
        struct ip6_hdr *ip6;
        u_int32_t id;
        int tlen, len, off;
        int error;
 
-       ml_init(fml);
+       ml_init(ml);
 
        ip6 = mtod(m0, struct ip6_hdr *);
        tlen = m0->m_pkthdr.len;
@@ -810,10 +800,11 @@ ip6_fragment(struct mbuf *m0, struct mbu
        id = htonl(ip6_randomid());
 
        /*
-        * Loop through length of segment,
+        * Loop through length of payload,
         * make new header and copy data of each part and link onto chain.
         */
        for (off = hlen; off < tlen; off += len) {
+               struct mbuf *m;
                struct mbuf *mlast;
                struct ip6_hdr *mhip6;
                struct ip6_frag *ip6f;
@@ -823,8 +814,7 @@ ip6_fragment(struct mbuf *m0, struct mbu
                        error = ENOBUFS;
                        goto bad;
                }
-               ml_enqueue(fml, m);
-
+               ml_enqueue(ml, m);
                if ((error = m_dup_pkthdr(m, m0, M_DONTWAIT)) != 0)
                        goto bad;
                m->m_data += max_linkhdr;
@@ -856,13 +846,13 @@ ip6_fragment(struct mbuf *m0, struct mbu
                ip6f->ip6f_nxt = nextproto;
        }
 
-       ip6stat_add(ip6s_ofragments, ml_len(fml));
+       ip6stat_add(ip6s_ofragments, ml_len(ml));
        m_freem(m0);
        return (0);
 
 bad:
        ip6stat_inc(ip6s_odropped);
-       ml_purge(fml);
+       ml_purge(ml);
        m_freem(m0);
        return (error);
 }
Index: netinet6/nd6.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/nd6.c,v
retrieving revision 1.275
diff -u -p -r1.275 nd6.c
--- netinet6/nd6.c      4 May 2023 06:56:56 -0000       1.275
+++ netinet6/nd6.c      5 May 2023 20:27:06 -0000
@@ -1181,7 +1181,7 @@ fail:
                         * meaningless.
                         */
                        nd6_llinfo_settimer(ln, nd6_gctimer);
-                       if_mqoutput(ifp, &ln->ln_mq, &ln_hold_total,
+                       if_output_mq(ifp, &ln->ln_mq, &ln_hold_total,
                            rt_key(rt), rt);
                } else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
                        /* probe right away */
Index: netinet6/nd6_nbr.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/nd6_nbr.c,v
retrieving revision 1.148
diff -u -p -r1.148 nd6_nbr.c
--- netinet6/nd6_nbr.c  4 May 2023 06:56:56 -0000       1.148
+++ netinet6/nd6_nbr.c  5 May 2023 20:27:06 -0000
@@ -851,7 +851,7 @@ nd6_na_input(struct mbuf *m, int off, in
        }
        rt->rt_flags &= ~RTF_REJECT;
        ln->ln_asked = 0;
-       if_mqoutput(ifp, &ln->ln_mq, &ln_hold_total, rt_key(rt), rt);
+       if_output_mq(ifp, &ln->ln_mq, &ln_hold_total, rt_key(rt), rt);
 
  freeit:
        rtfree(rt);

Reply via email to