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>