The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=0d9c3423f59bb305301f5a5bc7c8f5daf7b7aa52

commit 0d9c3423f59bb305301f5a5bc7c8f5daf7b7aa52
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2021-11-24 18:19:54 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2021-11-24 18:31:16 +0000

    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
---
 sys/netinet/in_cksum.c | 63 +++++++++++++++++++++++++-------------------------
 1 file 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);
 }

Reply via email to