* code and should be modified for each CPU to be as fast as possible.
*/
+union s_util {
+ char c[2];
+ u_short s;
+};
+union l_util {
+ u_int16_t s[2];
+ u_int32_t l;
+};
+union q_util {
+ u_int16_t s[4];
+ u_int32_t l[2];
+ u_int64_t q;
+};
+
+#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
+
+#define REDUCE32 \
+ { \
+ q_util.q = sum; \
+ sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
+ }
+#define REDUCE16 \
+ { \
+ q_util.q = sum; \
+ l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
+ sum = l_util.s[0] + l_util.s[1]; \
+ ADDCARRY(sum); \
+ }
+
+#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
+
+
#if defined(ppc)
+__inline unsigned short
+in_addword(u_short a, u_short b)
+{
+ union l_util l_util;
+ u_int32_t sum = a + b;
+ REDUCE;
+ return (sum);
+}
+
+__inline unsigned short
+in_pseudo(u_int a, u_int b, u_int c)
+{
+ u_int64_t sum;
+ union q_util q_util;
+ union l_util l_util;
+
+ sum = (u_int64_t) a + b + c;
+ REDUCE16;
+ return (sum);
+
+}
+
int
in_cksum(m, len)
register struct mbuf *m;
return (~sum & 0xffff);
}
+u_short
+in_cksum_skip(m, len, skip)
+ register struct mbuf *m;
+ register int len;
+ register int skip;
+{
+ register u_short *w;
+ register int sum = 0;
+ register int mlen = 0;
+ int starting_on_odd = 0;
+
+ len -= skip;
+ for (; skip && m; m = m->m_next) {
+ if (m->m_len > skip) {
+ mlen = m->m_len - skip;
+ w = (u_short *)(m->m_data+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;
+ w = mtod(m, u_short *);
+
+skip_start:
+ if (len < mlen)
+ mlen = len;
+ sum = xsum_assym(w, mlen, sum, starting_on_odd);
+ len -= mlen;
+ if (mlen & 0x1)
+ {
+ if (starting_on_odd)
+ starting_on_odd = 0;
+ else
+ starting_on_odd = 1;
+ }
+ }
+
+ return (~sum & 0xffff);
+}
#else
+u_short
+in_addword(u_short a, u_short b)
+{
+ union l_util l_util;
+ u_int32_t sum = a + b;
+ REDUCE(sum);
+ return (sum);
+}
-#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
-#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
+u_short
+in_pseudo(u_int a, u_int b, u_int c)
+{
+ u_int64_t sum;
+ union q_util q_util;
+ union l_util l_util;
+ sum = (u_int64_t) a + b + c;
+ REDUCE16;
+ return (sum);
+}
int
register int sum = 0;
register int mlen = 0;
int byte_swapped = 0;
-
- union {
- char c[2];
- u_short s;
- } s_util;
- union {
- u_short s[2];
- long l;
- } l_util;
+ union s_util s_util;
+ union l_util l_util;
KERNEL_DEBUG(DBG_FNC_IN_CKSUM | DBG_FUNC_START, len,0,0,0,0);
return (~sum & 0xffff);
}
+int
+in_cksum_skip(m, len, skip)
+ register struct mbuf *m;
+ register u_short len;
+ register u_short skip;
+{
+ register u_short *w;
+ register int sum = 0;
+ register int mlen = 0;
+ int byte_swapped = 0;
+ union s_util s_util;
+ union l_util l_util;
+
+ KERNEL_DEBUG(DBG_FNC_IN_CKSUM | DBG_FUNC_START, len,0,0,0,0);
+
+ len -= skip;
+ for (; skip && m; m = m->m_next) {
+ if (m->m_len > skip) {
+ mlen = m->m_len - skip;
+ w = (u_short *)(m->m_data+skip);
+ goto skip_start;
+ } else {
+ skip -= m->m_len;
+ }
+ }
+ for (;m && len; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ w = mtod(m, u_short *);
+
+ 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_short *)((char *)w + 1);
+ mlen = m->m_len - 1;
+ len--;
+ } else {
+ mlen = m->m_len;
+ }
+skip_start:
+ if (len < mlen)
+ mlen = len;
+
+ len -= mlen;
+ /*
+ * Force to even boundary.
+ */
+ if ((1 & (int) w) && (mlen > 0)) {
+ REDUCE;
+ sum <<= 8;
+ s_util.c[0] = *(u_char *)w;
+ w = (u_short *)((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 (len)
+ printf("cksum: out of data\n");
+ 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) */
+ s_util.c[1] = 0;
+ sum += s_util.s;
+ }
+ REDUCE;
+ KERNEL_DEBUG(DBG_FNC_IN_CKSUM | DBG_FUNC_END, 0,0,0,0,0);
+ return (~sum & 0xffff);
+}
+
#endif