Changes in uspace/lib/net/generic/net_checksum.c [8d601db:849ed54] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/net/generic/net_checksum.c
r8d601db r849ed54 27 27 */ 28 28 29 /** @addtogroup libnet30 * @{29 /** @addtogroup net 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * General CRC and checksum computation implementation.34 * General CRC and checksum computation implementation. 35 35 */ 36 36 … … 39 39 #include <net_checksum.h> 40 40 41 /** Big-endian encoding CRC divider. */ 42 #define CRC_DIVIDER_BE 0x04c11db7 41 /** Big-endian encoding CRC divider. 42 */ 43 #define CRC_DIVIDER_BE 0x04C11DB7 43 44 44 /** Little-endian encoding CRC divider. */ 45 #define CRC_DIVIDER_LE 0xedb88320 45 /** Little-endian encoding CRC divider. 46 */ 47 #define CRC_DIVIDER_LE 0xEDB88320 46 48 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 { 49 uint16_t compact_checksum(uint32_t sum){ 54 50 // shorten to the 16 bits 55 while (sum >> 16) 56 sum = (sum & 0xffff) + (sum >> 16); 51 while(sum >> 16){ 52 sum = (sum &0xFFFF) + (sum >> 16); 53 } 57 54 58 55 return (uint16_t) sum; 59 56 } 60 57 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 { 58 uint32_t compute_checksum(uint32_t seed, uint8_t * data, size_t length){ 72 59 size_t index; 73 60 74 61 // sum all the 16 bit fields 75 for (index = 0; index + 1 < length; index += 2)62 for(index = 0; index + 1 < length; index += 2){ 76 63 seed += (data[index] << 8) + data[index + 1]; 64 } 77 65 78 66 // last odd byte with zero padding 79 if (index + 1 == length)67 if(index + 1 == length){ 80 68 seed += data[index] << 8; 69 } 81 70 82 71 return seed; 83 72 } 84 73 85 /** Computes CRC32 value in the big-endian 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 { 74 uint32_t compute_crc32_be(uint32_t seed, uint8_t * data, size_t length){ 94 75 size_t index; 95 76 96 77 // process full bytes 97 while (length >= 8){78 while(length >= 8){ 98 79 // add the data 99 80 seed ^= (*data) << 24; 100 101 81 // for each added bit 102 for (index = 0; index < 8; ++index){82 for(index = 0; index < 8; ++ index){ 103 83 // if the first bit is set 104 if (seed & 0x80000000){84 if(seed &0x80000000){ 105 85 // shift and divide the checksum 106 86 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE); 107 } else{87 }else{ 108 88 // shift otherwise 109 89 seed <<= 1; 110 90 } 111 91 } 112 113 92 // move to the next byte 114 ++ data;93 ++ data; 115 94 length -= 8; 116 95 } 117 96 118 97 // process the odd bits 119 if (length > 0){98 if(length > 0){ 120 99 // add the data with zero padding 121 seed ^= ((*data) & (0xff << (8 - length))) << 24; 122 100 seed ^= ((*data) &(0xFF << (8 - length))) << 24; 123 101 // for each added bit 124 for (index = 0; index < length; ++index){102 for(index = 0; index < length; ++ index){ 125 103 // if the first bit is set 126 if (seed & 0x80000000){104 if(seed &0x80000000){ 127 105 // shift and divide the checksum 128 106 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE); 129 } else{107 }else{ 130 108 // shift otherwise 131 109 seed <<= 1; … … 137 115 } 138 116 139 /** Computes CRC32 value in the little-endian 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 { 117 uint32_t compute_crc32_le(uint32_t seed, uint8_t * data, size_t length){ 148 118 size_t index; 149 119 150 120 // process full bytes 151 while (length >= 8){121 while(length >= 8){ 152 122 // add the data 153 123 seed ^= (*data); 154 155 124 // for each added bit 156 for (index = 0; index < 8; ++index){125 for(index = 0; index < 8; ++ index){ 157 126 // if the last bit is set 158 if (seed & 1){127 if(seed &1){ 159 128 // shift and divide the checksum 160 129 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE); 161 } else{130 }else{ 162 131 // shift otherwise 163 132 seed >>= 1; 164 133 } 165 134 } 166 167 135 // move to the next byte 168 ++ data;136 ++ data; 169 137 length -= 8; 170 138 } 171 139 172 140 // process the odd bits 173 if (length > 0){141 if(length > 0){ 174 142 // add the data with zero padding 175 143 seed ^= (*data) >> (8 - length); 176 177 for (index = 0; index < length; ++index) { 144 for(index = 0; index < length; ++ index){ 178 145 // if the last bit is set 179 if (seed & 1){146 if(seed &1){ 180 147 // shift and divide the checksum 181 148 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE); 182 } else{149 }else{ 183 150 // shift otherwise 184 151 seed >>= 1; … … 190 157 } 191 158 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 { 159 uint16_t flip_checksum(uint16_t checksum){ 200 160 // flip, zero is returned as 0xFFFF (not flipped) 201 checksum = ~ checksum;161 checksum = ~ checksum; 202 162 return checksum ? checksum : IP_CHECKSUM_ZERO; 203 163 } 204 164 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 { 165 uint16_t ip_checksum(uint8_t * data, size_t length){ 218 166 // compute, compact and flip the data checksum 219 return flip_checksum(compact_checksum(compute_checksum(0, data, 220 length))); 167 return flip_checksum(compact_checksum(compute_checksum(0, data, length))); 221 168 } 222 169
Note:
See TracChangeset
for help on using the changeset viewer.