Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netinet Add IPv4/TCP hooks for TCP Segment Offload on tr...



details:   https://anonhg.NetBSD.org/src/rev/1d082611fe2a
branches:  trunk
changeset: 574604:1d082611fe2a
user:      matt <matt%NetBSD.org@localhost>
date:      Sun Mar 06 00:35:07 2005 +0000

description:
Add IPv4/TCP hooks for TCP Segment Offload on transmit.

diffstat:

 sys/netinet/ip_output.c  |  22 ++++++++++++--
 sys/netinet/tcp_output.c |  70 ++++++++++++++++++++++++++++++++++-------------
 2 files changed, 69 insertions(+), 23 deletions(-)

diffs (186 lines):

diff -r fd9f631fd7cd -r 1d082611fe2a sys/netinet/ip_output.c
--- a/sys/netinet/ip_output.c   Sun Mar 06 00:13:36 2005 +0000
+++ b/sys/netinet/ip_output.c   Sun Mar 06 00:35:07 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_output.c,v 1.145 2005/03/05 02:46:38 briggs Exp $   */
+/*     $NetBSD: ip_output.c,v 1.146 2005/03/06 00:35:07 matt Exp $     */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -98,7 +98,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.145 2005/03/05 02:46:38 briggs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.146 2005/03/06 00:35:07 matt Exp $");
 
 #include "opt_pfil_hooks.h"
 #include "opt_inet.h"
@@ -758,6 +758,8 @@
        hlen = ip->ip_hl << 2;
 #endif /* PFIL_HOOKS */
 
+       m->m_pkthdr.csum_data |= hlen << 16;
+
 #if IFA_STATS
        /*
         * search for the source address structure to
@@ -766,6 +768,19 @@
        INADDR_TO_IA(ip->ip_src, ia);
 #endif
 
+       if (m->m_pkthdr.csum_flags & M_CSUM_TSOv4) {
+#if IFA_STATS
+               if (ia)
+                       ia->ia_ifa.ifa_data.ifad_outbytes += ip_len;
+#endif
+#ifdef IPSEC
+               /* clean ipsec history once it goes out of the node */
+               ipsec_delaux(m);
+#endif
+               error = (*ifp->if_output)(ifp, m, sintosa(dst), ro->ro_rt);
+               goto done;
+       }
+
        /* Maybe skip checksums on loopback interfaces. */
        if (__predict_true(!(ifp->if_flags & IFF_LOOPBACK) ||
                           ip_do_loopback_cksum))
@@ -799,8 +814,7 @@
                if (sw_csum & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
                        in_delayed_cksum(m);
                        m->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
-               } else
-                       m->m_pkthdr.csum_data |= hlen << 16;
+               }
 
 #ifdef IPSEC
                /* clean ipsec history once it goes out of the node */
diff -r fd9f631fd7cd -r 1d082611fe2a sys/netinet/tcp_output.c
--- a/sys/netinet/tcp_output.c  Sun Mar 06 00:13:36 2005 +0000
+++ b/sys/netinet/tcp_output.c  Sun Mar 06 00:35:07 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_output.c,v 1.119 2005/03/02 10:20:18 mycroft Exp $ */
+/*     $NetBSD: tcp_output.c,v 1.120 2005/03/06 00:35:07 matt Exp $    */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -140,7 +140,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.119 2005/03/02 10:20:18 mycroft Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.120 2005/03/06 00:35:07 matt Exp $");
 
 #include "opt_inet.h"
 #include "opt_ipsec.h"
@@ -556,6 +556,7 @@
        int maxburst = TCP_MAXBURST;
        int af;         /* address family on the wire */
        int iphdrlen;
+       int use_tso;
        int sack_rxmit;
        int sack_bytes_rxmt;
        struct sackhole *p;
@@ -608,6 +609,21 @@
        idle = (tp->snd_max == tp->snd_una);
 
        /*
+        * Determine if we can use TCP segmentation offload:
+        * - If we're using IPv4
+        * - If there is not an IPsec policy that prevents it
+        * - If the interface can do it
+        */
+       use_tso = tp->t_inpcb != NULL &&
+#if defined(IPSEC) || defined(FAST_IPSEC)
+                 IPSEC_PCB_SKIP_IPSEC(tp->t_inpcb->inp_sp,
+                                      IPSEC_DIR_OUTBOUND) &&
+#endif
+                 tp->t_inpcb->inp_route.ro_rt != NULL &&
+                 (tp->t_inpcb->inp_route.ro_rt->rt_ifp->if_capenable &
+                  IFCAP_TSOv4) != 0;
+
+       /*
         * Restart Window computation.  From draft-floyd-incr-init-win-03:
         *
         *      Optionally, a TCP MAY set the restart window to the
@@ -828,10 +844,19 @@
                }
        }
        if (len > txsegsize) {
-               len = txsegsize;
+               if (use_tso) {
+                       /*
+                        * Truncate TSO transfers to IP_MAXPACKET, and make
+                        * sure that we send equal size transfers down the
+                        * stack (rather than big-small-big-small-...).
+                        */
+                       len = (min(len, IP_MAXPACKET) / txsegsize) * txsegsize;
+               } else
+                       len = txsegsize;
                flags &= ~TH_FIN;
                sendalot = 1;
-       }
+       } else
+               use_tso = 0;
        if (sack_rxmit) {
                if (SEQ_LT(p->rxmit + len, tp->snd_una + so->so_snd.sb_cc))
                        flags &= ~TH_FIN;
@@ -850,7 +875,7 @@
         * to send into a small window), then must resend.
         */
        if (len) {
-               if (len == txsegsize)
+               if (len >= txsegsize)
                        goto send;
                if ((so->so_state & SS_MORETOCOME) == 0 &&
                    ((idle || tp->t_flags & TF_NODELAY) &&
@@ -1083,8 +1108,10 @@
        hdrlen += optlen;
 
 #ifdef DIAGNOSTIC
-       if (len > txsegsize)
+       if (!use_tso && len > txsegsize)
                panic("tcp data to be sent is larger than segment");
+       else if (use_tso && len > IP_MAXPACKET)
+               panic("tcp data to be sent is larger than max TSO size");
        if (max_linkhdr + hdrlen > MCLBYTES)
                panic("tcphdr too big");
 #endif
@@ -1255,19 +1282,24 @@
        switch (af) {
 #ifdef INET
        case AF_INET:
-               if (__predict_true(ro->ro_rt == NULL ||
-                                  !(ro->ro_rt->rt_ifp->if_flags &
-                                    IFF_LOOPBACK) ||
-                                  tcp_do_loopback_cksum))
-                       m->m_pkthdr.csum_flags = M_CSUM_TCPv4;
-               else
-                       m->m_pkthdr.csum_flags = 0;
-               m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
-               if (len + optlen) {
-                       /* Fixup the pseudo-header checksum. */
-                       /* XXXJRT Not IP Jumbogram safe. */
-                       th->th_sum = in_cksum_addword(th->th_sum,
-                           htons((u_int16_t) (len + optlen)));
+               if (use_tso) {
+                       m->m_pkthdr.segsz = txsegsize;
+                       m->m_pkthdr.csum_flags |= M_CSUM_TSOv4;
+               } else {
+                       if (__predict_true(ro->ro_rt == NULL ||
+                                          !(ro->ro_rt->rt_ifp->if_flags &
+                                            IFF_LOOPBACK) ||
+                                          tcp_do_loopback_cksum))
+                               m->m_pkthdr.csum_flags = M_CSUM_TCPv4;
+                       else
+                               m->m_pkthdr.csum_flags = 0;
+                       m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+                       if (len + optlen) {
+                               /* Fixup the pseudo-header checksum. */
+                               /* XXXJRT Not IP Jumbogram safe. */
+                               th->th_sum = in_cksum_addword(th->th_sum,
+                                   htons((u_int16_t) (len + optlen)));
+                       }
                }
                break;
 #endif



Home | Main Index | Thread Index | Old Index