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