Annotation of embedaddon/istgt/src/istgt_crc32c.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008-2010 Daisuke Aoyama <aoyama@peach.ne.jp>.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17: * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24: * SUCH DAMAGE.
25: *
26: */
27:
28: #ifdef HAVE_CONFIG_H
29: #include "config.h"
30: #endif
31:
32: #include <inttypes.h>
33: #include <stdint.h>
34:
35: #include <ctype.h>
36: #include <stdio.h>
37: #include <string.h>
38: #include <sys/uio.h>
39:
40: #include "istgt_iscsi.h"
41: #include "istgt_crc32c.h"
42:
43: /* defined in RFC3720(12.1) */
44: static uint32_t istgt_crc32c_initial = ISTGT_CRC32C_INITIAL;
45: static uint32_t istgt_crc32c_xor = ISTGT_CRC32C_XOR;
46: static uint32_t istgt_crc32c_polynomial = ISTGT_CRC32C_POLYNOMIAL;
47: #ifdef ISTGT_USE_CRC32C_TABLE
48: static uint32_t istgt_crc32c_table[256];
49: static int istgt_crc32c_initialized = 0;
50: #endif /* ISTGT_USE_CRC32C_TABLE */
51:
52: static uint32_t
53: istgt_reflect(uint32_t val, int bits)
54: {
55: int i;
56: uint32_t r;
57:
58: if (bits < 1 || bits > 32)
59: return 0;
60: r = 0;
61: for (i = 0; i < bits; i++) {
62: r |= ((val >> ((bits - 1) - i)) & 1) << i;
63: }
64: return r;
65: }
66:
67: #ifdef ISTGT_USE_CRC32C_TABLE
68: void
69: istgt_init_crc32c_table(void)
70: {
71: int i, j;
72: uint32_t val;
73: uint32_t reflect_polynomial;
74:
75: reflect_polynomial = istgt_reflect(istgt_crc32c_polynomial, 32);
76: for (i = 0; i < 256; i++) {
77: val = i;
78: for (j = 0; j < 8; j++) {
79: if (val & 1) {
80: val = (val >> 1) ^ reflect_polynomial;
81: } else {
82: val = (val >> 1);
83: }
84: }
85: istgt_crc32c_table[i] = val;
86: }
87: istgt_crc32c_initialized = 1;
88: }
89: #endif /* ISTGT_USE_CRC32C_TABLE */
90:
91: uint32_t
92: istgt_update_crc32c(const uint8_t *buf, size_t len, uint32_t crc)
93: {
94: size_t s;
95: #ifndef ISTGT_USE_CRC32C_TABLE
96: int i;
97: uint32_t val;
98: uint32_t reflect_polynomial;
99: #endif /* ISTGT_USE_CRC32C_TABLE */
100:
101: #ifdef ISTGT_USE_CRC32C_TABLE
102: #if 0
103: /* initialize by main() */
104: if (!istgt_crc32c_initialized) {
105: istgt_init_crc32c_table();
106: }
107: #endif
108: #else
109: reflect_polynomial = istgt_reflect(istgt_crc32c_polynomial, 32);
110: #endif /* ISTGT_USE_CRC32C_TABLE */
111:
112: for (s = 0; s < len; s++) {
113: #ifdef ISTGT_USE_CRC32C_TABLE
114: crc = (crc >> 8) ^ istgt_crc32c_table[(crc ^ buf[s]) & 0xff];
115: #else
116: val = buf[s];
117: for (i = 0; i < 8; i++) {
118: if ((crc ^ val) & 1) {
119: crc = (crc >> 1) ^ reflect_polynomial;
120: } else {
121: crc = (crc >> 1);
122: }
123: val = val >> 1;
124: }
125: #endif /* ISTGT_USE_CRC32C_TABLE */
126: }
127: return crc;
128: }
129:
130: uint32_t
131: istgt_fixup_crc32c(size_t total, uint32_t crc)
132: {
133: uint8_t padding[ISCSI_ALIGNMENT];
134: size_t pad_length;
135: size_t rest;
136:
137: if (total == 0)
138: return crc;
139: #if 0
140: /* alignment must be power of 2 */
141: rest = total & ~(ISCSI_ALIGNMENT - 1);
142: #endif
143: rest = total % ISCSI_ALIGNMENT;
144: if (rest != 0) {
145: pad_length = ISCSI_ALIGNMENT;
146: pad_length -= rest;
147: if (pad_length > 0 && pad_length < sizeof padding){
148: memset(padding, 0, sizeof padding);
149: crc = istgt_update_crc32c(padding, pad_length, crc);
150: }
151: }
152: return crc;
153: }
154:
155: uint32_t
156: istgt_crc32c(const uint8_t *buf, size_t len)
157: {
158: uint32_t crc32c;
159:
160: crc32c = istgt_crc32c_initial;
161: crc32c = istgt_update_crc32c(buf, len, crc32c);
162: if ((len % ISCSI_ALIGNMENT) != 0) {
163: crc32c = istgt_fixup_crc32c(len, crc32c);
164: }
165: crc32c = crc32c ^ istgt_crc32c_xor;
166: return crc32c;
167: }
168:
169: uint32_t
170: istgt_iovec_crc32c(const struct iovec *iovp, int iovc, uint32_t offset, uint32_t len)
171: {
172: const uint8_t *p;
173: uint32_t total;
174: uint32_t pos;
175: uint32_t n;
176: uint32_t crc32c;
177: int i;
178:
179: pos = 0;
180: total = 0;
181: crc32c = istgt_crc32c_initial;
182: for (i = 0; i < iovc; i++) {
183: if (len == 0)
184: break;
185: if (pos + iovp[i].iov_len > offset) {
186: p = (const uint8_t *) iovp[i].iov_base + (offset - pos);
187: if (iovp[i].iov_len > len) {
188: n = len;
189: len = 0;
190: } else {
191: n = iovp[i].iov_len;
192: len -= n;
193: }
194: crc32c = istgt_update_crc32c(p, n, crc32c);
195: offset += n;
196: total += n;
197: }
198: pos += iovp[i].iov_len;
199: }
200: #if 0
201: printf("update %d bytes\n", total);
202: #endif
203: crc32c = istgt_fixup_crc32c(total, crc32c);
204: crc32c = crc32c ^ istgt_crc32c_xor;
205: return crc32c;
206: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>