source: mainline/uspace/srv/net/checksum.c@ a64c64d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a64c64d 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
Line 
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
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){
59 size_t index;
60
61 // sum all the 16 bit fields
62 for(index = 0; index + 1 < length; index += 2){
63 seed += (data[index] << 8) + data[index + 1];
64 }
65
66 // last odd byte with zero padding
67 if(index + 1 == length){
68 seed += data[index] << 8;
69 }
70
71 return seed;
72}
73
74uint32_t compute_crc32_be(uint32_t seed, uint8_t * data, size_t length){
75 size_t index;
76
77 // process full bytes
78 while(length >= 8){
79 // add the data
80 seed ^= (*data) << 24;
81 // for each added bit
82 for(index = 0; index < 8; ++ index){
83 // if the first bit is set
84 if(seed &0x80000000){
85 // shift and divide the checksum
86 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
87 }else{
88 // shift otherwise
89 seed <<= 1;
90 }
91 }
92 // move to the next byte
93 ++ data;
94 length -= 8;
95 }
96
97 // process the odd bits
98 if(length > 0){
99 // add the data with zero padding
100 seed ^= ((*data) &(0xFF << (8 - length))) << 24;
101 // for each added bit
102 for(index = 0; index < length; ++ index){
103 // if the first bit is set
104 if(seed &0x80000000){
105 // shift and divide the checksum
106 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
107 }else{
108 // shift otherwise
109 seed <<= 1;
110 }
111 }
112 }
113
114 return seed;
115}
116
117uint32_t compute_crc32_le(uint32_t seed, uint8_t * data, size_t length){
118 size_t index;
119
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;
138 }
139
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 }
154 }
155
156 return seed;
157}
158
159uint16_t flip_checksum(uint16_t checksum){
160 // flip, zero is returned as 0xFFFF (not flipped)
161 checksum = ~ checksum;
162 return checksum ? checksum : IP_CHECKSUM_ZERO;
163}
164
165uint16_t ip_checksum(uint8_t * data, size_t length){
166 // compute, compact and flip the data checksum
167 return flip_checksum(compact_checksum(compute_checksum(0, data, length)));
168}
169
170/** @}
171 */
Note: See TracBrowser for help on using the repository browser.