patch-2.4.23 linux-2.4.23/net/sctp/adler32.c

Next file: linux-2.4.23/net/sctp/associola.c
Previous file: linux-2.4.23/net/sctp/Makefile
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/net/sctp/adler32.c linux-2.4.23/net/sctp/adler32.c
@@ -0,0 +1,171 @@
+/* SCTP kernel reference Implementation
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2003 International Business Machines, Corp.
+ *
+ * This file is part of the SCTP kernel reference Implementation
+ *
+ * This file has direct heritage from the SCTP user-level reference
+ * implementation by R. Stewart, et al.  These functions implement the
+ * Adler-32 algorithm as specified by RFC 2960.
+ *
+ * The SCTP reference implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * The SCTP reference implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ *                 ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ *    http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ *    Randall Stewart <rstewar1@email.mot.com>
+ *    Ken Morneau     <kmorneau@cisco.com>
+ *    Qiaobing Xie    <qxie1@email.mot.com>
+ *    Sridhar Samudrala <sri@us.ibm.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+/* This is an entry point for external calls
+ * Define this function in the header file. This is
+ * direct from rfc1950, ...
+ *
+ * The following C code computes the Adler-32 checksum of a data buffer.
+ * It is written for clarity, not for speed.  The sample code is in the
+ * ANSI C programming language. Non C users may find it easier to read
+ * with these hints:
+ *
+ *    &      Bitwise AND operator.
+ *    >>     Bitwise right shift operator. When applied to an
+ *           unsigned quantity, as here, right shift inserts zero bit(s)
+ *           at the left.
+ *    <<     Bitwise left shift operator. Left shift inserts zero
+ *           bit(s) at the right.
+ *    ++     "n++" increments the variable n.
+ *    %      modulo operator: a % b is the remainder of a divided by b.
+ *
+ * Well, the above is a bit of a lie, I have optimized this a small
+ * tad, but I have commented the original lines below
+ */
+
+#include <linux/types.h>
+#include <net/sctp/sctp.h>
+
+#define BASE 65521 /* largest prime smaller than 65536 */
+
+
+/* Performance work as shown this pig to be the
+ * worst CPU wise guy. I have done what I could think
+ * of on my flight to Australia but I am sure some
+ * clever assembly could speed this up, but of
+ * course this would require the dreaded #ifdef's for
+ * architecture. If you can speed this up more, pass
+ * it back and we will incorporate it :-)
+ */
+
+unsigned long update_adler32(unsigned long adler,
+			     unsigned char *buf, int len)
+{
+	__u32 s1 = adler & 0xffff;
+	__u32 s2 = (adler >> 16) & 0xffff;
+        int n;
+
+	for (n = 0; n < len; n++,buf++) {
+		/* s1 = (s1 + buf[n]) % BASE */
+		/* first we add */
+		s1 = (s1 + *buf);
+
+		/* Now if we need to, we do a mod by
+		 * subtracting. It seems a bit faster
+		 * since I really will only ever do
+		 * one subtract at the MOST, since buf[n]
+		 * is a max of 255.
+		 */
+		if (s1 >= BASE)
+			s1 -= BASE;
+
+		/* s2 = (s2 + s1) % BASE */
+		/* first we add */
+		s2 = (s2 + s1);
+
+		/* again, it is more efficient (it seems) to
+		 * subtract since the most s2 will ever be
+		 * is (BASE-1 + BASE-1) in the worse case.
+		 * This would then be (2 * BASE) - 2, which
+		 * will still only do one subtract. On Intel
+		 * this is much better to do this way and
+		 * avoid the divide. Have not -pg'd on
+		 * sparc.
+		 */
+		if (s2 >= BASE) {
+			/*      s2 %= BASE;*/
+			s2 -= BASE;
+		}
+	}
+
+	/* Return the adler32 of the bytes buf[0..len-1] */
+	return (s2 << 16) + s1;
+}
+
+__u32 sctp_start_cksum(__u8 *ptr, __u16 count)
+{
+	/*
+	 * Update a running Adler-32 checksum with the bytes
+	 * buf[0..len-1] and return the updated checksum. The Adler-32
+	 * checksum should be initialized to 1.
+	 */
+	__u32 adler = 1L;
+	__u32 zero = 0L;
+
+	/* Calculate the CRC up to the checksum field. */
+	adler = update_adler32(adler, ptr,
+			       sizeof(struct sctphdr) - sizeof(__u32));
+	/* Skip over the checksum field. */
+	adler = update_adler32(adler, (unsigned char *) &zero,
+			       sizeof(__u32));
+	ptr += sizeof(struct sctphdr);
+	count -= sizeof(struct sctphdr);
+
+	/* Calculate the rest of the Adler-32. */
+	adler = update_adler32(adler, ptr, count);
+
+        return adler;
+}
+
+__u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 adler)
+{
+	adler = update_adler32(adler, ptr, count);
+
+	return adler;
+}
+
+__u32 sctp_update_copy_cksum(__u8 *to, __u8 *from, __u16 count, __u32 adler)
+{
+	/* Its not worth it to try harder.  Adler32 is obsolescent. */
+	adler = update_adler32(adler, from, count);
+	memcpy(to, from, count);
+
+	return adler;
+}
+
+__u32 sctp_end_cksum(__u32 adler)
+{
+	return adler;
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)