File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / istgt / src / istgt_crc32c.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:42:02 2012 UTC (13 years, 1 month ago) by misho
Branches: istgt, MAIN
CVS tags: v20121028, v20120901, v20111008, HEAD
istgt

    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>