localize header files
[unix-history] / usr / src / sys / vax / vax / in_cksum.c
index 6976a0c..55f2727 100644 (file)
@@ -1,49 +1,40 @@
-/* in_cksum.c 1.1 81/10/14 */
+/* in_cksum.c 1.13 82/10/09 */
 
 #include <sys/types.h>
 
 #include <sys/types.h>
-#include "../bbnnet/net.h"
-#include "../bbnnet/count.h"
+#include "../h/mbuf.h"
+#include "../netinet/in.h"
+#include "../netinet/in_systm.h"
 
 /*
 
 /*
- * Network primitives; this file varies per-cpu,
- * and the code here is for VAX only.
+ * Checksum routine for Internet Protocol family headers.
+ * This routine is very heavily used in the network
+ * code and should be rewritten for each CPU to be as fast as possible.
  */
  */
-cksum(m, len)
-register struct mbuf *m;
-{
-       int i,j;
-       i = ncksum(m, len);
-       j = ocksum(m, len);
-       if (i != j) {
-               printf("old %x new %x \n", i, j);
-               while (m != 0) {
-                       printf("m->m_off %d m->m_len %d\n", m->m_off, m->m_len);
-                       m = m->m_next;
-               }
-       }
-       return (j);
-}
 
 
-/*
- * Checksum routine for TCP/IP headers.  This
- * is very heavily used in the network
- * code and should be rewritten for each CPU
- * to be as fast as possible.
- */
-ncksum(m, len)
+#if vax
+in_cksum(m, len)
        register struct mbuf *m;
        register int len;
 {
        register u_short *w;            /* known to be r9 */
        register int sum = 0;           /* known to be r8 */
        register int mlen = 0;
        register struct mbuf *m;
        register int len;
 {
        register u_short *w;            /* known to be r9 */
        register int sum = 0;           /* known to be r8 */
        register int mlen = 0;
-COUNT(NCKSUM);
 
        for (;;) {
 
        for (;;) {
-               w = (u_short *)((int)m + m->m_off);
+               /*
+                * Each trip around loop adds in
+                * word from one mbuf segment.
+                */
+               w = mtod(m, u_short *);
                if (mlen == -1) {
                if (mlen == -1) {
+                       /*
+                        * There is a byte left from the last segment;
+                        * add it into the checksum.  Don't have to worry
+                        * about a carry-out here because we make sure
+                        * that high part of (32 bit) sum is small below.
+                        */
                        sum += *(u_char *)w << 8;
                        sum += *(u_char *)w << 8;
-                       w = (unsigned short *)((char *)w + 1);
+                       w = (u_short *)((char *)w + 1);
                        mlen = m->m_len - 1;
                        len--;
                } else
                        mlen = m->m_len - 1;
                        len--;
                } else
@@ -52,96 +43,85 @@ COUNT(NCKSUM);
                if (len < mlen)
                        mlen = len;
                len -= mlen;
                if (len < mlen)
                        mlen = len;
                len -= mlen;
+               /*
+                * Force to long boundary so we do longword aligned
+                * memory operations.  It is too hard to do byte
+                * adjustment, do only word adjustment.
+                */
+               if (((int)w&0x2) && mlen >= 2) {
+                       sum += *w++;
+                       mlen -= 2;
+               }
+               /*
+                * Do as much of the checksum as possible 32 bits at at time.
+                * In fact, this loop is unrolled to make overhead from
+                * branches &c small.
+                *
+                * We can do a 16 bit ones complement sum 32 bits at a time
+                * because the 32 bit register is acting as two 16 bit
+                * registers for adding, with carries from the low added
+                * into the high (by normal carry-chaining) and carries
+                * from the high carried into the low on the next word
+                * by use of the adwc instruction.  This lets us run
+                * this loop at almost memory speed.
+                *
+                * Here there is the danger of high order carry out, and
+                * we carefully use adwc.
+                */
                while ((mlen -= 32) >= 0) {
                while ((mlen -= 32) >= 0) {
-#define ADD            asm("movzwl (r9)+,r0; addl2 r0,r8");
-                       ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
+                       asm("clrl r0");         /* clears carry */
+#undef ADD
+#define ADD            asm("adwc (r9)+,r8;");
                        ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
                        ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
+                       asm("adwc $0,r8");
                }
                mlen += 32;
                while ((mlen -= 8) >= 0) {
                }
                mlen += 32;
                while ((mlen -= 8) >= 0) {
-                       ADD; ADD; ADD; ADD;
+                       asm("clrl r0");
+                       ADD; ADD;
+                       asm("adwc $0,r8");
                }
                mlen += 8;
                }
                mlen += 8;
+               /*
+                * Now eliminate the possibility of carry-out's by
+                * folding back to a 16 bit number (adding high and
+                * low parts together.)  Then mop up trailing words
+                * and maybe an odd byte.
+                */
+               { asm("ashl $-16,r8,r0; addw2 r0,r8");
+                 asm("adwc $0,r8; movzwl r8,r8"); }
                while ((mlen -= 2) >= 0) {
                while ((mlen -= 2) >= 0) {
-                       ADD;
+                       asm("movzwl (r9)+,r0; addl2 r0,r8");
                }
                if (mlen == -1)
                        sum += *(u_char *)w;
                if (len == 0)
                        break;
                }
                if (mlen == -1)
                        sum += *(u_char *)w;
                if (len == 0)
                        break;
+               /*
+                * Locate the next block with some data.
+                * If there is a word split across a boundary we
+                * will wrap to the top with mlen == -1 and
+                * then add it in shifted appropriately.
+                */
                for (;;) {
                for (;;) {
-                       if (m == 0)
-                               panic("cksum: out of data");
+                       if (m == 0) {
+                               printf("cksum: out of data\n");
+                               goto done;
+                       }
                        if (m->m_len)
                                break;
                        m = m->m_next;
                }
        }
                        if (m->m_len)
                                break;
                        m = m->m_next;
                }
        }
-       return(~(sum + (sum >> 16)) & 0xffff);
-}
-
-/*
- * These routines are implemented as inline expansions
- * and are mentioned here for reference only
- *
- *     htons and ntohs         do byte reverse of a 16 bit integer
- *     htonl and ntohl         do byte reverse of a 32 bit integer
- */
-ocksum(m, len)
-register struct mbuf *m;
-register len;
-{
-       register unsigned short *w;
-       register unsigned long sum;
-       register mlen;
-COUNT(OCKSUM);
-
-       w = (unsigned short *)((int)m + m->m_off);
-       mlen = m->m_len;
-       sum = 0;
-
-       for (; len > 0; len -= 2, mlen -= 2) {
-
-try:            if (mlen > 1) {         /* can get a word */
-
-                       if (len > 1) {
-                               sum += *(w++);
-
-                       } else            /* trailing odd byte */
-
-                               sum += *((char *)w) & 0xff;
-
-               } else if (mlen > 0) {  /* last byte of mbuf */
-
-                       sum += *((char *)w) & 0xff;
-
-                       if (len > 1) {
-
-                               /* get next good mbuf for hi byte */
-        
-                               while ((m = m->m_next) != 0 && 
-                                       (mlen = m->m_len + 1) == 1);
-                               if (m != 0) {
-                                       w = (unsigned short *)((int)m + m->m_off);
-                                       sum += (*((char *)w) & 0xff) << 8;
-                                       w = (unsigned short *)((int)w + 1);
-                               } else
-                                       len = 0;        /* force loop exit */
-                       }
-
-               } else {                /* end of mbuf, get next and try again */
-
-                       while ((m = m->m_next) != 0 && (mlen = m->m_len) == 0);
-                       if (m != 0) {
-                               w = (unsigned short *)((int)m + m->m_off);
-                               goto try;
-                       } else
-                               break;
-               }
-       }
-
-       /* add in one's complement carry */
-
-       sum = (sum + (sum >> 16)) & 0xffff;
-       return(~sum & 0xffff);
+done:
+       /*
+        * Add together high and low parts of sum
+        * and carry to get cksum.
+        * Have to be careful to not drop the last
+        * carry here.
+        */
+       { asm("ashl $-16,r8,r0; addw2 r0,r8; adwc $0,r8");
+         asm("mcoml r8,r8; movzwl r8,r8"); }
+       return (sum);
 }
 }
+#endif