Hi,

I found a little inconsistency in IPv6 forwarding with TSO.

Sending with TSO should only done if the large packet does not fit
in the interface MTU.  In case tcp_if_output_tso() does not process
the packet, we should send an ICMP6 error.  Rearrange the code that
it looks more like other calls to tcp_if_output_tso().

All these cases can only be reached when LRO is turned on for IPv6
which none of our drivers currently supports.

When comparing ip6_forward() with ip6_output() I found a typo there.
Of course we have to compare ph_mss with if_mtu and not the packet
checksum flags.  ph_mss contains the size of the copped packets.

ok?

bluhm

Index: netinet6/ip6_forward.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_forward.c,v
retrieving revision 1.110
diff -u -p -r1.110 ip6_forward.c
--- netinet6/ip6_forward.c      1 Jun 2023 09:05:33 -0000       1.110
+++ netinet6/ip6_forward.c      12 Jun 2023 13:34:03 -0000
@@ -319,37 +319,32 @@ reroute:
        }
 #endif
 
-       error = tcp_if_output_tso(ifp, &m, sin6tosa(sin6), rt, IFCAP_TSOv6,
-           ifp->if_mtu);
-       if (error || m == NULL)
-               goto freecopy;
-
        /* Check the size after pf_test to give pf a chance to refragment. */
-       if (m->m_pkthdr.len > ifp->if_mtu) {
-               if (mcopy)
-                       icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0,
-                           ifp->if_mtu);
-               m_freem(m);
-               goto out;
+       if (m->m_pkthdr.len <= ifp->if_mtu) {
+               in6_proto_cksum_out(m, ifp);
+               error = ifp->if_output(ifp, m, sin6tosa(sin6), rt);
+               if (error)
+                       ip6stat_inc(ip6s_cantforward);
+               else
+                       ip6stat_inc(ip6s_forward);
+               goto senderr;
        }
 
-       in6_proto_cksum_out(m, ifp);
-       error = ifp->if_output(ifp, m, sin6tosa(sin6), rt);
-       if (error) {
+       error = tcp_if_output_tso(ifp, &m, sin6tosa(sin6), rt, IFCAP_TSOv6,
+           ifp->if_mtu);
+       if (error)
                ip6stat_inc(ip6s_cantforward);
-       } else {
+       else
                ip6stat_inc(ip6s_forward);
-               if (type)
-                       ip6stat_inc(ip6s_redirectsent);
-               else {
-                       if (mcopy)
-                               goto freecopy;
-               }
-       }
+       if (error || m == NULL)
+               goto senderr;
+
+       if (mcopy != NULL)
+               icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
+       m_freem(m);
+       goto out;
 
-#if NPF > 0 || defined(IPSEC)
 senderr:
-#endif
        if (mcopy == NULL)
                goto out;
 
@@ -357,6 +352,7 @@ senderr:
        case 0:
                if (type == ND_REDIRECT) {
                        icmp6_redirect_output(mcopy, rt);
+                       ip6stat_inc(ip6s_redirectsent);
                        goto out;
                }
                goto freecopy;
Index: netinet6/ip6_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.277
diff -u -p -r1.277 ip6_output.c
--- netinet6/ip6_output.c       22 May 2023 16:08:34 -0000      1.277
+++ netinet6/ip6_output.c       12 Jun 2023 13:34:03 -0000
@@ -688,7 +688,7 @@ reroute:
                dontfrag = 0;
        if (dontfrag &&                                 /* case 2-b */
            (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) ?
-           m->m_pkthdr.csum_flags : tlen) > ifp->if_mtu) {
+           m->m_pkthdr.ph_mss : tlen) > ifp->if_mtu) {
 #ifdef IPSEC
                if (ip_mtudisc)
                        ipsec_adjust_mtu(m, mtu);

Reply via email to