Source-Changes-HG archive

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

[src/trunk]: src/sys Add routines to calculate a checkesum if the driver conc...



details:   https://anonhg.NetBSD.org/src/rev/5d1a1484b607
branches:  trunk
changeset: 759508:5d1a1484b607
user:      matt <matt%NetBSD.org@localhost>
date:      Sat Dec 11 22:37:46 2010 +0000

description:
Add routines to calculate a checkesum if the driver concludes that the
h/w can't do it.

diffstat:

 sys/netinet/in_offload.c   |  58 ++++++++++++++++++++++++++++++++++++++++++++-
 sys/netinet/in_offload.h   |   3 +-
 sys/netinet/ip_input.c     |   6 +++-
 sys/netinet6/in6_offload.c |  38 ++++++++++++++++++++++++++++-
 sys/netinet6/in6_offload.h |   3 +-
 5 files changed, 100 insertions(+), 8 deletions(-)

diffs (193 lines):

diff -r 2b6d8d3adf35 -r 5d1a1484b607 sys/netinet/in_offload.c
--- a/sys/netinet/in_offload.c  Sat Dec 11 22:34:03 2010 +0000
+++ b/sys/netinet/in_offload.c  Sat Dec 11 22:37:46 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in_offload.c,v 1.2 2007/04/24 23:43:50 dyoung Exp $    */
+/*     $NetBSD: in_offload.c,v 1.3 2010/12/11 22:37:46 matt Exp $      */
 
 /*-
  * Copyright (c)2005, 2006 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in_offload.c,v 1.2 2007/04/24 23:43:50 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in_offload.c,v 1.3 2010/12/11 22:37:46 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/mbuf.h>
@@ -195,3 +195,57 @@
 
        return error;
 }
+
+void
+ip_undefer_csum(struct mbuf *m, size_t hdrlen, int csum_flags)
+{
+       KASSERT(m->m_flags & M_PKTHDR);
+       KASSERT((m->m_pkthdr.csum_flags & csum_flags) == csum_flags);
+       uint16_t csum;
+       uint16_t ip_len;
+       uint16_t *csump;
+       size_t iphdrlen;
+
+       if (__predict_true(hdrlen + sizeof(struct ip) <= m->m_len)) {
+               struct ip *ip = (struct ip *)(mtod(m, uint8_t *) + hdrlen);
+               ip_len = ip->ip_len;
+               iphdrlen = ip->ip_hl << 2;
+               csump = &ip->ip_sum;
+       } else {
+               uint8_t ip_vhl;
+               const size_t ip_len_offset = hdrlen + offsetof(struct ip, ip_len);
+               m_copydata(m, hdrlen, sizeof(ip_vhl), &ip_vhl);
+               m_copydata(m, ip_len_offset, sizeof(ip_len), &ip_len);
+               iphdrlen = (ip_vhl & 0x0f) << 2;
+               csump = NULL;
+       }
+
+       if (csum_flags & M_CSUM_IPv4) {
+               const size_t offset = hdrlen + offsetof(struct ip, ip_sum);
+               csum = in4_cksum(m, 0, hdrlen, iphdrlen);
+               if (csump != NULL) {
+                       *csump = csum;
+               } else {
+                       m_copyback(m, offset, sizeof(uint16_t), &csum);
+               }
+       }
+
+       if (csum_flags & (M_CSUM_UDPv4|M_CSUM_TCPv4)) {
+               size_t l4offset = hdrlen
+                   + M_CSUM_DATA_IPv4_IPHL(m->m_pkthdr.csum_data);
+
+               csum = in4_cksum(m, 0, hdrlen + l4offset, ip_len - l4offset);
+               if (csum == 0 && (csum_flags & M_CSUM_UDPv4) != 0)
+                       csum = 0xffff;
+
+               l4offset += M_CSUM_DATA_IPv4_OFFSET(m->m_pkthdr.csum_data);
+
+               if (__predict_true(l4offset + sizeof(uint16_t) <= m->m_len)) {
+                       *(uint16_t *)(mtod(m, char *) + l4offset) = csum;
+               } else {
+                       m_copyback(m, l4offset, sizeof(csum), (void *) &csum);
+               }
+       }
+
+       m->m_pkthdr.csum_flags ^= csum_flags;
+}
diff -r 2b6d8d3adf35 -r 5d1a1484b607 sys/netinet/in_offload.h
--- a/sys/netinet/in_offload.h  Sat Dec 11 22:34:03 2010 +0000
+++ b/sys/netinet/in_offload.h  Sat Dec 11 22:37:46 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in_offload.h,v 1.6 2007/11/28 04:14:11 dyoung Exp $    */
+/*     $NetBSD: in_offload.h,v 1.7 2010/12/11 22:37:46 matt Exp $      */
 
 /*-
  * Copyright (c)2005, 2006 YAMAMOTO Takashi,
@@ -36,6 +36,7 @@
 int tcp4_segment(struct mbuf *, int (*)(void *, struct mbuf *), void *);
 int ip_tso_output(struct ifnet *, struct mbuf *, const struct sockaddr *,
     struct rtentry *);
+void ip_undefer_csum(struct mbuf *, size_t, int);        
 
 /*
  * offloading related sysctl variables.
diff -r 2b6d8d3adf35 -r 5d1a1484b607 sys/netinet/ip_input.c
--- a/sys/netinet/ip_input.c    Sat Dec 11 22:34:03 2010 +0000
+++ b/sys/netinet/ip_input.c    Sat Dec 11 22:37:46 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_input.c,v 1.291 2010/11/05 01:35:57 rmind Exp $     */
+/*     $NetBSD: ip_input.c,v 1.292 2010/12/11 22:37:46 matt Exp $      */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.291 2010/11/05 01:35:57 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.292 2010/12/11 22:37:46 matt Exp $");
 
 #include "opt_inet.h"
 #include "opt_compat_netbsd.h"
@@ -390,7 +390,9 @@
                IF_DEQUEUE(&lcl_intrq, m);
                if (m == NULL)
                        break;
+               KERNEL_UNLOCK_ONE(NULL);
                ip_input(m);
+               KERNEL_LOCK(1, NULL);
        }
        mutex_exit(softnet_lock);
 }
diff -r 2b6d8d3adf35 -r 5d1a1484b607 sys/netinet6/in6_offload.c
--- a/sys/netinet6/in6_offload.c        Sat Dec 11 22:34:03 2010 +0000
+++ b/sys/netinet6/in6_offload.c        Sat Dec 11 22:37:46 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6_offload.c,v 1.4 2007/05/02 20:40:26 dyoung Exp $   */
+/*     $NetBSD: in6_offload.c,v 1.5 2010/12/11 22:37:47 matt Exp $     */
 
 /*-
  * Copyright (c)2006 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_offload.c,v 1.4 2007/05/02 20:40:26 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_offload.c,v 1.5 2010/12/11 22:37:47 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/mbuf.h>
@@ -191,3 +191,37 @@
 
        return error;
 }
+
+void
+ip6_undefer_csum(struct mbuf *m, size_t hdrlen, int csum_flags)
+{
+       KASSERT(m->m_flags & M_PKTHDR);
+       KASSERT((m->m_pkthdr.csum_flags & csum_flags) == csum_flags);
+       KASSERT(csum_flags == M_CSUM_UDPv6 || csum_flags == M_CSUM_TCPv6);
+
+       const size_t ip6_plen_offset = hdrlen + offsetof(struct ip6_hdr, ip6_plen);
+       uint16_t plen;
+
+       if (__predict_true(hdrlen + sizeof(struct ip6_hdr) <= m->m_len)) {
+               plen = *(uint16_t *)(mtod(m, char *) + ip6_plen_offset);
+       } else {
+               m_copydata(m, ip6_plen_offset, sizeof(plen), &plen);
+       }
+
+       const size_t l4hdroff = M_CSUM_DATA_IPv6_HL(m->m_pkthdr.csum_data);
+       size_t l4offset = hdrlen + l4hdroff;
+       uint16_t csum = in6_cksum(m, 0, l4offset, plen - l4hdroff);
+
+       if (csum == 0 && (csum_flags & M_CSUM_UDPv6) != 0)
+               csum = 0xffff;
+
+       l4offset += M_CSUM_DATA_IPv6_OFFSET(m->m_pkthdr.csum_data);
+
+       if (__predict_true((l4offset + sizeof(uint16_t)) <= m->m_len)) {
+               *(uint16_t *)(mtod(m, char *) + l4offset) = csum;
+       } else {
+               m_copyback(m, l4offset, sizeof(csum), (void *) &csum);
+       }
+
+       m->m_pkthdr.csum_flags ^= csum_flags;
+}
diff -r 2b6d8d3adf35 -r 5d1a1484b607 sys/netinet6/in6_offload.h
--- a/sys/netinet6/in6_offload.h        Sat Dec 11 22:34:03 2010 +0000
+++ b/sys/netinet6/in6_offload.h        Sat Dec 11 22:37:46 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6_offload.h,v 1.5 2007/05/02 20:40:26 dyoung Exp $   */
+/*     $NetBSD: in6_offload.h,v 1.6 2010/12/11 22:37:47 matt Exp $     */
 
 /*-
  * Copyright (c)2005, 2006 YAMAMOTO Takashi,
@@ -36,5 +36,6 @@
 int tcp6_segment(struct mbuf *, int (*)(void *, struct mbuf *), void *);
 int ip6_tso_output(struct ifnet *, struct ifnet *, struct mbuf *,
     const struct sockaddr_in6 *, struct rtentry *);
+void ip6_undefer_csum(struct mbuf *, size_t, int);
 
 #endif /* !defined(_NETINET6_IN6_OFFLOAD_H_) */



Home | Main Index | Thread Index | Old Index