Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102978604
D40598.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D40598.diff
View Options
diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h
--- a/sys/netinet6/in6.h
+++ b/sys/netinet6/in6.h
@@ -659,10 +659,10 @@
struct cmsghdr;
struct ip6_hdr;
+int in6_cksum(struct mbuf *, uint8_t, uint32_t, uint32_t);
+int in6_cksum_partial(struct mbuf *, uint8_t, uint32_t, uint32_t, uint32_t);
int in6_cksum_pseudo(struct ip6_hdr *, uint32_t, uint8_t, uint16_t);
-int in6_cksum(struct mbuf *, u_int8_t, u_int32_t, u_int32_t);
-int in6_cksum_partial(struct mbuf *, u_int8_t, u_int32_t, u_int32_t,
- u_int32_t);
+
int in6_localaddr(struct in6_addr *);
int in6_localip(struct in6_addr *);
bool in6_localip_fib(struct in6_addr *, uint16_t);
diff --git a/sys/netinet6/in6_cksum.c b/sys/netinet6/in6_cksum.c
--- a/sys/netinet6/in6_cksum.c
+++ b/sys/netinet6/in6_cksum.c
@@ -82,6 +82,16 @@
#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; (void)ADDCARRY(sum);}
+union l_util {
+ uint16_t s[2];
+ uint32_t l;
+};
+
+union s_util {
+ uint8_t c[2];
+ uint16_t s;
+};
+
static int
_in6_cksum_pseudo(struct ip6_hdr *ip6, uint32_t len, uint8_t nxt, uint16_t csum)
{
@@ -131,17 +141,115 @@
int
in6_cksum_pseudo(struct ip6_hdr *ip6, uint32_t len, uint8_t nxt, uint16_t csum)
{
+ union l_util l_util;
int sum;
- union {
- u_int16_t s[2];
- u_int32_t l;
- } l_util;
sum = _in6_cksum_pseudo(ip6, len, nxt, csum);
REDUCE;
return (sum);
}
+static int
+in6_cksumdata(void *data, int *lenp, uint8_t *residp, int rlen)
+{
+ union l_util l_util;
+ union s_util s_util;
+ uint16_t *w;
+ int len, sum;
+ bool byte_swapped;
+
+ KASSERT(*lenp >= 0, ("%s: negative len %d", __func__, *lenp));
+ KASSERT(rlen == 0 || rlen == 1, ("%s: rlen %d", __func__, rlen));
+
+ len = *lenp;
+ sum = 0;
+
+ if (len == 0) {
+ len = rlen;
+ goto out;
+ }
+
+ byte_swapped = false;
+ w = data;
+
+ /*
+ * Do we have a residual byte left over from the previous buffer?
+ */
+ if (rlen == 1) {
+ s_util.c[0] = *residp;
+ s_util.c[1] = *(uint8_t *)w;
+ sum += s_util.s;
+ w = (uint16_t *)((uint8_t *)w + 1);
+ len--;
+ rlen = 0;
+ }
+
+ /*
+ * Force to even boundary.
+ */
+ if ((1 & (uintptr_t)w) && len > 0) {
+ REDUCE;
+ sum <<= 8;
+ s_util.c[0] = *(uint8_t *)w;
+ w = (uint16_t *)((uint8_t *)w + 1);
+ len--;
+ byte_swapped = true;
+ }
+
+ /*
+ * Unroll the loop to make overhead from branches &c small.
+ */
+ while ((len -= 32) >= 0) {
+ sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
+ sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
+ sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
+ sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
+ w += 16;
+ }
+ len += 32;
+ while ((len -= 8) >= 0) {
+ sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
+ w += 4;
+ }
+ len += 8;
+ if (len == 0 && !byte_swapped)
+ goto out;
+ REDUCE;
+ while ((len -= 2) >= 0) {
+ sum += *w++;
+ }
+ if (byte_swapped) {
+ REDUCE;
+ sum <<= 8;
+ if (len == -1) {
+ s_util.c[1] = *(uint8_t *)w;
+ sum += s_util.s;
+ } else /* len == -2 */
+ *residp = s_util.c[0];
+ len++;
+ } else if (len == -1)
+ *residp = *(uint8_t *)w;
+out:
+ *lenp = len & 1;
+ return (sum);
+}
+
+struct in6_cksum_partial_arg {
+ int sum;
+ int rlen;
+ uint8_t resid;
+};
+
+static int
+in6_cksum_partial_one(void *_arg, void *data, u_int len)
+{
+ struct in6_cksum_partial_arg *arg = _arg;
+
+ arg->sum += in6_cksumdata(data, &len, &arg->resid, arg->rlen);
+ arg->rlen = len;
+ return (0);
+}
+
/*
* m MUST contain a contiguous IP6 header.
* off is an offset where TCP/UDP/ICMP6 header starts.
@@ -150,33 +258,29 @@
* cov is the number of bytes to be taken into account for the checksum
*/
int
-in6_cksum_partial(struct mbuf *m, u_int8_t nxt, u_int32_t off,
- u_int32_t len, u_int32_t cov)
+in6_cksum_partial(struct mbuf *m, uint8_t nxt, uint32_t off, uint32_t len,
+ uint32_t cov)
{
+ struct in6_cksum_partial_arg arg;
+ union l_util l_util;
+ union s_util s_util;
struct ip6_hdr *ip6;
- u_int16_t *w, scope;
- int byte_swapped, mlen;
+ uint16_t *w, scope;
int sum;
union {
- u_int16_t phs[4];
+ uint16_t phs[4];
struct {
- u_int32_t ph_len;
- u_int8_t ph_zero[3];
- u_int8_t ph_nxt;
+ uint32_t ph_len;
+ uint8_t ph_zero[3];
+ uint8_t ph_nxt;
} __packed ph;
} uph;
- union {
- u_int8_t c[2];
- u_int16_t s;
- } s_util;
- union {
- u_int16_t s[2];
- u_int32_t l;
- } l_util;
/* Sanity check. */
KASSERT(m->m_pkthdr.len >= off + len, ("%s: mbuf len (%d) < off(%d)+"
"len(%d)", __func__, m->m_pkthdr.len, off, len));
+ KASSERT(m->m_len >= sizeof(*ip6),
+ ("%s: mbuf len %d < sizeof(ip6)", __func__, m->m_len));
/*
* First create IP6 pseudo header and calculate a summary.
@@ -193,7 +297,7 @@
/* IPv6 source address. */
scope = in6_getscope(&ip6->ip6_src);
- w = (u_int16_t *)&ip6->ip6_src;
+ w = (uint16_t *)&ip6->ip6_src;
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
if (scope != 0)
@@ -201,158 +305,26 @@
/* IPv6 destination address. */
scope = in6_getscope(&ip6->ip6_dst);
- w = (u_int16_t *)&ip6->ip6_dst;
+ w = (uint16_t *)&ip6->ip6_dst;
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
if (scope != 0)
sum -= scope;
/*
- * Secondly calculate a summary of the first mbuf excluding offset.
+ * Loop over the rest of the mbuf chain and compute the rest of the
+ * checksum. m_apply() handles unmapped mbufs.
*/
- while (off > 0) {
- if (m->m_len <= off)
- off -= m->m_len;
- else
- break;
- m = m->m_next;
- }
- w = (u_int16_t *)(mtod(m, u_char *) + off);
- mlen = m->m_len - off;
- if (cov < mlen)
- mlen = cov;
- cov -= mlen;
- /*
- * Force to even boundary.
- */
- if ((1 & (long)w) && (mlen > 0)) {
- REDUCE;
- sum <<= 8;
- s_util.c[0] = *(u_char *)w;
- w = (u_int16_t *)((char *)w + 1);
- mlen--;
- byte_swapped = 1;
- } else
- byte_swapped = 0;
+ arg.sum = sum;
+ arg.rlen = 0;
+ (void)m_apply(m, off, cov, in6_cksum_partial_one, &arg);
+ sum = arg.sum;
/*
- * Unroll the loop to make overhead from
- * branches &c small.
+ * Handle a residual byte.
*/
- while ((mlen -= 32) >= 0) {
- sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
- sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
- sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
- sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
- w += 16;
- }
- mlen += 32;
- while ((mlen -= 8) >= 0) {
- sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
- w += 4;
- }
- mlen += 8;
- if (mlen == 0 && byte_swapped == 0)
- goto next;
- REDUCE;
- while ((mlen -= 2) >= 0) {
- sum += *w++;
- }
- if (byte_swapped) {
- REDUCE;
- sum <<= 8;
- byte_swapped = 0;
- if (mlen == -1) {
- s_util.c[1] = *(char *)w;
- sum += s_util.s;
- mlen = 0;
- } else
- mlen = -1;
- } else if (mlen == -1)
- s_util.c[0] = *(char *)w;
- next:
- m = m->m_next;
-
- /*
- * Lastly calculate a summary of the rest of mbufs.
- */
-
- for (;m && cov; m = m->m_next) {
- if (m->m_len == 0)
- continue;
- w = mtod(m, u_int16_t *);
- if (mlen == -1) {
- /*
- * The first byte of this mbuf is the continuation
- * of a word spanning between this mbuf and the
- * last mbuf.
- *
- * s_util.c[0] is already saved when scanning previous
- * mbuf.
- */
- s_util.c[1] = *(char *)w;
- sum += s_util.s;
- w = (u_int16_t *)((char *)w + 1);
- mlen = m->m_len - 1;
- cov--;
- } else
- mlen = m->m_len;
- if (cov < mlen)
- mlen = cov;
- cov -= mlen;
- /*
- * Force to even boundary.
- */
- if ((1 & (long) w) && (mlen > 0)) {
- REDUCE;
- sum <<= 8;
- s_util.c[0] = *(u_char *)w;
- w = (u_int16_t *)((char *)w + 1);
- mlen--;
- byte_swapped = 1;
- }
- /*
- * Unroll the loop to make overhead from
- * branches &c small.
- */
- while ((mlen -= 32) >= 0) {
- sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
- sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
- sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
- sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
- w += 16;
- }
- mlen += 32;
- while ((mlen -= 8) >= 0) {
- sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
- w += 4;
- }
- mlen += 8;
- if (mlen == 0 && byte_swapped == 0)
- continue;
- REDUCE;
- while ((mlen -= 2) >= 0) {
- sum += *w++;
- }
- if (byte_swapped) {
- REDUCE;
- sum <<= 8;
- byte_swapped = 0;
- if (mlen == -1) {
- s_util.c[1] = *(char *)w;
- sum += s_util.s;
- mlen = 0;
- } else
- mlen = -1;
- } else if (mlen == -1)
- s_util.c[0] = *(char *)w;
- }
- if (cov)
- panic("in6_cksum: out of data");
- if (mlen == -1) {
- /* The last mbuf has odd # of bytes. Follow the
- standard (the odd byte may be shifted left by 8 bits
- or not as determined by endian-ness of the machine) */
+ if (arg.rlen == 1) {
+ s_util.c[0] = arg.resid;
s_util.c[1] = 0;
sum += s_util.s;
}
@@ -361,7 +333,7 @@
}
int
-in6_cksum(struct mbuf *m, u_int8_t nxt, u_int32_t off, u_int32_t len)
+in6_cksum(struct mbuf *m, uint8_t nxt, uint32_t off, uint32_t len)
{
return (in6_cksum_partial(m, nxt, off, len, len));
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 20, 10:25 AM (21 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14735936
Default Alt Text
D40598.diff (8 KB)
Attached To
Mode
D40598: netinet6: Implement in6_cksum_partial() using m_apply()
Attached
Detach File
Event Timeline
Log In to Comment