source: mainline/uspace/srv/net/checksum.c@ 60ab6c3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 60ab6c3 was a64c64d, checked in by Lukas Mejdrech <lukasmejdrech@…>, 15 years ago
  • code reorganization (no functional change)
  • Property mode set to 100644
File size: 4.3 KB
RevLine 
[21580dd]1/*
2 * Copyright (c) 2009 Lukas Mejdrech
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 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup net
30 * @{
31 */
32
33/** @file
34 * General CRC and checksum computation implementation.
35 */
36
37#include <sys/types.h>
38
39#include "include/checksum.h"
40
41/** Big-endian encoding CRC divider.
42 */
43#define CRC_DIVIDER_BE 0x04C11DB7
44
45/** Little-endian encoding CRC divider.
46 */
47#define CRC_DIVIDER_LE 0xEDB88320
48
[a64c64d]49uint16_t compact_checksum(uint32_t sum){
50 // shorten to the 16 bits
51 while(sum >> 16){
52 sum = (sum &0xFFFF) + (sum >> 16);
53 }
54
55 return (uint16_t) sum;
56}
57
58uint32_t compute_checksum(uint32_t seed, uint8_t * data, size_t length){
[aadf01e]59 size_t index;
60
[a64c64d]61 // sum all the 16 bit fields
62 for(index = 0; index + 1 < length; index += 2){
63 seed += (data[index] << 8) + data[index + 1];
[21580dd]64 }
[a64c64d]65
66 // last odd byte with zero padding
67 if(index + 1 == length){
68 seed += data[index] << 8;
[21580dd]69 }
[a64c64d]70
[21580dd]71 return seed;
72}
73
[aadf01e]74uint32_t compute_crc32_be(uint32_t seed, uint8_t * data, size_t length){
75 size_t index;
[21580dd]76
[a64c64d]77 // process full bytes
[aadf01e]78 while(length >= 8){
[a64c64d]79 // add the data
[aadf01e]80 seed ^= (*data) << 24;
[a64c64d]81 // for each added bit
[aadf01e]82 for(index = 0; index < 8; ++ index){
[a64c64d]83 // if the first bit is set
[aadf01e]84 if(seed &0x80000000){
[a64c64d]85 // shift and divide the checksum
[aadf01e]86 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
[21580dd]87 }else{
[a64c64d]88 // shift otherwise
[21580dd]89 seed <<= 1;
90 }
91 }
[a64c64d]92 // move to the next byte
[21580dd]93 ++ data;
94 length -= 8;
95 }
[a64c64d]96
97 // process the odd bits
[aadf01e]98 if(length > 0){
[a64c64d]99 // add the data with zero padding
[aadf01e]100 seed ^= ((*data) &(0xFF << (8 - length))) << 24;
[a64c64d]101 // for each added bit
[aadf01e]102 for(index = 0; index < length; ++ index){
[a64c64d]103 // if the first bit is set
[aadf01e]104 if(seed &0x80000000){
[a64c64d]105 // shift and divide the checksum
[aadf01e]106 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
[21580dd]107 }else{
[a64c64d]108 // shift otherwise
[21580dd]109 seed <<= 1;
110 }
111 }
112 }
[a64c64d]113
[21580dd]114 return seed;
115}
116
[a64c64d]117uint32_t compute_crc32_le(uint32_t seed, uint8_t * data, size_t length){
[aadf01e]118 size_t index;
[21580dd]119
[a64c64d]120 // process full bytes
121 while(length >= 8){
122 // add the data
123 seed ^= (*data);
124 // for each added bit
125 for(index = 0; index < 8; ++ index){
126 // if the last bit is set
127 if(seed &1){
128 // shift and divide the checksum
129 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
130 }else{
131 // shift otherwise
132 seed >>= 1;
133 }
134 }
135 // move to the next byte
136 ++ data;
137 length -= 8;
[21580dd]138 }
139
[a64c64d]140 // process the odd bits
141 if(length > 0){
142 // add the data with zero padding
143 seed ^= (*data) >> (8 - length);
144 for(index = 0; index < length; ++ index){
145 // if the last bit is set
146 if(seed &1){
147 // shift and divide the checksum
148 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
149 }else{
150 // shift otherwise
151 seed >>= 1;
152 }
153 }
[21580dd]154 }
155
156 return seed;
157}
158
[aadf01e]159uint16_t flip_checksum(uint16_t checksum){
[21580dd]160 // flip, zero is returned as 0xFFFF (not flipped)
[918e9910]161 checksum = ~ checksum;
162 return checksum ? checksum : IP_CHECKSUM_ZERO;
[21580dd]163}
164
[aadf01e]165uint16_t ip_checksum(uint8_t * data, size_t length){
[a64c64d]166 // compute, compact and flip the data checksum
[aadf01e]167 return flip_checksum(compact_checksum(compute_checksum(0, data, length)));
[21580dd]168}
169
170/** @}
171 */
Note: See TracBrowser for help on using the repository browser.