Changeset 4687a26c in mainline for uspace/lib/net/generic/net_checksum.c
 Timestamp:
 20101102T18:29:01Z (13 years ago)
 Branches:
 lfn, master, serial, ticket/834toolchainupdate, topic/msimupgrade
 Children:
 4f35b9ff
 Parents:
 76e1121f (diff), 28f4adb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent.  File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

uspace/lib/net/generic/net_checksum.c
r76e1121f r4687a26c 27 27 */ 28 28 29 /** @addtogroup net30 * 29 /** @addtogroup libnet 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 34 * General CRC and checksum computation implementation. 35 35 */ 36 36 … … 39 39 #include <net_checksum.h> 40 40 41 /** Bigendian encoding CRC divider. 42 */ 43 #define CRC_DIVIDER_BE 0x04C11DB7 44 45 /** Littleendian encoding CRC divider. 46 */ 47 #define CRC_DIVIDER_LE 0xEDB88320 48 49 uint16_t compact_checksum(uint32_t sum){ 41 /** Bigendian encoding CRC divider. */ 42 #define CRC_DIVIDER_BE 0x04c11db7 43 44 /** Littleendian encoding CRC divider. */ 45 #define CRC_DIVIDER_LE 0xedb88320 46 47 /** Compacts the computed checksum to the 16 bit number adding the carries. 48 * 49 * @param[in] sum Computed checksum. 50 * @returns Compacted computed checksum to the 16 bits. 51 */ 52 uint16_t compact_checksum(uint32_t sum) 53 { 50 54 // shorten to the 16 bits 51 while(sum >> 16){ 52 sum = (sum &0xFFFF) + (sum >> 16); 53 } 55 while (sum >> 16) 56 sum = (sum & 0xffff) + (sum >> 16); 54 57 55 58 return (uint16_t) sum; 56 59 } 57 60 58 uint32_t compute_checksum(uint32_t seed, uint8_t * data, size_t length){ 61 /** Computes sum of the 2 byte fields. 62 * 63 * Padds one zero (0) byte if odd. 64 * 65 * @param[in] seed Initial value. Often used as 0 or ~0. 66 * @param[in] data Pointer to the beginning of data to process. 67 * @param[in] length Length of the data in bytes. 68 * @returns The computed checksum of the length bytes of the data. 69 */ 70 uint32_t compute_checksum(uint32_t seed, uint8_t *data, size_t length) 71 { 59 72 size_t index; 60 73 61 74 // sum all the 16 bit fields 62 for (index = 0; index + 1 < length; index += 2){75 for (index = 0; index + 1 < length; index += 2) 63 76 seed += (data[index] << 8) + data[index + 1]; 64 }65 77 66 78 // last odd byte with zero padding 67 if (index + 1 == length){79 if (index + 1 == length) 68 80 seed += data[index] << 8; 69 }70 81 71 82 return seed; 72 83 } 73 84 74 uint32_t compute_crc32_be(uint32_t seed, uint8_t * data, size_t length){ 85 /** Computes CRC32 value in the bigendian environment. 86 * 87 * @param[in] seed Initial value. Often used as 0 or ~0. 88 * @param[in] data Pointer to the beginning of data to process. 89 * @param[in] length Length of the data in bits. 90 * @returns The computed CRC32 of the length bits of the data. 91 */ 92 uint32_t compute_crc32_be(uint32_t seed, uint8_t * data, size_t length) 93 { 75 94 size_t index; 76 95 77 96 // process full bytes 78 while (length >= 8){97 while (length >= 8) { 79 98 // add the data 80 99 seed ^= (*data) << 24; 100 81 101 // for each added bit 82 for (index = 0; index < 8; ++ index){102 for (index = 0; index < 8; ++index) { 83 103 // if the first bit is set 84 if (seed &0x80000000){104 if (seed & 0x80000000) { 85 105 // shift and divide the checksum 86 106 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE); 87 } else{107 } else { 88 108 // shift otherwise 89 109 seed <<= 1; 90 110 } 91 111 } 112 92 113 // move to the next byte 93 ++ 114 ++data; 94 115 length = 8; 95 116 } 96 117 97 118 // process the odd bits 98 if (length > 0){119 if (length > 0) { 99 120 // add the data with zero padding 100 seed ^= ((*data) &(0xFF << (8  length))) << 24; 121 seed ^= ((*data) & (0xff << (8  length))) << 24; 122 101 123 // for each added bit 102 for (index = 0; index < length; ++ index){124 for (index = 0; index < length; ++index) { 103 125 // if the first bit is set 104 if (seed &0x80000000){126 if (seed & 0x80000000) { 105 127 // shift and divide the checksum 106 128 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE); 107 } else{129 } else { 108 130 // shift otherwise 109 131 seed <<= 1; … … 115 137 } 116 138 117 uint32_t compute_crc32_le(uint32_t seed, uint8_t * data, size_t length){ 139 /** Computes CRC32 value in the littleendian environment. 140 * 141 * @param[in] seed Initial value. Often used as 0 or ~0. 142 * @param[in] data Pointer to the beginning of data to process. 143 * @param[in] length Length of the data in bits. 144 * @returns The computed CRC32 of the length bits of the data. 145 */ 146 uint32_t compute_crc32_le(uint32_t seed, uint8_t * data, size_t length) 147 { 118 148 size_t index; 119 149 120 150 // process full bytes 121 while (length >= 8){151 while (length >= 8) { 122 152 // add the data 123 153 seed ^= (*data); 154 124 155 // for each added bit 125 for (index = 0; index < 8; ++ index){156 for (index = 0; index < 8; ++index) { 126 157 // if the last bit is set 127 if (seed &1){158 if (seed & 1) { 128 159 // shift and divide the checksum 129 160 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE); 130 } else{161 } else { 131 162 // shift otherwise 132 163 seed >>= 1; 133 164 } 134 165 } 166 135 167 // move to the next byte 136 ++ 168 ++data; 137 169 length = 8; 138 170 } 139 171 140 172 // process the odd bits 141 if (length > 0){173 if (length > 0) { 142 174 // add the data with zero padding 143 175 seed ^= (*data) >> (8  length); 144 for(index = 0; index < length; ++ index){ 176 177 for (index = 0; index < length; ++index) { 145 178 // if the last bit is set 146 if (seed &1){179 if (seed & 1) { 147 180 // shift and divide the checksum 148 181 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE); 149 } else{182 } else { 150 183 // shift otherwise 151 184 seed >>= 1; … … 157 190 } 158 191 159 uint16_t flip_checksum(uint16_t checksum){ 192 /** Returns or flips the checksum if zero. 193 * 194 * @param[in] checksum The computed checksum. 195 * @returns The internet protocol header checksum. 196 * @returns 0xFFFF if the computed checksum is zero. 197 */ 198 uint16_t flip_checksum(uint16_t checksum) 199 { 160 200 // flip, zero is returned as 0xFFFF (not flipped) 161 checksum = ~ 201 checksum = ~checksum; 162 202 return checksum ? checksum : IP_CHECKSUM_ZERO; 163 203 } 164 204 165 uint16_t ip_checksum(uint8_t * data, size_t length){ 205 /** Computes the ip header checksum. 206 * 207 * To compute the checksum of a new packet, the checksum header field must be 208 * zero. To check the checksum of a received packet, the checksum may be left 209 * set. Zero will be returned in this case if valid. 210 * 211 * @param[in] data The header data. 212 * @param[in] length The header length in bytes. 213 * @returns The internet protocol header checksum. 214 * @returns 0xFFFF if the computed checksum is zero. 215 */ 216 uint16_t ip_checksum(uint8_t *data, size_t length) 217 { 166 218 // compute, compact and flip the data checksum 167 return flip_checksum(compact_checksum(compute_checksum(0, data, length))); 219 return flip_checksum(compact_checksum(compute_checksum(0, data, 220 length))); 168 221 } 169 222
Note:
See TracChangeset
for help on using the changeset viewer.