On Thu, Jul 06, 2023 at 10:19:21PM +0300, Alexander Bluhm wrote:
> On Thu, Jul 06, 2023 at 08:49:03PM +0200, Jan Klemkow wrote:
> > > @@ -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>
> 
> Right.
> 
> > > + 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
> 
> There is the case in tcp_if_output_tso() where we call tcp_chopper().
> Then checksum has to be calcualted after chopping.  If I do it
> always before tcp_if_output_tso(), we may caluclate it twice.  Once
> for the large packet and once for the small ones.
> 
> New diff without duplicate includes.

tested with v4/v6, direct and forwarding.

ok jan@

> Index: net/if.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/if.c,v
> retrieving revision 1.704
> diff -u -p -r1.704 if.c
> --- net/if.c  6 Jul 2023 04:55:04 -0000       1.704
> +++ net/if.c  6 Jul 2023 19:15:00 -0000
> @@ -886,6 +886,57 @@ if_output_ml(struct ifnet *ifp, struct m
>  }
>  
>  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) {
> +             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;
> +}
> +
> +int
>  if_output_mq(struct ifnet *ifp, struct mbuf_queue *mq, unsigned int *total,
>      struct sockaddr *dst, struct rtentry *rt)
>  {
> Index: net/if_var.h
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/if_var.h,v
> retrieving revision 1.128
> diff -u -p -r1.128 if_var.h
> --- net/if_var.h      28 Jun 2023 11:49:49 -0000      1.128
> +++ net/if_var.h      6 Jul 2023 19:12:39 -0000
> @@ -329,6 +329,8 @@ int       if_output_ml(struct ifnet *, struct 
>           struct sockaddr *, struct rtentry *);
>  int  if_output_mq(struct ifnet *, struct mbuf_queue *, unsigned int *,
>           struct sockaddr *, struct rtentry *);
> +int  if_output_tso(struct ifnet *, struct mbuf **, struct sockaddr *,
> +         struct rtentry *, u_int);
>  int  if_output_local(struct ifnet *, struct mbuf *, sa_family_t);
>  void if_rtrequest_dummy(struct ifnet *, int, struct rtentry *);
>  void p2p_rtrequest(struct ifnet *, int, struct rtentry *);
> Index: net/pf.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
> retrieving revision 1.1182
> diff -u -p -r1.1182 pf.c
> --- net/pf.c  6 Jul 2023 04:55:05 -0000       1.1182
> +++ net/pf.c  6 Jul 2023 19:12:39 -0000
> @@ -6610,15 +6610,8 @@ pf_route(struct pf_pdesc *pd, struct pf_
>               ip = mtod(m0, struct ip *);
>       }
>  
> -     if (ntohs(ip->ip_len) <= ifp->if_mtu) {
> -             in_hdr_cksum_out(m0, ifp);
> -             in_proto_cksum_out(m0, ifp);
> -             ifp->if_output(ifp, m0, sintosa(dst), rt);
> -             goto done;
> -     }
> -
> -     if (tcp_if_output_tso(ifp, &m0, sintosa(dst), rt,
> -         IFCAP_TSOv4, ifp->if_mtu) || m0 == NULL)
> +     if (if_output_tso(ifp, &m0, sintosa(dst), rt, ifp->if_mtu) ||
> +         m0 == NULL)
>               goto done;
>  
>       /*
> @@ -6745,14 +6738,8 @@ pf_route6(struct pf_pdesc *pd, struct pf
>               goto done;
>       }
>  
> -     if (m0->m_pkthdr.len <= ifp->if_mtu) {
> -             in6_proto_cksum_out(m0, ifp);
> -             ifp->if_output(ifp, m0, sin6tosa(dst), rt);
> -             goto done;
> -     }
> -
> -     if (tcp_if_output_tso(ifp, &m0, sin6tosa(dst), rt,
> -         IFCAP_TSOv6, ifp->if_mtu) || m0 == NULL)
> +     if (if_output_tso(ifp, &m0, sin6tosa(dst), rt, ifp->if_mtu) ||
> +         m0 == NULL)
>               goto done;
>  
>       ip6stat_inc(ip6s_cantfrag);
> Index: netinet/ip_output.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v
> retrieving revision 1.389
> diff -u -p -r1.389 ip_output.c
> --- netinet/ip_output.c       4 Jul 2023 10:48:19 -0000       1.389
> +++ netinet/ip_output.c       6 Jul 2023 19:12:39 -0000
> @@ -451,17 +451,9 @@ sendit:
>  #endif
>  
>       /*
> -      * If small enough for interface, can just send directly.
> +      * If TSO or small enough for interface, can just send directly.
>        */
> -     if (ntohs(ip->ip_len) <= mtu) {
> -             in_hdr_cksum_out(m, ifp);
> -             in_proto_cksum_out(m, ifp);
> -             error = ifp->if_output(ifp, m, sintosa(dst), ro->ro_rt);
> -             goto done;
> -     }
> -
> -     error = tcp_if_output_tso(ifp, &m, sintosa(dst), ro->ro_rt,
> -         IFCAP_TSOv4, mtu);
> +     error = if_output_tso(ifp, &m, sintosa(dst), ro->ro_rt, mtu);
>       if (error || m == NULL)
>               goto done;
>  
> Index: netinet6/ip6_forward.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_forward.c,v
> retrieving revision 1.111
> diff -u -p -r1.111 ip6_forward.c
> --- netinet6/ip6_forward.c    16 Jun 2023 19:18:56 -0000      1.111
> +++ netinet6/ip6_forward.c    6 Jul 2023 19:12:39 -0000
> @@ -319,25 +319,13 @@ reroute:
>       }
>  #endif
>  
> -     error = tcp_if_output_tso(ifp, &m, sin6tosa(sin6), rt, IFCAP_TSOv6,
> -         ifp->if_mtu);
> +     error = if_output_tso(ifp, &m, sin6tosa(sin6), rt, ifp->if_mtu);
>       if (error)
>               ip6stat_inc(ip6s_cantforward);
>       else if (m == NULL)
>               ip6stat_inc(ip6s_forward);
>       if (error || m == NULL)
>               goto senderr;
> -
> -     /* Check the size after pf_test to give pf a chance to refragment. */
> -     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;
> -     }
>  
>       if (mcopy != NULL)
>               icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
> Index: netinet6/ip6_output.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v
> retrieving revision 1.278
> diff -u -p -r1.278 ip6_output.c
> --- netinet6/ip6_output.c     13 Jun 2023 19:34:12 -0000      1.278
> +++ netinet6/ip6_output.c     6 Jul 2023 19:15:00 -0000
> @@ -677,7 +677,8 @@ reroute:
>        * 2-a: send as is if tlen <= interface mtu
>        * 2-b: error if tlen > interface mtu
>        */
> -     tlen = m->m_pkthdr.len;
> +     tlen = ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) ?
> +         m->m_pkthdr.ph_mss : m->m_pkthdr.len;
>  
>       if (ISSET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT)) {
>               CLR(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT);
> @@ -686,9 +687,8 @@ reroute:
>               dontfrag = 1;
>       else
>               dontfrag = 0;
> -     if (dontfrag &&                                 /* case 2-b */
> -         (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) ?
> -         m->m_pkthdr.ph_mss : tlen) > ifp->if_mtu) {
> +
> +     if (dontfrag && tlen > ifp->if_mtu) {           /* case 2-b */
>  #ifdef IPSEC
>               if (ip_mtudisc)
>                       ipsec_adjust_mtu(m, mtu);
> @@ -701,15 +701,12 @@ reroute:
>        * transmit packet without fragmentation
>        */
>       if (dontfrag || tlen <= mtu) {                  /* case 1-a and 2-a */
> -             in6_proto_cksum_out(m, ifp);
> -             error = ifp->if_output(ifp, m, sin6tosa(dst), ro->ro_rt);
> -             goto done;
> +             error = if_output_tso(ifp, &m, sin6tosa(dst), ro->ro_rt,
> +                 ifp->if_mtu);
> +             if (error || m == NULL)
> +                     goto done;
> +             goto bad;                               /* should not happen */
>       }
> -
> -     error = tcp_if_output_tso(ifp, &m, sin6tosa(dst), ro->ro_rt,
> -         IFCAP_TSOv6, mtu);
> -     if (error || m == NULL)
> -             goto done;
>  
>       /*
>        * try to fragment the packet.  case 1-b
> 

Reply via email to