Source-Changes-HG archive

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

[src/trunk]: src/sys ipv6 tx checksum offloading. reviewed by Jason Thorpe.



details:   https://anonhg.NetBSD.org/src/rev/384775653b88
branches:  trunk
changeset: 583515:384775653b88
user:      yamt <yamt%NetBSD.org@localhost>
date:      Wed Aug 10 12:58:37 2005 +0000

description:
ipv6 tx checksum offloading.  reviewed by Jason Thorpe.

diffstat:

 sys/netinet/tcp_output.c   |  19 ++------------
 sys/netinet6/in6.h         |   3 +-
 sys/netinet6/ip6_output.c  |  57 ++++++++++++++++++++++++++++++++++++++++++++-
 sys/netinet6/udp6_output.c |  12 ++++----
 sys/sys/mbuf.h             |  15 +++++++++++-
 5 files changed, 80 insertions(+), 26 deletions(-)

diffs (253 lines):

diff -r 19e11643504f -r 384775653b88 sys/netinet/tcp_output.c
--- a/sys/netinet/tcp_output.c  Wed Aug 10 12:46:24 2005 +0000
+++ b/sys/netinet/tcp_output.c  Wed Aug 10 12:58:37 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_output.c,v 1.137 2005/07/19 17:00:02 christos Exp $        */
+/*     $NetBSD: tcp_output.c,v 1.138 2005/08/10 12:58:37 yamt 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.137 2005/07/19 17:00:02 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.138 2005/08/10 12:58:37 yamt Exp $");
 
 #include "opt_inet.h"
 #include "opt_ipsec.h"
@@ -1344,27 +1344,14 @@
 #endif
 #ifdef INET6
        case AF_INET6:
-               /*
-                * XXX Actually delaying the checksum is Hard
-                * XXX (well, maybe not for Itojun, but it is
-                * XXX for me), but we can still take advantage
-                * XXX of the cached pseudo-header checksum.
-                */
-               /* equals to hdrlen + len */
-               m->m_pkthdr.len = sizeof(struct ip6_hdr)
-                       + sizeof(struct tcphdr) + optlen + len;
-#ifdef notyet
+               m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
                m->m_pkthdr.csum_flags = M_CSUM_TCPv6;
-               m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
-#endif
                if (len + optlen) {
                        /* Fixup the pseudo-header checksum. */
                        /* XXXJRT: Not IPv6 Jumbogram safe. */
                        th->th_sum = in_cksum_addword(th->th_sum,
                            htons((u_int16_t) (len + optlen)));
                }
-               th->th_sum = in6_cksum(m, 0, sizeof(struct ip6_hdr),
-                   sizeof(struct tcphdr) + optlen + len);
                break;
 #endif
        }
diff -r 19e11643504f -r 384775653b88 sys/netinet6/in6.h
--- a/sys/netinet6/in6.h        Wed Aug 10 12:46:24 2005 +0000
+++ b/sys/netinet6/in6.h        Wed Aug 10 12:58:37 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6.h,v 1.45 2004/06/11 04:10:10 itojun Exp $  */
+/*     $NetBSD: in6.h,v 1.46 2005/08/10 12:58:37 yamt Exp $    */
 /*     $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $    */
 
 /*
@@ -647,6 +647,7 @@
 }
 
 int    in6_cksum __P((struct mbuf *, u_int8_t, u_int32_t, u_int32_t));
+void   in6_delayed_cksum __P((struct mbuf *));
 int    in6_localaddr __P((struct in6_addr *));
 int    in6_addrscope __P((struct in6_addr *));
 struct in6_ifaddr *in6_ifawithscope __P((struct ifnet *, struct in6_addr *));
diff -r 19e11643504f -r 384775653b88 sys/netinet6/ip6_output.c
--- a/sys/netinet6/ip6_output.c Wed Aug 10 12:46:24 2005 +0000
+++ b/sys/netinet6/ip6_output.c Wed Aug 10 12:58:37 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip6_output.c,v 1.88 2005/02/28 09:27:07 itojun Exp $   */
+/*     $NetBSD: ip6_output.c,v 1.89 2005/08/10 12:58:37 yamt Exp $     */
 /*     $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $    */
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.88 2005/02/28 09:27:07 itojun Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.89 2005/08/10 12:58:37 yamt Exp $");
 
 #include "opt_inet.h"
 #include "opt_ipsec.h"
@@ -167,6 +167,8 @@
        ip6 = mtod(m, struct ip6_hdr *);
 #endif /* IPSEC */
 
+       M_CSUM_DATA_IPv6_HL_SET(m->m_pkthdr.csum_data, sizeof(struct ip6_hdr));
+
 #define MAKE_EXTHDR(hp, mp)                                            \
     do {                                                               \
        if (hp) {                                                       \
@@ -248,6 +250,12 @@
   skippolicycheck:;
 #endif /* IPSEC */
 
+       if (needipsec &&
+           (m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0) {
+               in6_delayed_cksum(m);
+               m->m_pkthdr.csum_flags &= ~(M_CSUM_UDPv6|M_CSUM_TCPv6);
+       }
+
        /*
         * Calculate the total length of the extension header chain.
         * Keep the length of the unfragmentable part for fragmentation.
@@ -294,6 +302,7 @@
                ip6 = mtod(m, struct ip6_hdr *);
                if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0)
                        goto freehdrs;
+               optlen += 8; /* XXX JUMBOOPTLEN */
                ip6->ip6_plen = 0;
        } else
                ip6->ip6_plen = htons(plen);
@@ -353,6 +362,9 @@
                MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp,
                    IPPROTO_ROUTING);
 
+               M_CSUM_DATA_IPv6_HL_SET(m->m_pkthdr.csum_data,
+                   sizeof(struct ip6_hdr) + optlen);
+
 #ifdef IPSEC
                if (!needipsec)
                        goto skip_ipsec2;
@@ -868,6 +880,7 @@
         */
        if (dontfrag || (!alwaysfrag && tlen <= mtu)) { /* case 1-a and 2-a */
                struct in6_ifaddr *ia6;
+               int sw_csum;
 
                ip6 = mtod(m, struct ip6_hdr *);
                ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
@@ -879,6 +892,13 @@
                /* clean ipsec history once it goes out of the node */
                ipsec_delaux(m);
 #endif
+
+               sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_csum_flags_tx;
+               if ((sw_csum & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0) {
+                       in6_delayed_cksum(m);
+                       m->m_pkthdr.csum_flags &= ~(M_CSUM_UDPv6|M_CSUM_TCPv6);
+               }
+
                error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
                goto done;
        }
@@ -947,6 +967,12 @@
                        ip6->ip6_nxt = IPPROTO_FRAGMENT;
                }
 
+               if ((m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6))
+                   != 0) {
+                       in6_delayed_cksum(m);
+                       m->m_pkthdr.csum_flags &= ~(M_CSUM_UDPv6|M_CSUM_TCPv6);
+               }
+
                /*
                 * Loop through length of segment after first fragment,
                 * make new header and copy data of each part and link onto
@@ -1092,6 +1118,33 @@
 }
 
 /*
+ * Process a delayed payload checksum calculation.
+ */
+void
+in6_delayed_cksum(struct mbuf *m)
+{
+       uint16_t csum, offset;
+
+       KASSERT((m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0);
+       KASSERT((~m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0);
+       KASSERT((m->m_pkthdr.csum_flags
+           & (M_CSUM_UDPv4|M_CSUM_TCPv4|M_CSUM_TSOv4)) == 0);
+
+       offset = M_CSUM_DATA_IPv6_HL(m->m_pkthdr.csum_data);
+       csum = in6_cksum(m, 0, offset, m->m_pkthdr.len - offset);
+       if (csum == 0 && (m->m_pkthdr.csum_flags & M_CSUM_UDPv6) != 0) {
+               csum = 0xffff;
+       }
+
+       offset += M_CSUM_DATA_IPv6_OFFSET(m->m_pkthdr.csum_data);
+       if ((offset + sizeof(csum)) > m->m_len) {
+               m_copyback(m, offset, sizeof(csum), &csum);
+       } else {
+               *(uint16_t *)(mtod(m, caddr_t) + offset) = csum;
+       }
+}
+
+/*
  * Insert jumbo payload option.
  */
 static int
diff -r 19e11643504f -r 384775653b88 sys/netinet6/udp6_output.c
--- a/sys/netinet6/udp6_output.c        Wed Aug 10 12:46:24 2005 +0000
+++ b/sys/netinet6/udp6_output.c        Wed Aug 10 12:58:37 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: udp6_output.c,v 1.20 2005/04/22 11:56:33 yamt Exp $    */
+/*     $NetBSD: udp6_output.c,v 1.21 2005/08/10 12:58:37 yamt Exp $    */
 /*     $KAME: udp6_output.c,v 1.43 2001/10/15 09:19:52 itojun Exp $    */
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.20 2005/04/22 11:56:33 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.21 2005/08/10 12:58:37 yamt Exp $");
 
 #include "opt_inet.h"
 
@@ -330,10 +330,10 @@
                ip6->ip6_src    = *laddr;
                ip6->ip6_dst    = *faddr;
 
-               if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP,
-                   sizeof(struct ip6_hdr), plen)) == 0) {
-                       udp6->uh_sum = 0xffff;
-               }
+               udp6->uh_sum = in6_cksum_phdr(laddr, faddr,
+                   htonl(plen), htonl(IPPROTO_UDP));
+               m->m_pkthdr.csum_flags = M_CSUM_UDPv6;
+               m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
 
                if (in6p->in6p_flags & IN6P_MINMTU)
                        flags |= IPV6_MINMTU;
diff -r 19e11643504f -r 384775653b88 sys/sys/mbuf.h
--- a/sys/sys/mbuf.h    Wed Aug 10 12:46:24 2005 +0000
+++ b/sys/sys/mbuf.h    Wed Aug 10 12:58:37 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mbuf.h,v 1.113 2005/07/26 22:52:48 dyoung Exp $        */
+/*     $NetBSD: mbuf.h,v 1.114 2005/08/10 12:58:37 yamt Exp $  */
 
 /*-
  * Copyright (c) 1996, 1997, 1999, 2001 The NetBSD Foundation, Inc.
@@ -189,6 +189,19 @@
 #define        M_CSUM_DATA_IPv4_OFFSET(x)      ((x) & 0xffff)
 
 /*
+ * Macros for M_CSUM_TCPv6 and M_CSUM_UDPv6
+ *
+ * M_CSUM_DATA_IPv6_HL: length of ip6_hdr + ext header.
+ * ie. offset of UDP/TCP header in the packet.
+ *
+ * M_CSUM_DATA_IPv6_OFFSET: offset of the checksum field in UDP/TCP header. 
+ */
+
+#define        M_CSUM_DATA_IPv6_HL(x)          ((x) >> 16)
+#define        M_CSUM_DATA_IPv6_HL_SET(x, v)   (x) = ((x) & 0xffff) | ((v) << 16)
+#define        M_CSUM_DATA_IPv6_OFFSET(x)      ((x) & 0xffff)
+
+/*
  * Max # of pages we can attach to m_ext.  This is carefully chosen
  * to be able to handle SOSEND_LOAN_CHUNK with our minimum sized page.
  */



Home | Main Index | Thread Index | Old Index