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