Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
lwip_inet_chksum.c
00001 /** 00002 * @file 00003 * Incluse internet checksum functions. 00004 * 00005 */ 00006 00007 /* 00008 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * This file is part of the lwIP TCP/IP stack. 00034 * 00035 * Author: Adam Dunkels <adam@sics.se> 00036 * 00037 */ 00038 00039 #include "lwip/opt.h" 00040 00041 #include "lwip/inet_chksum.h" 00042 #include "lwip/def.h" 00043 #include "lwip/ip_addr.h" 00044 00045 #include <stddef.h> 00046 #include <string.h> 00047 00048 /* These are some reference implementations of the checksum algorithm, with the 00049 * aim of being simple, correct and fully portable. Checksumming is the 00050 * first thing you would want to optimize for your platform. If you create 00051 * your own version, link it in and in your cc.h put: 00052 * 00053 * #define LWIP_CHKSUM <your_checksum_routine> 00054 * 00055 * Or you can select from the implementations below by defining 00056 * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. 00057 */ 00058 00059 #ifndef LWIP_CHKSUM 00060 # define LWIP_CHKSUM lwip_standard_chksum 00061 # ifndef LWIP_CHKSUM_ALGORITHM 00062 # define LWIP_CHKSUM_ALGORITHM 2 00063 # endif 00064 u16_t lwip_standard_chksum(const void *dataptr, int len); 00065 #endif 00066 /* If none set: */ 00067 #ifndef LWIP_CHKSUM_ALGORITHM 00068 # define LWIP_CHKSUM_ALGORITHM 0 00069 #endif 00070 00071 #if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ 00072 /** 00073 * lwip checksum 00074 * 00075 * @param dataptr points to start of data to be summed at any boundary 00076 * @param len length of data to be summed 00077 * @return host order (!) lwip checksum (non-inverted Internet sum) 00078 * 00079 * @note accumulator size limits summable length to 64k 00080 * @note host endianess is irrelevant (p3 RFC1071) 00081 */ 00082 u16_t 00083 lwip_standard_chksum(const void *dataptr, int len) 00084 { 00085 u32_t acc; 00086 u16_t src; 00087 const u8_t *octetptr; 00088 00089 acc = 0; 00090 /* dataptr may be at odd or even addresses */ 00091 octetptr = (const u8_t*)dataptr; 00092 while (len > 1) { 00093 /* declare first octet as most significant 00094 thus assume network order, ignoring host order */ 00095 src = (*octetptr) << 8; 00096 octetptr++; 00097 /* declare second octet as least significant */ 00098 src |= (*octetptr); 00099 octetptr++; 00100 acc += src; 00101 len -= 2; 00102 } 00103 if (len > 0) { 00104 /* accumulate remaining octet */ 00105 src = (*octetptr) << 8; 00106 acc += src; 00107 } 00108 /* add deferred carry bits */ 00109 acc = (acc >> 16) + (acc & 0x0000ffffUL); 00110 if ((acc & 0xffff0000UL) != 0) { 00111 acc = (acc >> 16) + (acc & 0x0000ffffUL); 00112 } 00113 /* This maybe a little confusing: reorder sum using htons() 00114 instead of ntohs() since it has a little less call overhead. 00115 The caller must invert bits for Internet sum ! */ 00116 return htons((u16_t)acc); 00117 } 00118 #endif 00119 00120 #if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ 00121 /* 00122 * Curt McDowell 00123 * Broadcom Corp. 00124 * csm@broadcom.com 00125 * 00126 * IP checksum two bytes at a time with support for 00127 * unaligned buffer. 00128 * Works for len up to and including 0x20000. 00129 * by Curt McDowell, Broadcom Corp. 12/08/2005 00130 * 00131 * @param dataptr points to start of data to be summed at any boundary 00132 * @param len length of data to be summed 00133 * @return host order (!) lwip checksum (non-inverted Internet sum) 00134 */ 00135 u16_t 00136 lwip_standard_chksum(const void *dataptr, int len) 00137 { 00138 const u8_t *pb = (const u8_t *)dataptr; 00139 const u16_t *ps; 00140 u16_t t = 0; 00141 u32_t sum = 0; 00142 int odd = ((mem_ptr_t)pb & 1); 00143 00144 /* Get aligned to u16_t */ 00145 if (odd && len > 0) { 00146 ((u8_t *)&t)[1] = *pb++; 00147 len--; 00148 } 00149 00150 /* Add the bulk of the data */ 00151 ps = (const u16_t *)(const void *)pb; 00152 while (len > 1) { 00153 sum += *ps++; 00154 len -= 2; 00155 } 00156 00157 /* Consume left-over byte, if any */ 00158 if (len > 0) { 00159 ((u8_t *)&t)[0] = *(const u8_t *)ps; 00160 } 00161 00162 /* Add end bytes */ 00163 sum += t; 00164 00165 /* Fold 32-bit sum to 16 bits 00166 calling this twice is probably faster than if statements... */ 00167 sum = FOLD_U32T(sum); 00168 sum = FOLD_U32T(sum); 00169 00170 /* Swap if alignment was odd */ 00171 if (odd) { 00172 sum = SWAP_BYTES_IN_WORD(sum); 00173 } 00174 00175 return (u16_t)sum; 00176 } 00177 #endif 00178 00179 #if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ 00180 /** 00181 * An optimized checksum routine. Basically, it uses loop-unrolling on 00182 * the checksum loop, treating the head and tail bytes specially, whereas 00183 * the inner loop acts on 8 bytes at a time. 00184 * 00185 * @arg start of buffer to be checksummed. May be an odd byte address. 00186 * @len number of bytes in the buffer to be checksummed. 00187 * @return host order (!) lwip checksum (non-inverted Internet sum) 00188 * 00189 * by Curt McDowell, Broadcom Corp. December 8th, 2005 00190 */ 00191 u16_t 00192 lwip_standard_chksum(const void *dataptr, int len) 00193 { 00194 const u8_t *pb = (const u8_t *)dataptr; 00195 const u16_t *ps; 00196 u16_t t = 0; 00197 const u32_t *pl; 00198 u32_t sum = 0, tmp; 00199 /* starts at odd byte address? */ 00200 int odd = ((mem_ptr_t)pb & 1); 00201 00202 if (odd && len > 0) { 00203 ((u8_t *)&t)[1] = *pb++; 00204 len--; 00205 } 00206 00207 ps = (const u16_t *)(const void*)pb; 00208 00209 if (((mem_ptr_t)ps & 3) && len > 1) { 00210 sum += *ps++; 00211 len -= 2; 00212 } 00213 00214 pl = (const u32_t *)(const void*)ps; 00215 00216 while (len > 7) { 00217 tmp = sum + *pl++; /* ping */ 00218 if (tmp < sum) { 00219 tmp++; /* add back carry */ 00220 } 00221 00222 sum = tmp + *pl++; /* pong */ 00223 if (sum < tmp) { 00224 sum++; /* add back carry */ 00225 } 00226 00227 len -= 8; 00228 } 00229 00230 /* make room in upper bits */ 00231 sum = FOLD_U32T(sum); 00232 00233 ps = (const u16_t *)pl; 00234 00235 /* 16-bit aligned word remaining? */ 00236 while (len > 1) { 00237 sum += *ps++; 00238 len -= 2; 00239 } 00240 00241 /* dangling tail byte remaining? */ 00242 if (len > 0) { /* include odd byte */ 00243 ((u8_t *)&t)[0] = *(const u8_t *)ps; 00244 } 00245 00246 sum += t; /* add end bytes */ 00247 00248 /* Fold 32-bit sum to 16 bits 00249 calling this twice is probably faster than if statements... */ 00250 sum = FOLD_U32T(sum); 00251 sum = FOLD_U32T(sum); 00252 00253 if (odd) { 00254 sum = SWAP_BYTES_IN_WORD(sum); 00255 } 00256 00257 return (u16_t)sum; 00258 } 00259 #endif 00260 00261 /** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ 00262 static u16_t 00263 inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc) 00264 { 00265 struct pbuf *q; 00266 u8_t swapped = 0; 00267 00268 /* iterate through all pbuf in chain */ 00269 for (q = p; q != NULL; q = q->next) { 00270 LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", 00271 (void *)q, (void *)q->next)); 00272 acc += LWIP_CHKSUM(q->payload, q->len); 00273 /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ 00274 /* just executing this next line is probably faster that the if statement needed 00275 to check whether we really need to execute it, and does no harm */ 00276 acc = FOLD_U32T(acc); 00277 if (q->len % 2 != 0) { 00278 swapped = 1 - swapped; 00279 acc = SWAP_BYTES_IN_WORD(acc); 00280 } 00281 /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ 00282 } 00283 00284 if (swapped) { 00285 acc = SWAP_BYTES_IN_WORD(acc); 00286 } 00287 00288 acc += (u32_t)htons((u16_t)proto); 00289 acc += (u32_t)htons(proto_len); 00290 00291 /* Fold 32-bit sum to 16 bits 00292 calling this twice is probably faster than if statements... */ 00293 acc = FOLD_U32T(acc); 00294 acc = FOLD_U32T(acc); 00295 LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); 00296 return (u16_t)~(acc & 0xffffUL); 00297 } 00298 00299 #if LWIP_IPV4 00300 /* inet_chksum_pseudo: 00301 * 00302 * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. 00303 * IP addresses are expected to be in network byte order. 00304 * 00305 * @param p chain of pbufs over that a checksum should be calculated (ip data part) 00306 * @param src source ip address (used for checksum of pseudo header) 00307 * @param dst destination ip address (used for checksum of pseudo header) 00308 * @param proto ip protocol (used for checksum of pseudo header) 00309 * @param proto_len length of the ip data part (used for checksum of pseudo header) 00310 * @return checksum (as u16_t) to be saved directly in the protocol header 00311 */ 00312 u16_t 00313 inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, 00314 const ip4_addr_t *src, const ip4_addr_t *dest) 00315 { 00316 u32_t acc; 00317 u32_t addr; 00318 00319 addr = ip4_addr_get_u32(src); 00320 acc = (addr & 0xffffUL); 00321 acc += ((addr >> 16) & 0xffffUL); 00322 addr = ip4_addr_get_u32(dest); 00323 acc += (addr & 0xffffUL); 00324 acc += ((addr >> 16) & 0xffffUL); 00325 /* fold down to 16 bits */ 00326 acc = FOLD_U32T(acc); 00327 acc = FOLD_U32T(acc); 00328 00329 return inet_cksum_pseudo_base(p, proto, proto_len, acc); 00330 } 00331 #endif /* LWIP_IPV4 */ 00332 00333 #if LWIP_IPV6 00334 /** 00335 * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. 00336 * IPv6 addresses are expected to be in network byte order. 00337 * 00338 * @param p chain of pbufs over that a checksum should be calculated (ip data part) 00339 * @param proto ipv6 protocol/next header (used for checksum of pseudo header) 00340 * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) 00341 * @param src source ipv6 address (used for checksum of pseudo header) 00342 * @param dest destination ipv6 address (used for checksum of pseudo header) 00343 * @return checksum (as u16_t) to be saved directly in the protocol header 00344 */ 00345 u16_t 00346 ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, 00347 const ip6_addr_t *src, const ip6_addr_t *dest) 00348 { 00349 u32_t acc = 0; 00350 u32_t addr; 00351 u8_t addr_part; 00352 00353 for (addr_part = 0; addr_part < 4; addr_part++) { 00354 addr = src->addr[addr_part]; 00355 acc += (addr & 0xffffUL); 00356 acc += ((addr >> 16) & 0xffffUL); 00357 addr = dest->addr[addr_part]; 00358 acc += (addr & 0xffffUL); 00359 acc += ((addr >> 16) & 0xffffUL); 00360 } 00361 /* fold down to 16 bits */ 00362 acc = FOLD_U32T(acc); 00363 acc = FOLD_U32T(acc); 00364 00365 return inet_cksum_pseudo_base(p, proto, proto_len, acc); 00366 } 00367 #endif /* LWIP_IPV6 */ 00368 00369 /* ip_chksum_pseudo: 00370 * 00371 * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. 00372 * IP addresses are expected to be in network byte order. 00373 * 00374 * @param p chain of pbufs over that a checksum should be calculated (ip data part) 00375 * @param src source ip address (used for checksum of pseudo header) 00376 * @param dst destination ip address (used for checksum of pseudo header) 00377 * @param proto ip protocol (used for checksum of pseudo header) 00378 * @param proto_len length of the ip data part (used for checksum of pseudo header) 00379 * @return checksum (as u16_t) to be saved directly in the protocol header 00380 */ 00381 u16_t 00382 ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, 00383 const ip_addr_t *src, const ip_addr_t *dest) 00384 { 00385 #if LWIP_IPV6 00386 if (IP_IS_V6(dest)) { 00387 return ip6_chksum_pseudo(p, proto, proto_len, ip_2_ip6(src), ip_2_ip6(dest)); 00388 } 00389 #endif /* LWIP_IPV6 */ 00390 #if LWIP_IPV4 && LWIP_IPV6 00391 else 00392 #endif /* LWIP_IPV4 && LWIP_IPV6 */ 00393 #if LWIP_IPV4 00394 { 00395 return inet_chksum_pseudo(p, proto, proto_len, ip_2_ip4(src), ip_2_ip4(dest)); 00396 } 00397 #endif /* LWIP_IPV4 */ 00398 } 00399 00400 /** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ 00401 static u16_t 00402 inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len, 00403 u16_t chksum_len, u32_t acc) 00404 { 00405 struct pbuf *q; 00406 u8_t swapped = 0; 00407 u16_t chklen; 00408 00409 /* iterate through all pbuf in chain */ 00410 for (q = p; (q != NULL) && (chksum_len > 0); q = q->next) { 00411 LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", 00412 (void *)q, (void *)q->next)); 00413 chklen = q->len; 00414 if (chklen > chksum_len) { 00415 chklen = chksum_len; 00416 } 00417 acc += LWIP_CHKSUM(q->payload, chklen); 00418 chksum_len -= chklen; 00419 LWIP_ASSERT("delete me", chksum_len < 0x7fff); 00420 /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ 00421 /* fold the upper bit down */ 00422 acc = FOLD_U32T(acc); 00423 if (q->len % 2 != 0) { 00424 swapped = 1 - swapped; 00425 acc = SWAP_BYTES_IN_WORD(acc); 00426 } 00427 /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ 00428 } 00429 00430 if (swapped) { 00431 acc = SWAP_BYTES_IN_WORD(acc); 00432 } 00433 00434 acc += (u32_t)htons((u16_t)proto); 00435 acc += (u32_t)htons(proto_len); 00436 00437 /* Fold 32-bit sum to 16 bits 00438 calling this twice is probably faster than if statements... */ 00439 acc = FOLD_U32T(acc); 00440 acc = FOLD_U32T(acc); 00441 LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); 00442 return (u16_t)~(acc & 0xffffUL); 00443 } 00444 00445 #if LWIP_IPV4 00446 /* inet_chksum_pseudo_partial: 00447 * 00448 * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. 00449 * IP addresses are expected to be in network byte order. 00450 * 00451 * @param p chain of pbufs over that a checksum should be calculated (ip data part) 00452 * @param src source ip address (used for checksum of pseudo header) 00453 * @param dst destination ip address (used for checksum of pseudo header) 00454 * @param proto ip protocol (used for checksum of pseudo header) 00455 * @param proto_len length of the ip data part (used for checksum of pseudo header) 00456 * @return checksum (as u16_t) to be saved directly in the protocol header 00457 */ 00458 u16_t 00459 inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, 00460 u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest) 00461 { 00462 u32_t acc; 00463 u32_t addr; 00464 00465 addr = ip4_addr_get_u32(src); 00466 acc = (addr & 0xffffUL); 00467 acc += ((addr >> 16) & 0xffffUL); 00468 addr = ip4_addr_get_u32(dest); 00469 acc += (addr & 0xffffUL); 00470 acc += ((addr >> 16) & 0xffffUL); 00471 /* fold down to 16 bits */ 00472 acc = FOLD_U32T(acc); 00473 acc = FOLD_U32T(acc); 00474 00475 return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); 00476 } 00477 #endif /* LWIP_IPV4 */ 00478 00479 #if LWIP_IPV6 00480 /** 00481 * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. 00482 * IPv6 addresses are expected to be in network byte order. Will only compute for a 00483 * portion of the payload. 00484 * 00485 * @param p chain of pbufs over that a checksum should be calculated (ip data part) 00486 * @param proto ipv6 protocol/next header (used for checksum of pseudo header) 00487 * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) 00488 * @param chksum_len number of payload bytes used to compute chksum 00489 * @param src source ipv6 address (used for checksum of pseudo header) 00490 * @param dest destination ipv6 address (used for checksum of pseudo header) 00491 * @return checksum (as u16_t) to be saved directly in the protocol header 00492 */ 00493 u16_t 00494 ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, 00495 u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest) 00496 { 00497 u32_t acc = 0; 00498 u32_t addr; 00499 u8_t addr_part; 00500 00501 for (addr_part = 0; addr_part < 4; addr_part++) { 00502 addr = src->addr[addr_part]; 00503 acc += (addr & 0xffffUL); 00504 acc += ((addr >> 16) & 0xffffUL); 00505 addr = dest->addr[addr_part]; 00506 acc += (addr & 0xffffUL); 00507 acc += ((addr >> 16) & 0xffffUL); 00508 } 00509 /* fold down to 16 bits */ 00510 acc = FOLD_U32T(acc); 00511 acc = FOLD_U32T(acc); 00512 00513 return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); 00514 } 00515 #endif /* LWIP_IPV6 */ 00516 00517 /* ip_chksum_pseudo_partial: 00518 * 00519 * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. 00520 * 00521 * @param p chain of pbufs over that a checksum should be calculated (ip data part) 00522 * @param src source ip address (used for checksum of pseudo header) 00523 * @param dst destination ip address (used for checksum of pseudo header) 00524 * @param proto ip protocol (used for checksum of pseudo header) 00525 * @param proto_len length of the ip data part (used for checksum of pseudo header) 00526 * @return checksum (as u16_t) to be saved directly in the protocol header 00527 */ 00528 u16_t 00529 ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, 00530 u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest) 00531 { 00532 #if LWIP_IPV6 00533 if (IP_IS_V6(dest)) { 00534 return ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip6(src), ip_2_ip6(dest)); 00535 } 00536 #endif /* LWIP_IPV6 */ 00537 #if LWIP_IPV4 && LWIP_IPV6 00538 else 00539 #endif /* LWIP_IPV4 && LWIP_IPV6 */ 00540 #if LWIP_IPV4 00541 { 00542 return inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip4(src), ip_2_ip4(dest)); 00543 } 00544 #endif /* LWIP_IPV4 */ 00545 } 00546 00547 /* inet_chksum: 00548 * 00549 * Calculates the Internet checksum over a portion of memory. Used primarily for IP 00550 * and ICMP. 00551 * 00552 * @param dataptr start of the buffer to calculate the checksum (no alignment needed) 00553 * @param len length of the buffer to calculate the checksum 00554 * @return checksum (as u16_t) to be saved directly in the protocol header 00555 */ 00556 00557 u16_t 00558 inet_chksum(const void *dataptr, u16_t len) 00559 { 00560 return (u16_t)~(unsigned int)LWIP_CHKSUM(dataptr, len); 00561 } 00562 00563 /** 00564 * Calculate a checksum over a chain of pbufs (without pseudo-header, much like 00565 * inet_chksum only pbufs are used). 00566 * 00567 * @param p pbuf chain over that the checksum should be calculated 00568 * @return checksum (as u16_t) to be saved directly in the protocol header 00569 */ 00570 u16_t 00571 inet_chksum_pbuf(struct pbuf *p) 00572 { 00573 u32_t acc; 00574 struct pbuf *q; 00575 u8_t swapped; 00576 00577 acc = 0; 00578 swapped = 0; 00579 for (q = p; q != NULL; q = q->next) { 00580 acc += LWIP_CHKSUM(q->payload, q->len); 00581 acc = FOLD_U32T(acc); 00582 if (q->len % 2 != 0) { 00583 swapped = 1 - swapped; 00584 acc = SWAP_BYTES_IN_WORD(acc); 00585 } 00586 } 00587 00588 if (swapped) { 00589 acc = SWAP_BYTES_IN_WORD(acc); 00590 } 00591 return (u16_t)~(acc & 0xffffUL); 00592 } 00593 00594 /* These are some implementations for LWIP_CHKSUM_COPY, which copies data 00595 * like MEMCPY but generates a checksum at the same time. Since this is a 00596 * performance-sensitive function, you might want to create your own version 00597 * in assembly targeted at your hardware by defining it in lwipopts.h: 00598 * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) 00599 */ 00600 00601 #if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ 00602 /** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. 00603 * For architectures with big caches, data might still be in cache when 00604 * generating the checksum after copying. 00605 */ 00606 u16_t 00607 lwip_chksum_copy(void *dst, const void *src, u16_t len) 00608 { 00609 MEMCPY(dst, src, len); 00610 return LWIP_CHKSUM(dst, len); 00611 } 00612 #endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */
Generated on Tue Jul 12 2022 11:02:41 by
