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