source: mainline/uspace/srv/net/checksum.c@ 5297fe8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5297fe8 was 918e9910, checked in by Lukas Mejdrech <lukasmejdrech@…>, 16 years ago
  • zero IP checksum flip fix
  • Property mode set to 100644
File size: 3.7 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
49uint32_t compute_crc32_le( uint32_t seed, uint8_t * data, size_t length ){
50 size_t index;
51
52 while( length >= 8 ){
53 seed ^= ( * data );
54 for( index = 0; index < 8; ++ index ){
55 if( seed & 1 ){
56 seed = ( seed >> 1 ) ^ (( uint32_t ) CRC_DIVIDER_LE );
57 }else{
58 seed >>= 1;
59 }
60 }
61 ++ data;
62 length -= 8;
63 }
64 if( length > 0 ){
65 seed ^= ( * data ) >> ( 8 - length );
66 for( index = 0; index < length; ++ index ){
67 if( seed & 1 ){
68 seed = ( seed >> 1 ) ^ (( uint32_t ) CRC_DIVIDER_LE );
69 }else{
70 seed >>= 1;
71 }
72 }
73 length -= 8;
74 }
75 return seed;
76}
77
78uint32_t compute_crc32_be( uint32_t seed, uint8_t * data, size_t length ){
79 size_t index;
80
81 while( length >= 8 ){
82 seed ^= ( * data ) << 24;
83 for( index = 0; index < 8; ++ index ){
84 if( seed & 0x80000000 ){
85 seed = ( seed << 1 ) ^ (( uint32_t ) CRC_DIVIDER_BE );
86 }else{
87 seed <<= 1;
88 }
89 }
90 ++ data;
91 length -= 8;
92 }
93 if( length > 0 ){
94 seed ^= (( * data ) & ( 0xFF << ( 8 - length ))) << 24;
95 for( index = 0; index < length; ++ index ){
96 if( seed & 0x80000000 ){
97 seed = ( seed << 1 ) ^ (( uint32_t ) CRC_DIVIDER_BE );
98 }else{
99 seed <<= 1;
100 }
101 }
102 length -= 8;
103 }
104 return seed;
105}
106
107uint32_t compute_checksum( uint32_t seed, uint8_t * data, size_t length ){
108 size_t index;
109
110 // sum all the 16 bit fields
111 for( index = 0; index + 1 < length; index += 2 ){
112 seed += ( data[ index ] << 8 ) + data[ index + 1 ];
113 }
114
115 // last odd byte with zero padding
116 if( index + 1 == length ){
117 seed += data[ index ] << 8;
118 }
119
120 return seed;
121}
122
123uint16_t compact_checksum( uint32_t sum ){
124 // shorten to the 16 bits
125 while( sum >> 16 ) sum = ( sum & 0xFFFF ) + ( sum >> 16 );
126
127 return ( uint16_t ) sum;
128}
129
130uint16_t flip_checksum( uint16_t checksum ){
131 // flip, zero is returned as 0xFFFF (not flipped)
132 checksum = ~ checksum;
133 return checksum ? checksum : IP_CHECKSUM_ZERO;
134}
135
136uint16_t ip_checksum( uint8_t * data, size_t length ){
137 return flip_checksum( compact_checksum( compute_checksum( 0, data, length )));
138}
139
140/** @}
141 */
Note: See TracBrowser for help on using the repository browser.