|
@@ -105,21 +105,56 @@ int trans_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
|
105
|
105
|
}
|
106
|
106
|
|
107
|
107
|
/**
|
108
|
|
- * Calculate internet checksum
|
|
108
|
+ * Calculate continued TCP/IP checkum
|
109
|
109
|
*
|
110
|
|
- * @v b Pointer to the data
|
111
|
|
- * @v len Length of data to be checksummed
|
112
|
|
- * @ret result 16 bit internet checksum
|
|
110
|
+ * @v partial Checksum of already-summed data, in network byte order
|
|
111
|
+ * @v data Data buffer
|
|
112
|
+ * @v len Length of data buffer
|
|
113
|
+ * @ret cksum Updated checksum, in network byte order
|
|
114
|
+ *
|
|
115
|
+ * Calculates a TCP/IP-style 16-bit checksum over the data block. The
|
|
116
|
+ * checksum is returned in network byte order.
|
|
117
|
+ *
|
|
118
|
+ * This function may be used to add new data to an existing checksum.
|
|
119
|
+ * The function assumes that both the old data and the new data start
|
|
120
|
+ * on even byte offsets; if this is not the case then you will need to
|
|
121
|
+ * byte-swap either the input partial checksum, the output checksum,
|
|
122
|
+ * or both. Deciding which to swap is left as an exercise for the
|
|
123
|
+ * interested reader.
|
|
124
|
+ */
|
|
125
|
+unsigned int tcpip_continue_chksum ( unsigned int partial, const void *data,
|
|
126
|
+ size_t len ) {
|
|
127
|
+ unsigned int cksum = ( ( ~partial ) & 0xffff );
|
|
128
|
+ unsigned int value;
|
|
129
|
+ unsigned int i;
|
|
130
|
+
|
|
131
|
+ for ( i = 0 ; i < len ; i++ ) {
|
|
132
|
+ value = * ( ( uint8_t * ) data + i );
|
|
133
|
+ if ( i & 1 ) {
|
|
134
|
+ /* Odd bytes: swap on little-endian systems */
|
|
135
|
+ value = be16_to_cpu ( value );
|
|
136
|
+ } else {
|
|
137
|
+ /* Even bytes: swap on big-endian systems */
|
|
138
|
+ value = le16_to_cpu ( value );
|
|
139
|
+ }
|
|
140
|
+ cksum += value;
|
|
141
|
+ if ( cksum > 0xffff )
|
|
142
|
+ cksum -= 0xffff;
|
|
143
|
+ }
|
|
144
|
+
|
|
145
|
+ return ( ( ~cksum ) & 0xffff );
|
|
146
|
+}
|
|
147
|
+
|
|
148
|
+/**
|
|
149
|
+ * Calculate TCP/IP checkum
|
|
150
|
+ *
|
|
151
|
+ * @v data Data buffer
|
|
152
|
+ * @v len Length of data buffer
|
|
153
|
+ * @ret cksum Checksum, in network byte order
|
|
154
|
+ *
|
|
155
|
+ * Calculates a TCP/IP-style 16-bit checksum over the data block. The
|
|
156
|
+ * checksum is returned in network byte order.
|
113
|
157
|
*/
|
114
|
|
-uint16_t calc_chksum(void *b, int len) {
|
115
|
|
- uint16_t *buf = b, result;
|
116
|
|
- uint16_t sum=0;
|
117
|
|
- for ( sum = 0; len > 1; len -= 2 ) /* Sum all 16b words */
|
118
|
|
- sum += *buf++;
|
119
|
|
- if ( len == 1 ) /* If any stray bytes, */
|
120
|
|
- sum += *(unsigned char*)buf; /* add to sum */
|
121
|
|
- sum = (sum >> 16) + (sum & 0xffff); /* Add the carry */
|
122
|
|
- sum += (sum >> 16); /* (again) */
|
123
|
|
- result = ~sum; /* Take the one's complement */
|
124
|
|
- return result; /* Return 16b value */
|
|
158
|
+unsigned int tcpip_chksum ( const void *data, size_t len ) {
|
|
159
|
+ return tcpip_continue_chksum ( 0xffff, data, len );
|
125
|
160
|
}
|