xref: /titanic_41/usr/src/uts/common/os/sctp_crc32.c (revision da14cebe459d3275048785f25bd869cb09b5307f)
1*da14cebeSEric Cheng /*
2*da14cebeSEric Cheng  * CDDL HEADER START
3*da14cebeSEric Cheng  *
4*da14cebeSEric Cheng  * The contents of this file are subject to the terms of the
5*da14cebeSEric Cheng  * Common Development and Distribution License (the "License").
6*da14cebeSEric Cheng  * You may not use this file except in compliance with the License.
7*da14cebeSEric Cheng  *
8*da14cebeSEric Cheng  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*da14cebeSEric Cheng  * or http://www.opensolaris.org/os/licensing.
10*da14cebeSEric Cheng  * See the License for the specific language governing permissions
11*da14cebeSEric Cheng  * and limitations under the License.
12*da14cebeSEric Cheng  *
13*da14cebeSEric Cheng  * When distributing Covered Code, include this CDDL HEADER in each
14*da14cebeSEric Cheng  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*da14cebeSEric Cheng  * If applicable, add the following below this CDDL HEADER, with the
16*da14cebeSEric Cheng  * fields enclosed by brackets "[]" replaced with your own identifying
17*da14cebeSEric Cheng  * information: Portions Copyright [yyyy] [name of copyright owner]
18*da14cebeSEric Cheng  *
19*da14cebeSEric Cheng  * CDDL HEADER END
20*da14cebeSEric Cheng  */
21*da14cebeSEric Cheng /*
22*da14cebeSEric Cheng  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*da14cebeSEric Cheng  * Use is subject to license terms.
24*da14cebeSEric Cheng  */
25*da14cebeSEric Cheng 
26*da14cebeSEric Cheng #include <sys/types.h>
27*da14cebeSEric Cheng 
28*da14cebeSEric Cheng /*
29*da14cebeSEric Cheng  * Fast CRC32 calculation algorithm suggested by Ferenc Rakoczi
30*da14cebeSEric Cheng  * (ferenc.rakoczi@sun.com).  The basic idea is to look at it
31*da14cebeSEric Cheng  * four bytes (one word) at a time, using four tables.  The
32*da14cebeSEric Cheng  * standard algorithm in RFC 3309 uses one table.
33*da14cebeSEric Cheng  */
34*da14cebeSEric Cheng 
35*da14cebeSEric Cheng /*
36*da14cebeSEric Cheng  * SCTP uses reflected/reverse polynomial CRC32 with generating
37*da14cebeSEric Cheng  * polynomial 0x1EDC6F41L
38*da14cebeSEric Cheng  */
39*da14cebeSEric Cheng #define	SCTP_POLY 0x1EDC6F41L
40*da14cebeSEric Cheng 
41*da14cebeSEric Cheng /* The four CRC tables. */
42*da14cebeSEric Cheng static uint32_t crctab[4][256];
43*da14cebeSEric Cheng 
44*da14cebeSEric Cheng static uint32_t
reflect_32(uint32_t b)45*da14cebeSEric Cheng reflect_32(uint32_t b)
46*da14cebeSEric Cheng {
47*da14cebeSEric Cheng 	int i;
48*da14cebeSEric Cheng 	uint32_t rw = 0;
49*da14cebeSEric Cheng 
50*da14cebeSEric Cheng 	for (i = 0; i < 32; i++) {
51*da14cebeSEric Cheng 		if (b & 1) {
52*da14cebeSEric Cheng 			rw |= 1 << (31 - i);
53*da14cebeSEric Cheng 		}
54*da14cebeSEric Cheng 		b >>= 1;
55*da14cebeSEric Cheng 	}
56*da14cebeSEric Cheng 	return (rw);
57*da14cebeSEric Cheng }
58*da14cebeSEric Cheng 
59*da14cebeSEric Cheng #ifdef _BIG_ENDIAN
60*da14cebeSEric Cheng 
61*da14cebeSEric Cheng /*
62*da14cebeSEric Cheng  * This function is only used for big endian processor.
63*da14cebeSEric Cheng  */
64*da14cebeSEric Cheng static uint32_t
flip32(uint32_t w)65*da14cebeSEric Cheng flip32(uint32_t w)
66*da14cebeSEric Cheng {
67*da14cebeSEric Cheng 	return (((w >> 24) | ((w >> 8) & 0xff00) | ((w << 8) & 0xff0000) |
68*da14cebeSEric Cheng 	    (w << 24)));
69*da14cebeSEric Cheng }
70*da14cebeSEric Cheng 
71*da14cebeSEric Cheng #endif
72*da14cebeSEric Cheng 
73*da14cebeSEric Cheng void
sctp_crc32_init(void)74*da14cebeSEric Cheng sctp_crc32_init(void)
75*da14cebeSEric Cheng {
76*da14cebeSEric Cheng 	uint32_t i, j, k, crc;
77*da14cebeSEric Cheng 
78*da14cebeSEric Cheng 	for (i = 0; i < 256; i++) {
79*da14cebeSEric Cheng 		crc = reflect_32(i);
80*da14cebeSEric Cheng 		for (k = 0; k < 4; k++) {
81*da14cebeSEric Cheng 			for (j = 0; j < 8; j++) {
82*da14cebeSEric Cheng 				crc = (crc & 0x80000000) ?
83*da14cebeSEric Cheng 				    (crc << 1) ^ SCTP_POLY : crc << 1;
84*da14cebeSEric Cheng 			}
85*da14cebeSEric Cheng #ifdef _BIG_ENDIAN
86*da14cebeSEric Cheng 			crctab[3 - k][i] = flip32(reflect_32(crc));
87*da14cebeSEric Cheng #else
88*da14cebeSEric Cheng 			crctab[k][i] = reflect_32(crc);
89*da14cebeSEric Cheng #endif
90*da14cebeSEric Cheng 		}
91*da14cebeSEric Cheng 	}
92*da14cebeSEric Cheng }
93*da14cebeSEric Cheng 
94*da14cebeSEric Cheng static void
sctp_crc_byte(uint32_t * crcptr,const uint8_t * buf,int len)95*da14cebeSEric Cheng sctp_crc_byte(uint32_t *crcptr, const uint8_t *buf, int len)
96*da14cebeSEric Cheng {
97*da14cebeSEric Cheng 	uint32_t crc;
98*da14cebeSEric Cheng 	int i;
99*da14cebeSEric Cheng 
100*da14cebeSEric Cheng 	crc = *crcptr;
101*da14cebeSEric Cheng 	for (i = 0; i < len; i++) {
102*da14cebeSEric Cheng #ifdef _BIG_ENDIAN
103*da14cebeSEric Cheng 		crc = (crc << 8) ^ crctab[3][buf[i] ^ (crc >> 24)];
104*da14cebeSEric Cheng #else
105*da14cebeSEric Cheng 		crc = (crc >> 8) ^ crctab[0][buf[i] ^ (crc & 0xff)];
106*da14cebeSEric Cheng #endif
107*da14cebeSEric Cheng 	}
108*da14cebeSEric Cheng 	*crcptr = crc;
109*da14cebeSEric Cheng }
110*da14cebeSEric Cheng 
111*da14cebeSEric Cheng static void
sctp_crc_word(uint32_t * crcptr,const uint32_t * buf,int len)112*da14cebeSEric Cheng sctp_crc_word(uint32_t *crcptr, const uint32_t *buf, int len)
113*da14cebeSEric Cheng {
114*da14cebeSEric Cheng 	uint32_t w, crc;
115*da14cebeSEric Cheng 	int i;
116*da14cebeSEric Cheng 
117*da14cebeSEric Cheng 	crc = *crcptr;
118*da14cebeSEric Cheng 	for (i = 0; i < len; i++) {
119*da14cebeSEric Cheng 		w = crc ^ buf[i];
120*da14cebeSEric Cheng 		crc = crctab[0][w >> 24] ^ crctab[1][(w >> 16) & 0xff] ^
121*da14cebeSEric Cheng 		    crctab[2][(w >> 8) & 0xff] ^ crctab[3][w & 0xff];
122*da14cebeSEric Cheng 	}
123*da14cebeSEric Cheng 	*crcptr = crc;
124*da14cebeSEric Cheng }
125*da14cebeSEric Cheng 
126*da14cebeSEric Cheng uint32_t
sctp_crc32(uint32_t crc32,const uint8_t * buf,int len)127*da14cebeSEric Cheng sctp_crc32(uint32_t crc32, const uint8_t *buf, int len)
128*da14cebeSEric Cheng {
129*da14cebeSEric Cheng 	int rem;
130*da14cebeSEric Cheng 
131*da14cebeSEric Cheng 	rem = 4 - ((uintptr_t)buf) & 3;
132*da14cebeSEric Cheng 	if (rem != 0) {
133*da14cebeSEric Cheng 		if (len < rem) {
134*da14cebeSEric Cheng 			rem = len;
135*da14cebeSEric Cheng 		}
136*da14cebeSEric Cheng 		sctp_crc_byte(&crc32, buf, rem);
137*da14cebeSEric Cheng 		buf = buf + rem;
138*da14cebeSEric Cheng 		len = len - rem;
139*da14cebeSEric Cheng 	}
140*da14cebeSEric Cheng 
141*da14cebeSEric Cheng 	if (len > 3) {
142*da14cebeSEric Cheng 		sctp_crc_word(&crc32, (const uint32_t *)buf, len / 4);
143*da14cebeSEric Cheng 	}
144*da14cebeSEric Cheng 
145*da14cebeSEric Cheng 	rem = len & 3;
146*da14cebeSEric Cheng 	if (rem != 0) {
147*da14cebeSEric Cheng 		sctp_crc_byte(&crc32, buf + len - rem, rem);
148*da14cebeSEric Cheng 	}
149*da14cebeSEric Cheng 	return (crc32);
150*da14cebeSEric Cheng }
151