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