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
This commit is contained in:
Mark Johnston 2021-11-24 13:19:54 -05:00
parent ecbbe83144
commit 0d9c3423f5

View File

@ -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);
}