aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-11-24 18:19:54 +0000
committerMark Johnston <markj@FreeBSD.org>2021-11-24 18:31:16 +0000
commit0d9c3423f59bb305301f5a5bc7c8f5daf7b7aa52 (patch)
tree0048e14884e4fee4a2bfe5e34897e8eab3dbefe6
parentecbbe831445a4b94279e5932828d60076e4ca444 (diff)
downloadsrc-0d9c3423f59bb305301f5a5bc7c8f5daf7b7aa52.tar.gz
src-0d9c3423f59bb305301f5a5bc7c8f5daf7b7aa52.zip
netinet: Implement in_cksum_skip() using m_apply()
This allows it to work with unmapped mbufs. In particular, in_cksum_skip() calls no longer need to be preceded by calls to mb_unmapped_to_ext() to avoid a page fault. PR: 259645 Reviewed by: gallatin, glebius, jhb MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D33096
-rw-r--r--sys/netinet/in_cksum.c63
1 files changed, 32 insertions, 31 deletions
diff --git a/sys/netinet/in_cksum.c b/sys/netinet/in_cksum.c
index 581950c8afa4..98317d4dac4a 100644
--- a/sys/netinet/in_cksum.c
+++ b/sys/netinet/in_cksum.c
@@ -49,7 +49,9 @@ __FBSDID("$FreeBSD$");
#include <machine/in_cksum.h>
/*
- * These implementations may be overridden on a per-platform basis.
+ * These implementations may be overridden on a per-platform basis. On
+ * platforms with a direct map, the implementation of in_cksum() must handle
+ * unmapped mbufs.
*/
#ifndef HAVE_MD_IN_CKSUM
@@ -203,44 +205,43 @@ in_pseudo(u_int32_t a, u_int32_t b, u_int32_t c)
return (sum);
}
+struct cksum_skip_partial_args {
+ uint64_t csum;
+ int clen;
+};
+
+static int
+in_cksum_skip_partial(void *arg, void *data, u_int len)
+{
+ struct cksum_skip_partial_args *a;
+
+ a = arg;
+ if (((uintptr_t)data ^ a->clen) & 1)
+ a->csum += in_cksumdata(data, len) << 8;
+ else
+ a->csum += in_cksumdata(data, len);
+ a->clen += len;
+ return (0);
+}
+
u_short
in_cksum_skip(struct mbuf *m, int len, int skip)
{
- u_int64_t sum = 0;
- int mlen = 0;
- int clen = 0;
- caddr_t addr;
+ struct cksum_skip_partial_args a;
union q_util q_util;
union l_util l_util;
+ uint64_t sum;
len -= skip;
- for (; skip && m; m = m->m_next) {
- if (m->m_len > skip) {
- mlen = m->m_len - skip;
- addr = mtod(m, caddr_t) + skip;
- goto skip_start;
- } else {
- skip -= m->m_len;
- }
- }
-
- for (; m && len; m = m->m_next) {
- if (m->m_len == 0)
- continue;
- mlen = m->m_len;
- addr = mtod(m, caddr_t);
-skip_start:
- if (len < mlen)
- mlen = len;
-
- if ((clen ^ (uintptr_t) addr) & 1)
- sum += in_cksumdata(addr, mlen) << 8;
- else
- sum += in_cksumdata(addr, mlen);
- clen += mlen;
- len -= mlen;
- }
+ /*
+ * The use of m_apply() allows this routine to operate on unmapped
+ * mbufs.
+ */
+ a.csum = 0;
+ a.clen = 0;
+ (void)m_apply(m, skip, len, in_cksum_skip_partial, &a);
+ sum = a.csum;
REDUCE16;
return (~sum & 0xffff);
}