Annotation of embedaddon/istgt/src/istgt_crc32c.c, revision 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>