Module Name: src
Committed By: matt
Date: Fri Jan 7 03:16:14 UTC 2011
Modified Files:
src/sys/netinet [matt-nb5-pq3]: in_offload.c in_offload.h ip_input.c
src/sys/netinet6 [matt-nb5-pq3]: in6_offload.c in6_offload.h
in6_proto.c
Log Message:
If using hardware checksum offload and the packet can't be h/w checksumed
(for whatever reason, some hardware is stupid) allow the driver to calculate
the checksum instead.
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.2.60.1 src/sys/netinet/in_offload.c
cvs rdiff -u -r1.6 -r1.6.44.1 src/sys/netinet/in_offload.h
cvs rdiff -u -r1.275.4.1 -r1.275.4.1.8.1 src/sys/netinet/ip_input.c
cvs rdiff -u -r1.4 -r1.4.60.1 src/sys/netinet6/in6_offload.c
cvs rdiff -u -r1.5 -r1.5.60.1 src/sys/netinet6/in6_offload.h
cvs rdiff -u -r1.82.12.1 -r1.82.12.1.2.1 src/sys/netinet6/in6_proto.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/netinet/in_offload.c
diff -u src/sys/netinet/in_offload.c:1.2 src/sys/netinet/in_offload.c:1.2.60.1
--- src/sys/netinet/in_offload.c:1.2 Tue Apr 24 23:43:50 2007
+++ src/sys/netinet/in_offload.c Fri Jan 7 03:16:14 2011
@@ -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.2.60.1 2011/01/07 03:16:14 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.2.60.1 2011/01/07 03:16:14 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;
+}
Index: src/sys/netinet/in_offload.h
diff -u src/sys/netinet/in_offload.h:1.6 src/sys/netinet/in_offload.h:1.6.44.1
--- src/sys/netinet/in_offload.h:1.6 Wed Nov 28 04:14:11 2007
+++ src/sys/netinet/in_offload.h Fri Jan 7 03:16:14 2011
@@ -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.6.44.1 2011/01/07 03:16:14 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.
Index: src/sys/netinet/ip_input.c
diff -u src/sys/netinet/ip_input.c:1.275.4.1 src/sys/netinet/ip_input.c:1.275.4.1.8.1
--- src/sys/netinet/ip_input.c:1.275.4.1 Tue Nov 25 04:04:38 2008
+++ src/sys/netinet/ip_input.c Fri Jan 7 03:16:14 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_input.c,v 1.275.4.1 2008/11/25 04:04:38 snj Exp $ */
+/* $NetBSD: ip_input.c,v 1.275.4.1.8.1 2011/01/07 03:16:14 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.275.4.1 2008/11/25 04:04:38 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.275.4.1.8.1 2011/01/07 03:16:14 matt Exp $");
#include "opt_inet.h"
#include "opt_gateway.h"
@@ -473,7 +473,9 @@
splx(s);
if (m == NULL)
break;
+ KERNEL_UNLOCK_ONE(NULL);
ip_input(m);
+ KERNEL_LOCK(1, NULL);
}
KERNEL_UNLOCK_ONE(NULL);
mutex_exit(softnet_lock);
Index: src/sys/netinet6/in6_offload.c
diff -u src/sys/netinet6/in6_offload.c:1.4 src/sys/netinet6/in6_offload.c:1.4.60.1
--- src/sys/netinet6/in6_offload.c:1.4 Wed May 2 20:40:26 2007
+++ src/sys/netinet6/in6_offload.c Fri Jan 7 03:16:14 2011
@@ -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.4.60.1 2011/01/07 03:16:14 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.4.60.1 2011/01/07 03:16:14 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;
+}
Index: src/sys/netinet6/in6_offload.h
diff -u src/sys/netinet6/in6_offload.h:1.5 src/sys/netinet6/in6_offload.h:1.5.60.1
--- src/sys/netinet6/in6_offload.h:1.5 Wed May 2 20:40:26 2007
+++ src/sys/netinet6/in6_offload.h Fri Jan 7 03:16:14 2011
@@ -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.5.60.1 2011/01/07 03:16:14 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_) */
Index: src/sys/netinet6/in6_proto.c
diff -u src/sys/netinet6/in6_proto.c:1.82.12.1 src/sys/netinet6/in6_proto.c:1.82.12.1.2.1
--- src/sys/netinet6/in6_proto.c:1.82.12.1 Sun Nov 21 20:45:39 2010
+++ src/sys/netinet6/in6_proto.c Fri Jan 7 03:16:14 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: in6_proto.c,v 1.82.12.1 2010/11/21 20:45:39 riz Exp $ */
+/* $NetBSD: in6_proto.c,v 1.82.12.1.2.1 2011/01/07 03:16:14 matt Exp $ */
/* $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.82.12.1 2010/11/21 20:45:39 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.82.12.1.2.1 2011/01/07 03:16:14 matt Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@@ -178,7 +178,10 @@
#if defined(IPSEC) || defined(FAST_IPSEC)
PR_WRAP_CTLINPUT(ah6_ctlinput)
+
+#if defined(IPSEC_ESP) || defined(FAST_IPSEC)
PR_WRAP_CTLINPUT(esp6_ctlinput)
+#endif
#define ah6_ctlinput ah6_ctlinput_wrapper
#define esp6_ctlinput esp6_ctlinput_wrapper