summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/in6_cksum.c
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2012-05-24 18:25:09 +0000
committerbz <bz@FreeBSD.org>2012-05-24 18:25:09 +0000
commitd9ff82d31375889fd29b665a55f4c23f88b1aa86 (patch)
tree8dfc96c625e2beca5527cd30a623ad424da455a3 /sys/netinet6/in6_cksum.c
parent9b587cf418ada5a60db4f592bc3f8cf28bc1ef04 (diff)
downloadFreeBSD-src-d9ff82d31375889fd29b665a55f4c23f88b1aa86.zip
FreeBSD-src-d9ff82d31375889fd29b665a55f4c23f88b1aa86.tar.gz
MFp4 bz_ipv6_fast:
Introduce a (for now copied stripped down) in6_cksum_pseudo() function. We should be able to use this from in6_cksum() but we should also ponder possible MD specific improvements. It takes an extra csum argument to allow for easy checks as will be done by the upper layer protocol input paths. Sponsored by: The FreeBSD Foundation Sponsored by: iXsystems Reviewed by: gnn (as part of the whole) MFC After: 3 days
Diffstat (limited to 'sys/netinet6/in6_cksum.c')
-rw-r--r--sys/netinet6/in6_cksum.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/sys/netinet6/in6_cksum.c b/sys/netinet6/in6_cksum.c
index 034848b..da8a2e6 100644
--- a/sys/netinet6/in6_cksum.c
+++ b/sys/netinet6/in6_cksum.c
@@ -80,6 +80,66 @@ __FBSDID("$FreeBSD$");
#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);}
+static int
+_in6_cksum_pseudo(struct ip6_hdr *ip6, uint32_t len, uint8_t nxt, uint16_t csum)
+{
+ int sum;
+ uint16_t scope, *w;
+ union {
+ u_int16_t phs[4];
+ struct {
+ u_int32_t ph_len;
+ u_int8_t ph_zero[3];
+ u_int8_t ph_nxt;
+ } __packed ph;
+ } uph;
+
+ sum = csum;
+
+ /*
+ * First create IP6 pseudo header and calculate a summary.
+ */
+ uph.ph.ph_len = htonl(len);
+ uph.ph.ph_zero[0] = uph.ph.ph_zero[1] = uph.ph.ph_zero[2] = 0;
+ uph.ph.ph_nxt = nxt;
+
+ /* Payload length and upper layer identifier. */
+ sum += uph.phs[0]; sum += uph.phs[1];
+ sum += uph.phs[2]; sum += uph.phs[3];
+
+ /* IPv6 source address. */
+ scope = in6_getscope(&ip6->ip6_src);
+ w = (u_int16_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)
+ sum -= scope;
+
+ /* IPv6 destination address. */
+ scope = in6_getscope(&ip6->ip6_dst);
+ w = (u_int16_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;
+
+ return (sum);
+}
+
+int
+in6_cksum_pseudo(struct ip6_hdr *ip6, uint32_t len, uint8_t nxt, uint16_t csum)
+{
+ 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);
+}
+
/*
* m MUST contain a contiguous IP6 header.
* off is an offset where TCP/UDP/ICMP6 header starts.
OpenPOWER on IntegriCloud