Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "lwip/opt.h"
00040
00041 #include "lwip/inet_chksum.h"
00042 #include "lwip/inet.h"
00043
00044 #include <stddef.h>
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #ifndef LWIP_CHKSUM
00058 # define LWIP_CHKSUM lwip_standard_chksum
00059 # ifndef LWIP_CHKSUM_ALGORITHM
00060 # define LWIP_CHKSUM_ALGORITHM 1
00061 # endif
00062 #endif
00063
00064 #ifndef LWIP_CHKSUM_ALGORITHM
00065 # define LWIP_CHKSUM_ALGORITHM 0
00066 #endif
00067
00068
00069 #if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)
00070
00071 #define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w)
00072 #else
00073
00074 #define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8)
00075 #endif
00076
00077
00078 #define FOLD_U32T(u) ((u >> 16) + (u & 0x0000ffffUL))
00079
00080 #if (LWIP_CHKSUM_ALGORITHM == 1)
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 static u16_t
00092 lwip_standard_chksum(void *dataptr, u16_t len)
00093 {
00094 u32_t acc;
00095 u16_t src;
00096 u8_t *octetptr;
00097
00098 acc = 0;
00099
00100 octetptr = (u8_t*)dataptr;
00101 while (len > 1) {
00102
00103
00104 src = (*octetptr) << 8;
00105 octetptr++;
00106
00107 src |= (*octetptr);
00108 octetptr++;
00109 acc += src;
00110 len -= 2;
00111 }
00112 if (len > 0) {
00113
00114 src = (*octetptr) << 8;
00115 acc += src;
00116 }
00117
00118 acc = (acc >> 16) + (acc & 0x0000ffffUL);
00119 if ((acc & 0xffff0000UL) != 0) {
00120 acc = (acc >> 16) + (acc & 0x0000ffffUL);
00121 }
00122
00123
00124
00125 return htons((u16_t)acc);
00126 }
00127 #endif
00128
00129 #if (LWIP_CHKSUM_ALGORITHM == 2)
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 static u16_t
00146 lwip_standard_chksum(void *dataptr, int len)
00147 {
00148 u8_t *pb = dataptr;
00149 u16_t *ps, t = 0;
00150 u32_t sum = 0;
00151 int odd = ((u32_t)pb & 1);
00152
00153
00154 if (odd && len > 0) {
00155 ((u8_t *)&t)[1] = *pb++;
00156 len--;
00157 }
00158
00159
00160 ps = (u16_t *)pb;
00161 while (len > 1) {
00162 sum += *ps++;
00163 len -= 2;
00164 }
00165
00166
00167 if (len > 0) {
00168 ((u8_t *)&t)[0] = *(u8_t *)ps;;
00169 }
00170
00171
00172 sum += t;
00173
00174
00175
00176 sum = FOLD_U32T(sum);
00177 sum = FOLD_U32T(sum);
00178
00179
00180 if (odd) {
00181 sum = SWAP_BYTES_IN_WORD(sum);
00182 }
00183
00184 return sum;
00185 }
00186 #endif
00187
00188 #if (LWIP_CHKSUM_ALGORITHM == 3)
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 static u16_t
00202 lwip_standard_chksum(void *dataptr, int len)
00203 {
00204 u8_t *pb = dataptr;
00205 u16_t *ps, t = 0;
00206 u32_t *pl;
00207 u32_t sum = 0, tmp;
00208
00209 int odd = ((u32_t)pb & 1);
00210
00211 if (odd && len > 0) {
00212 ((u8_t *)&t)[1] = *pb++;
00213 len--;
00214 }
00215
00216 ps = (u16_t *)pb;
00217
00218 if (((u32_t)ps & 3) && len > 1) {
00219 sum += *ps++;
00220 len -= 2;
00221 }
00222
00223 pl = (u32_t *)ps;
00224
00225 while (len > 7) {
00226 tmp = sum + *pl++;
00227 if (tmp < sum) {
00228 tmp++;
00229 }
00230
00231 sum = tmp + *pl++;
00232 if (sum < tmp) {
00233 sum++;
00234 }
00235
00236 len -= 8;
00237 }
00238
00239
00240 sum = FOLD_U32T(sum);
00241
00242 ps = (u16_t *)pl;
00243
00244
00245 while (len > 1) {
00246 sum += *ps++;
00247 len -= 2;
00248 }
00249
00250
00251 if (len > 0) {
00252 ((u8_t *)&t)[0] = *(u8_t *)ps;
00253 }
00254
00255 sum += t;
00256
00257
00258
00259 sum = FOLD_U32T(sum);
00260 sum = FOLD_U32T(sum);
00261
00262 if (odd) {
00263 sum = SWAP_BYTES_IN_WORD(sum);
00264 }
00265
00266 return sum;
00267 }
00268 #endif
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 u16_t
00283 inet_chksum_pseudo(struct pbuf *p,
00284 struct ip_addr *src, struct ip_addr *dest,
00285 u8_t proto, u16_t proto_len)
00286 {
00287 u32_t acc;
00288 struct pbuf *q;
00289 u8_t swapped;
00290
00291 acc = 0;
00292 swapped = 0;
00293
00294 for(q = p; q != NULL; q = q->next) {
00295 LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
00296 (void *)q, (void *)q->next));
00297 acc += LWIP_CHKSUM(q->payload, q->len);
00298
00299
00300
00301 acc = FOLD_U32T(acc);
00302 if (q->len % 2 != 0) {
00303 swapped = 1 - swapped;
00304 acc = SWAP_BYTES_IN_WORD(acc);
00305 }
00306
00307 }
00308
00309 if (swapped) {
00310 acc = SWAP_BYTES_IN_WORD(acc);
00311 }
00312 acc += (src->addr & 0xffffUL);
00313 acc += ((src->addr >> 16) & 0xffffUL);
00314 acc += (dest->addr & 0xffffUL);
00315 acc += ((dest->addr >> 16) & 0xffffUL);
00316 acc += (u32_t)htons((u16_t)proto);
00317 acc += (u32_t)htons(proto_len);
00318
00319
00320
00321 acc = FOLD_U32T(acc);
00322 acc = FOLD_U32T(acc);
00323 LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
00324 return (u16_t)~(acc & 0xffffUL);
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 #if LWIP_UDPLITE
00341 u16_t
00342 inet_chksum_pseudo_partial(struct pbuf *p,
00343 struct ip_addr *src, struct ip_addr *dest,
00344 u8_t proto, u16_t proto_len, u16_t chksum_len)
00345 {
00346 u32_t acc;
00347 struct pbuf *q;
00348 u8_t swapped;
00349 u16_t chklen;
00350
00351 acc = 0;
00352 swapped = 0;
00353
00354 for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) {
00355 LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
00356 (void *)q, (void *)q->next));
00357 chklen = q->len;
00358 if (chklen > chksum_len) {
00359 chklen = chksum_len;
00360 }
00361 acc += LWIP_CHKSUM(q->payload, chklen);
00362 chksum_len -= chklen;
00363 LWIP_ASSERT("delete me", chksum_len < 0x7fff);
00364
00365
00366 acc = FOLD_U32T(acc);
00367 if (q->len % 2 != 0) {
00368 swapped = 1 - swapped;
00369 acc = SWAP_BYTES_IN_WORD(acc);
00370 }
00371
00372 }
00373
00374 if (swapped) {
00375 acc = SWAP_BYTES_IN_WORD(acc);
00376 }
00377 acc += (src->addr & 0xffffUL);
00378 acc += ((src->addr >> 16) & 0xffffUL);
00379 acc += (dest->addr & 0xffffUL);
00380 acc += ((dest->addr >> 16) & 0xffffUL);
00381 acc += (u32_t)htons((u16_t)proto);
00382 acc += (u32_t)htons(proto_len);
00383
00384
00385
00386 acc = FOLD_U32T(acc);
00387 acc = FOLD_U32T(acc);
00388 LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
00389 return (u16_t)~(acc & 0xffffUL);
00390 }
00391 #endif
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 u16_t
00404 inet_chksum(void *dataptr, u16_t len)
00405 {
00406 return ~LWIP_CHKSUM(dataptr, len);
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416 u16_t
00417 inet_chksum_pbuf(struct pbuf *p)
00418 {
00419 u32_t acc;
00420 struct pbuf *q;
00421 u8_t swapped;
00422
00423 acc = 0;
00424 swapped = 0;
00425 for(q = p; q != NULL; q = q->next) {
00426 acc += LWIP_CHKSUM(q->payload, q->len);
00427 acc = FOLD_U32T(acc);
00428 if (q->len % 2 != 0) {
00429 swapped = 1 - swapped;
00430 acc = SWAP_BYTES_IN_WORD(acc);
00431 }
00432 }
00433
00434 if (swapped) {
00435 acc = SWAP_BYTES_IN_WORD(acc);
00436 }
00437 return (u16_t)~(acc & 0xffffUL);
00438 }