On Fri, Jun 16, 2023 at 12:06:08PM +0200, Alexander Bluhm wrote:
> On Mon, Jun 12, 2023 at 03:46:28PM +0200, Alexander Bluhm wrote:
> > 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.
>
> jan@ pointed out that reordering TSO in ip6 forward breaks path MTU
> discovery. So lets only fix the forward counters, icmp6 packet too
> big and icmp6 redirect.
>
> First try to send with TSO. The goto senderr handles icmp6 redirect
> and other errors.
>
> If TSO is not necessary and the interface MTU fits, just send the
> packet. Again goto senderr handles icmp6.
>
> Finally care about icmp6 packet too big.
Works fine in my setup.
> ok?
ok jan@
> 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 16 Jun 2023 08:55:43 -0000
> @@ -321,35 +321,30 @@ reroute:
>
> error = tcp_if_output_tso(ifp, &m, sin6tosa(sin6), rt, IFCAP_TSOv6,
> ifp->if_mtu);
> + if (error)
> + ip6stat_inc(ip6s_cantforward);
> + else if (m == NULL)
> + ip6stat_inc(ip6s_forward);
> if (error || m == NULL)
> - goto freecopy;
> + goto senderr;
>
> /* 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) {
> - ip6stat_inc(ip6s_cantforward);
> - } else {
> - ip6stat_inc(ip6s_forward);
> - if (type)
> - ip6stat_inc(ip6s_redirectsent);
> - else {
> - if (mcopy)
> - goto freecopy;
> - }
> - }
> + 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;
>