Changeset 89c57b6 in mainline for uspace/lib/net/generic/net_checksum.c
- Timestamp:
- 2011-04-13T14:45:41Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 88634420
- Parents:
- cefb126 (diff), 17279ead (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
rcefb126 r89c57b6 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 /** 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 49 uint16_t compact_checksum(uint32_t sum){ 50 // shorten to the 16 bits 51 while(sum >> 16){ 52 sum = (sum &0xFFFF) + (sum >> 16); 53 } 41 /** Big-endian encoding CRC divider. */ 42 #define CRC_DIVIDER_BE 0x04c11db7 43 44 /** Little-endian 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 * @return Compacted computed checksum to the 16 bits. 51 */ 52 uint16_t compact_checksum(uint32_t sum) 53 { 54 /* Shorten to the 16 bits */ 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 * @return 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 / / sum all the 16 bit fields62 for (index = 0; index + 1 < length; index += 2){74 /* Sum all the 16 bit fields */ 75 for (index = 0; index + 1 < length; index += 2) 63 76 seed += (data[index] << 8) + data[index + 1]; 64 } 65 66 // last odd byte with zero padding 67 if(index + 1 == length){ 77 78 /* Last odd byte with zero padding */ 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 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 * @return 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 / / process full bytes78 while (length >= 8){79 / / add the data96 /* Process full bytes */ 97 while (length >= 8) { 98 /* Add the data */ 80 99 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 100 101 /* For each added bit */ 102 for (index = 0; index < 8; ++index) { 103 /* If the first bit is set */ 104 if (seed & 0x80000000) { 105 /* Shift and divide the checksum */ 86 106 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE); 87 } else{88 / / shift otherwise107 } else { 108 /* Shift otherwise */ 89 109 seed <<= 1; 90 110 } 91 111 } 92 // move to the next byte 93 ++ data; 112 113 /* Move to the next byte */ 114 ++data; 94 115 length -= 8; 95 116 } 96 117 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 118 /* Process the odd bits */ 119 if (length > 0) { 120 /* Add the data with zero padding */ 121 seed ^= ((*data) & (0xff << (8 - length))) << 24; 122 123 /* For each added bit */ 124 for (index = 0; index < length; ++index) { 125 /* If the first bit is set */ 126 if (seed & 0x80000000) { 127 /* Shift and divide the checksum */ 106 128 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE); 107 } else{108 / / shift otherwise129 } else { 130 /* Shift otherwise */ 109 131 seed <<= 1; 110 132 } … … 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 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 * @return 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 / / process full bytes121 while (length >= 8){122 / / add the data150 /* Process full bytes */ 151 while (length >= 8) { 152 /* Add the data */ 123 153 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 154 155 /* For each added bit */ 156 for (index = 0; index < 8; ++index) { 157 /* If the last bit is set */ 158 if (seed & 1) { 159 /* Shift and divide the checksum */ 129 160 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE); 130 } else{131 / / shift otherwise161 } else { 162 /* Shift otherwise */ 132 163 seed >>= 1; 133 164 } 134 165 } 135 // move to the next byte 136 ++ data; 166 167 /* Move to the next byte */ 168 ++data; 137 169 length -= 8; 138 170 } 139 171 140 / / process the odd bits141 if (length > 0){142 / / add the data with zero padding172 /* Process the odd bits */ 173 if (length > 0) { 174 /* Add the data with zero padding */ 143 175 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 176 177 for (index = 0; index < length; ++index) { 178 /* If the last bit is set */ 179 if (seed & 1) { 180 /* Shift and divide the checksum */ 148 181 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE); 149 } else{150 / / shift otherwise182 } else { 183 /* Shift otherwise */ 151 184 seed >>= 1; 152 185 } … … 157 190 } 158 191 159 uint16_t flip_checksum(uint16_t checksum){ 160 // flip, zero is returned as 0xFFFF (not flipped) 161 checksum = ~ checksum; 192 /** Returns or flips the checksum if zero. 193 * 194 * @param[in] checksum The computed checksum. 195 * @return The internet protocol header checksum. 196 * @return 0xFFFF if the computed checksum is zero. 197 */ 198 uint16_t flip_checksum(uint16_t checksum) 199 { 200 /* Flip, zero is returned as 0xFFFF (not flipped) */ 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){ 166 // compute, compact and flip the data checksum 167 return flip_checksum(compact_checksum(compute_checksum(0, data, 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 * @return The internet protocol header checksum. 214 * @return 0xFFFF if the computed checksum is zero. 215 */ 216 uint16_t ip_checksum(uint8_t *data, size_t length) 217 { 218 /* Compute, compact and flip the data checksum */ 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.