On Mon, Jul 03, 2023 at 08:04:11PM +0300, Alexander Bluhm wrote:
> As final step before making LRO (Large Receive Offload) the default,
> we have to fix path MTU discovery when forwarding.
> 
> The drivers, currently ix(4) and lo(4) only, record an upper bound
> of the size of the original packets in ph_mss.  When sending we
> must chop the packets with TSO (TCP Segmentation Offload) to that
> size.  That means we have to call tcp_if_output_tso() before
> ifp->if_output().  I have put that logic into if_output_tso() to
> avoid code duplication.
> 
> ok?

I like the idea of this commit.  Some comments below.

Thanks,
Jan

> Index: net/if.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/if.c,v
> retrieving revision 1.702
> diff -u -p -r1.702 if.c
> --- net/if.c  2 Jul 2023 19:59:15 -0000       1.702
> +++ net/if.c  3 Jul 2023 10:28:30 -0000
> @@ -109,6 +109,9 @@
>  #include <netinet/tcp.h>
>  #include <netinet/tcp_timer.h>
>  #include <netinet/tcp_var.h>

I think is a merge bug, isn't it?

> +#include <netinet/tcp.h>
> +#include <netinet/tcp_timer.h>
> +#include <netinet/tcp_var.h>

> @@ -883,6 +886,57 @@ if_output_ml(struct ifnet *ifp, struct m
>               ml_purge(ml);
>  
>       return error;
> +}
> +
> +int
> +if_output_tso(struct ifnet *ifp, struct mbuf **mp, struct sockaddr *dst,
> +    struct rtentry *rt, u_int mtu)
> +{
> +     uint32_t ifcap;
> +     int error;
> +
> +     switch (dst->sa_family) {
> +     case AF_INET:
> +             ifcap = IFCAP_TSOv4;
> +             break;
> +#ifdef INET6
> +     case AF_INET6:
> +             ifcap = IFCAP_TSOv6;
> +             break;
> +#endif
> +     default:
> +             unhandled_af(dst->sa_family);
> +     }
> +
> +     /*
> +      * Try to send with TSO first.  When forwarding LRO may set
> +      * maximium segment size in mbuf header.  Chop TCP segment
> +      * even if it would fit interface MTU to preserve maximum
> +      * path MTU.
> +      */
> +     error = tcp_if_output_tso(ifp, mp, dst, rt, ifcap, mtu);
> +     if (error || *mp == NULL)
> +             return error;
> +
> +     if ((*mp)->m_pkthdr.len <= mtu) {

I may miss something but...

Couldn't you move the *_cksum_out() calls above the upper
tcp_if_output_tso() call?  And than remove the *_cksum_out() calls
inside of tcp_if_output_tso()?

Thus, there is just one place where we call them.

> +             switch (dst->sa_family) {
> +             case AF_INET:
> +                     in_hdr_cksum_out(*mp, ifp);
> +                     in_proto_cksum_out(*mp, ifp);
> +                     break;
> +#ifdef INET6
> +             case AF_INET6:
> +                     in6_proto_cksum_out(*mp, ifp);
> +                     break;
> +#endif
> +             }
> +             error = ifp->if_output(ifp, *mp, dst, rt);
> +             *mp = NULL;
> +             return error;
> +     }
> +
> +     /* mp still contains mbuf that has to be fragmented or dropped. */
> +     return 0;
>  }

Reply via email to