My fork of the HTTPServer (working)
Core/lwIP/core/ipv4/inet_chksum.c@0:7a64fbb4069d, 2012-08-06 (annotated)
- Committer:
- screamer
- Date:
- Mon Aug 06 09:23:14 2012 +0000
- Revision:
- 0:7a64fbb4069d
[mbed] converted /DGWWebServer/HTTPServer
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
screamer | 0:7a64fbb4069d | 1 | /** |
screamer | 0:7a64fbb4069d | 2 | * @file |
screamer | 0:7a64fbb4069d | 3 | * Incluse internet checksum functions. |
screamer | 0:7a64fbb4069d | 4 | * |
screamer | 0:7a64fbb4069d | 5 | */ |
screamer | 0:7a64fbb4069d | 6 | |
screamer | 0:7a64fbb4069d | 7 | /* |
screamer | 0:7a64fbb4069d | 8 | * Copyright (c) 2001-2004 Swedish Institute of Computer Science. |
screamer | 0:7a64fbb4069d | 9 | * All rights reserved. |
screamer | 0:7a64fbb4069d | 10 | * |
screamer | 0:7a64fbb4069d | 11 | * Redistribution and use in source and binary forms, with or without modification, |
screamer | 0:7a64fbb4069d | 12 | * are permitted provided that the following conditions are met: |
screamer | 0:7a64fbb4069d | 13 | * |
screamer | 0:7a64fbb4069d | 14 | * 1. Redistributions of source code must retain the above copyright notice, |
screamer | 0:7a64fbb4069d | 15 | * this list of conditions and the following disclaimer. |
screamer | 0:7a64fbb4069d | 16 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
screamer | 0:7a64fbb4069d | 17 | * this list of conditions and the following disclaimer in the documentation |
screamer | 0:7a64fbb4069d | 18 | * and/or other materials provided with the distribution. |
screamer | 0:7a64fbb4069d | 19 | * 3. The name of the author may not be used to endorse or promote products |
screamer | 0:7a64fbb4069d | 20 | * derived from this software without specific prior written permission. |
screamer | 0:7a64fbb4069d | 21 | * |
screamer | 0:7a64fbb4069d | 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
screamer | 0:7a64fbb4069d | 23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
screamer | 0:7a64fbb4069d | 24 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
screamer | 0:7a64fbb4069d | 25 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
screamer | 0:7a64fbb4069d | 26 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
screamer | 0:7a64fbb4069d | 27 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
screamer | 0:7a64fbb4069d | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
screamer | 0:7a64fbb4069d | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
screamer | 0:7a64fbb4069d | 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
screamer | 0:7a64fbb4069d | 31 | * OF SUCH DAMAGE. |
screamer | 0:7a64fbb4069d | 32 | * |
screamer | 0:7a64fbb4069d | 33 | * This file is part of the lwIP TCP/IP stack. |
screamer | 0:7a64fbb4069d | 34 | * |
screamer | 0:7a64fbb4069d | 35 | * Author: Adam Dunkels <adam@sics.se> |
screamer | 0:7a64fbb4069d | 36 | * |
screamer | 0:7a64fbb4069d | 37 | */ |
screamer | 0:7a64fbb4069d | 38 | |
screamer | 0:7a64fbb4069d | 39 | #include "lwip/opt.h" |
screamer | 0:7a64fbb4069d | 40 | |
screamer | 0:7a64fbb4069d | 41 | #include "lwip/inet_chksum.h" |
screamer | 0:7a64fbb4069d | 42 | #include "lwip/inet.h" |
screamer | 0:7a64fbb4069d | 43 | |
screamer | 0:7a64fbb4069d | 44 | /* These are some reference implementations of the checksum algorithm, with the |
screamer | 0:7a64fbb4069d | 45 | * aim of being simple, correct and fully portable. Checksumming is the |
screamer | 0:7a64fbb4069d | 46 | * first thing you would want to optimize for your platform. If you create |
screamer | 0:7a64fbb4069d | 47 | * your own version, link it in and in your cc.h put: |
screamer | 0:7a64fbb4069d | 48 | * |
screamer | 0:7a64fbb4069d | 49 | * #define LWIP_CHKSUM <your_checksum_routine> |
screamer | 0:7a64fbb4069d | 50 | * |
screamer | 0:7a64fbb4069d | 51 | * Or you can select from the implementations below by defining |
screamer | 0:7a64fbb4069d | 52 | * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. |
screamer | 0:7a64fbb4069d | 53 | */ |
screamer | 0:7a64fbb4069d | 54 | |
screamer | 0:7a64fbb4069d | 55 | #ifndef LWIP_CHKSUM |
screamer | 0:7a64fbb4069d | 56 | # define LWIP_CHKSUM lwip_standard_chksum |
screamer | 0:7a64fbb4069d | 57 | # ifndef LWIP_CHKSUM_ALGORITHM |
screamer | 0:7a64fbb4069d | 58 | # define LWIP_CHKSUM_ALGORITHM 1 |
screamer | 0:7a64fbb4069d | 59 | # endif |
screamer | 0:7a64fbb4069d | 60 | #endif |
screamer | 0:7a64fbb4069d | 61 | /* If none set: */ |
screamer | 0:7a64fbb4069d | 62 | #ifndef LWIP_CHKSUM_ALGORITHM |
screamer | 0:7a64fbb4069d | 63 | # define LWIP_CHKSUM_ALGORITHM 0 |
screamer | 0:7a64fbb4069d | 64 | #endif |
screamer | 0:7a64fbb4069d | 65 | |
screamer | 0:7a64fbb4069d | 66 | /** Like the name says... */ |
screamer | 0:7a64fbb4069d | 67 | #define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8) |
screamer | 0:7a64fbb4069d | 68 | /** Split an u32_t in two u16_ts and add them up */ |
screamer | 0:7a64fbb4069d | 69 | #define FOLD_U32T(u) ((u >> 16) + (u & 0x0000ffffUL)) |
screamer | 0:7a64fbb4069d | 70 | |
screamer | 0:7a64fbb4069d | 71 | #if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ |
screamer | 0:7a64fbb4069d | 72 | /** |
screamer | 0:7a64fbb4069d | 73 | * lwip checksum |
screamer | 0:7a64fbb4069d | 74 | * |
screamer | 0:7a64fbb4069d | 75 | * @param dataptr points to start of data to be summed at any boundary |
screamer | 0:7a64fbb4069d | 76 | * @param len length of data to be summed |
screamer | 0:7a64fbb4069d | 77 | * @return host order (!) lwip checksum (non-inverted Internet sum) |
screamer | 0:7a64fbb4069d | 78 | * |
screamer | 0:7a64fbb4069d | 79 | * @note accumulator size limits summable length to 64k |
screamer | 0:7a64fbb4069d | 80 | * @note host endianess is irrelevant (p3 RFC1071) |
screamer | 0:7a64fbb4069d | 81 | */ |
screamer | 0:7a64fbb4069d | 82 | static u16_t |
screamer | 0:7a64fbb4069d | 83 | lwip_standard_chksum(void *dataptr, u16_t len) |
screamer | 0:7a64fbb4069d | 84 | { |
screamer | 0:7a64fbb4069d | 85 | u32_t acc; |
screamer | 0:7a64fbb4069d | 86 | u16_t src; |
screamer | 0:7a64fbb4069d | 87 | u8_t *octetptr; |
screamer | 0:7a64fbb4069d | 88 | |
screamer | 0:7a64fbb4069d | 89 | acc = 0; |
screamer | 0:7a64fbb4069d | 90 | /* dataptr may be at odd or even addresses */ |
screamer | 0:7a64fbb4069d | 91 | octetptr = (u8_t*)dataptr; |
screamer | 0:7a64fbb4069d | 92 | while (len > 1) { |
screamer | 0:7a64fbb4069d | 93 | /* declare first octet as most significant |
screamer | 0:7a64fbb4069d | 94 | thus assume network order, ignoring host order */ |
screamer | 0:7a64fbb4069d | 95 | src = (*octetptr) << 8; |
screamer | 0:7a64fbb4069d | 96 | octetptr++; |
screamer | 0:7a64fbb4069d | 97 | /* declare second octet as least significant */ |
screamer | 0:7a64fbb4069d | 98 | src |= (*octetptr); |
screamer | 0:7a64fbb4069d | 99 | octetptr++; |
screamer | 0:7a64fbb4069d | 100 | acc += src; |
screamer | 0:7a64fbb4069d | 101 | len -= 2; |
screamer | 0:7a64fbb4069d | 102 | } |
screamer | 0:7a64fbb4069d | 103 | if (len > 0) { |
screamer | 0:7a64fbb4069d | 104 | /* accumulate remaining octet */ |
screamer | 0:7a64fbb4069d | 105 | src = (*octetptr) << 8; |
screamer | 0:7a64fbb4069d | 106 | acc += src; |
screamer | 0:7a64fbb4069d | 107 | } |
screamer | 0:7a64fbb4069d | 108 | /* add deferred carry bits */ |
screamer | 0:7a64fbb4069d | 109 | acc = (acc >> 16) + (acc & 0x0000ffffUL); |
screamer | 0:7a64fbb4069d | 110 | if ((acc & 0xffff0000UL) != 0) { |
screamer | 0:7a64fbb4069d | 111 | acc = (acc >> 16) + (acc & 0x0000ffffUL); |
screamer | 0:7a64fbb4069d | 112 | } |
screamer | 0:7a64fbb4069d | 113 | /* This maybe a little confusing: reorder sum using htons() |
screamer | 0:7a64fbb4069d | 114 | instead of ntohs() since it has a little less call overhead. |
screamer | 0:7a64fbb4069d | 115 | The caller must invert bits for Internet sum ! */ |
screamer | 0:7a64fbb4069d | 116 | return htons((u16_t)acc); |
screamer | 0:7a64fbb4069d | 117 | } |
screamer | 0:7a64fbb4069d | 118 | #endif |
screamer | 0:7a64fbb4069d | 119 | |
screamer | 0:7a64fbb4069d | 120 | #if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ |
screamer | 0:7a64fbb4069d | 121 | /* |
screamer | 0:7a64fbb4069d | 122 | * Curt McDowell |
screamer | 0:7a64fbb4069d | 123 | * Broadcom Corp. |
screamer | 0:7a64fbb4069d | 124 | * csm@broadcom.com |
screamer | 0:7a64fbb4069d | 125 | * |
screamer | 0:7a64fbb4069d | 126 | * IP checksum two bytes at a time with support for |
screamer | 0:7a64fbb4069d | 127 | * unaligned buffer. |
screamer | 0:7a64fbb4069d | 128 | * Works for len up to and including 0x20000. |
screamer | 0:7a64fbb4069d | 129 | * by Curt McDowell, Broadcom Corp. 12/08/2005 |
screamer | 0:7a64fbb4069d | 130 | * |
screamer | 0:7a64fbb4069d | 131 | * @param dataptr points to start of data to be summed at any boundary |
screamer | 0:7a64fbb4069d | 132 | * @param len length of data to be summed |
screamer | 0:7a64fbb4069d | 133 | * @return host order (!) lwip checksum (non-inverted Internet sum) |
screamer | 0:7a64fbb4069d | 134 | */ |
screamer | 0:7a64fbb4069d | 135 | |
screamer | 0:7a64fbb4069d | 136 | static u16_t |
screamer | 0:7a64fbb4069d | 137 | lwip_standard_chksum(void *dataptr, int len) |
screamer | 0:7a64fbb4069d | 138 | { |
screamer | 0:7a64fbb4069d | 139 | u8_t *pb = dataptr; |
screamer | 0:7a64fbb4069d | 140 | u16_t *ps, t = 0; |
screamer | 0:7a64fbb4069d | 141 | u32_t sum = 0; |
screamer | 0:7a64fbb4069d | 142 | int odd = ((u32_t)pb & 1); |
screamer | 0:7a64fbb4069d | 143 | |
screamer | 0:7a64fbb4069d | 144 | /* Get aligned to u16_t */ |
screamer | 0:7a64fbb4069d | 145 | if (odd && len > 0) { |
screamer | 0:7a64fbb4069d | 146 | ((u8_t *)&t)[1] = *pb++; |
screamer | 0:7a64fbb4069d | 147 | len--; |
screamer | 0:7a64fbb4069d | 148 | } |
screamer | 0:7a64fbb4069d | 149 | |
screamer | 0:7a64fbb4069d | 150 | /* Add the bulk of the data */ |
screamer | 0:7a64fbb4069d | 151 | ps = (u16_t *)pb; |
screamer | 0:7a64fbb4069d | 152 | while (len > 1) { |
screamer | 0:7a64fbb4069d | 153 | sum += *ps++; |
screamer | 0:7a64fbb4069d | 154 | len -= 2; |
screamer | 0:7a64fbb4069d | 155 | } |
screamer | 0:7a64fbb4069d | 156 | |
screamer | 0:7a64fbb4069d | 157 | /* Consume left-over byte, if any */ |
screamer | 0:7a64fbb4069d | 158 | if (len > 0) { |
screamer | 0:7a64fbb4069d | 159 | ((u8_t *)&t)[0] = *(u8_t *)ps;; |
screamer | 0:7a64fbb4069d | 160 | } |
screamer | 0:7a64fbb4069d | 161 | |
screamer | 0:7a64fbb4069d | 162 | /* Add end bytes */ |
screamer | 0:7a64fbb4069d | 163 | sum += t; |
screamer | 0:7a64fbb4069d | 164 | |
screamer | 0:7a64fbb4069d | 165 | /* Fold 32-bit sum to 16 bits |
screamer | 0:7a64fbb4069d | 166 | calling this twice is propably faster than if statements... */ |
screamer | 0:7a64fbb4069d | 167 | sum = FOLD_U32T(sum); |
screamer | 0:7a64fbb4069d | 168 | sum = FOLD_U32T(sum); |
screamer | 0:7a64fbb4069d | 169 | |
screamer | 0:7a64fbb4069d | 170 | /* Swap if alignment was odd */ |
screamer | 0:7a64fbb4069d | 171 | if (odd) { |
screamer | 0:7a64fbb4069d | 172 | sum = SWAP_BYTES_IN_WORD(sum); |
screamer | 0:7a64fbb4069d | 173 | } |
screamer | 0:7a64fbb4069d | 174 | |
screamer | 0:7a64fbb4069d | 175 | return sum; |
screamer | 0:7a64fbb4069d | 176 | } |
screamer | 0:7a64fbb4069d | 177 | #endif |
screamer | 0:7a64fbb4069d | 178 | |
screamer | 0:7a64fbb4069d | 179 | #if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ |
screamer | 0:7a64fbb4069d | 180 | /** |
screamer | 0:7a64fbb4069d | 181 | * An optimized checksum routine. Basically, it uses loop-unrolling on |
screamer | 0:7a64fbb4069d | 182 | * the checksum loop, treating the head and tail bytes specially, whereas |
screamer | 0:7a64fbb4069d | 183 | * the inner loop acts on 8 bytes at a time. |
screamer | 0:7a64fbb4069d | 184 | * |
screamer | 0:7a64fbb4069d | 185 | * @arg start of buffer to be checksummed. May be an odd byte address. |
screamer | 0:7a64fbb4069d | 186 | * @len number of bytes in the buffer to be checksummed. |
screamer | 0:7a64fbb4069d | 187 | * @return host order (!) lwip checksum (non-inverted Internet sum) |
screamer | 0:7a64fbb4069d | 188 | * |
screamer | 0:7a64fbb4069d | 189 | * by Curt McDowell, Broadcom Corp. December 8th, 2005 |
screamer | 0:7a64fbb4069d | 190 | */ |
screamer | 0:7a64fbb4069d | 191 | |
screamer | 0:7a64fbb4069d | 192 | static u16_t |
screamer | 0:7a64fbb4069d | 193 | lwip_standard_chksum(void *dataptr, int len) |
screamer | 0:7a64fbb4069d | 194 | { |
screamer | 0:7a64fbb4069d | 195 | u8_t *pb = dataptr; |
screamer | 0:7a64fbb4069d | 196 | u16_t *ps, t = 0; |
screamer | 0:7a64fbb4069d | 197 | u32_t *pl; |
screamer | 0:7a64fbb4069d | 198 | u32_t sum = 0, tmp; |
screamer | 0:7a64fbb4069d | 199 | /* starts at odd byte address? */ |
screamer | 0:7a64fbb4069d | 200 | int odd = ((u32_t)pb & 1); |
screamer | 0:7a64fbb4069d | 201 | |
screamer | 0:7a64fbb4069d | 202 | if (odd && len > 0) { |
screamer | 0:7a64fbb4069d | 203 | ((u8_t *)&t)[1] = *pb++; |
screamer | 0:7a64fbb4069d | 204 | len--; |
screamer | 0:7a64fbb4069d | 205 | } |
screamer | 0:7a64fbb4069d | 206 | |
screamer | 0:7a64fbb4069d | 207 | ps = (u16_t *)pb; |
screamer | 0:7a64fbb4069d | 208 | |
screamer | 0:7a64fbb4069d | 209 | if (((u32_t)ps & 3) && len > 1) { |
screamer | 0:7a64fbb4069d | 210 | sum += *ps++; |
screamer | 0:7a64fbb4069d | 211 | len -= 2; |
screamer | 0:7a64fbb4069d | 212 | } |
screamer | 0:7a64fbb4069d | 213 | |
screamer | 0:7a64fbb4069d | 214 | pl = (u32_t *)ps; |
screamer | 0:7a64fbb4069d | 215 | |
screamer | 0:7a64fbb4069d | 216 | while (len > 7) { |
screamer | 0:7a64fbb4069d | 217 | tmp = sum + *pl++; /* ping */ |
screamer | 0:7a64fbb4069d | 218 | if (tmp < sum) { |
screamer | 0:7a64fbb4069d | 219 | tmp++; /* add back carry */ |
screamer | 0:7a64fbb4069d | 220 | } |
screamer | 0:7a64fbb4069d | 221 | |
screamer | 0:7a64fbb4069d | 222 | sum = tmp + *pl++; /* pong */ |
screamer | 0:7a64fbb4069d | 223 | if (sum < tmp) { |
screamer | 0:7a64fbb4069d | 224 | sum++; /* add back carry */ |
screamer | 0:7a64fbb4069d | 225 | } |
screamer | 0:7a64fbb4069d | 226 | |
screamer | 0:7a64fbb4069d | 227 | len -= 8; |
screamer | 0:7a64fbb4069d | 228 | } |
screamer | 0:7a64fbb4069d | 229 | |
screamer | 0:7a64fbb4069d | 230 | /* make room in upper bits */ |
screamer | 0:7a64fbb4069d | 231 | sum = FOLD_U32T(sum); |
screamer | 0:7a64fbb4069d | 232 | |
screamer | 0:7a64fbb4069d | 233 | ps = (u16_t *)pl; |
screamer | 0:7a64fbb4069d | 234 | |
screamer | 0:7a64fbb4069d | 235 | /* 16-bit aligned word remaining? */ |
screamer | 0:7a64fbb4069d | 236 | while (len > 1) { |
screamer | 0:7a64fbb4069d | 237 | sum += *ps++; |
screamer | 0:7a64fbb4069d | 238 | len -= 2; |
screamer | 0:7a64fbb4069d | 239 | } |
screamer | 0:7a64fbb4069d | 240 | |
screamer | 0:7a64fbb4069d | 241 | /* dangling tail byte remaining? */ |
screamer | 0:7a64fbb4069d | 242 | if (len > 0) { /* include odd byte */ |
screamer | 0:7a64fbb4069d | 243 | ((u8_t *)&t)[0] = *(u8_t *)ps; |
screamer | 0:7a64fbb4069d | 244 | } |
screamer | 0:7a64fbb4069d | 245 | |
screamer | 0:7a64fbb4069d | 246 | sum += t; /* add end bytes */ |
screamer | 0:7a64fbb4069d | 247 | |
screamer | 0:7a64fbb4069d | 248 | /* Fold 32-bit sum to 16 bits |
screamer | 0:7a64fbb4069d | 249 | calling this twice is propably faster than if statements... */ |
screamer | 0:7a64fbb4069d | 250 | sum = FOLD_U32T(sum); |
screamer | 0:7a64fbb4069d | 251 | sum = FOLD_U32T(sum); |
screamer | 0:7a64fbb4069d | 252 | |
screamer | 0:7a64fbb4069d | 253 | if (odd) { |
screamer | 0:7a64fbb4069d | 254 | sum = SWAP_BYTES_IN_WORD(sum); |
screamer | 0:7a64fbb4069d | 255 | } |
screamer | 0:7a64fbb4069d | 256 | |
screamer | 0:7a64fbb4069d | 257 | return sum; |
screamer | 0:7a64fbb4069d | 258 | } |
screamer | 0:7a64fbb4069d | 259 | #endif |
screamer | 0:7a64fbb4069d | 260 | |
screamer | 0:7a64fbb4069d | 261 | /* inet_chksum_pseudo: |
screamer | 0:7a64fbb4069d | 262 | * |
screamer | 0:7a64fbb4069d | 263 | * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. |
screamer | 0:7a64fbb4069d | 264 | * IP addresses are expected to be in network byte order. |
screamer | 0:7a64fbb4069d | 265 | * |
screamer | 0:7a64fbb4069d | 266 | * @param p chain of pbufs over that a checksum should be calculated (ip data part) |
screamer | 0:7a64fbb4069d | 267 | * @param src source ip address (used for checksum of pseudo header) |
screamer | 0:7a64fbb4069d | 268 | * @param dst destination ip address (used for checksum of pseudo header) |
screamer | 0:7a64fbb4069d | 269 | * @param proto ip protocol (used for checksum of pseudo header) |
screamer | 0:7a64fbb4069d | 270 | * @param proto_len length of the ip data part (used for checksum of pseudo header) |
screamer | 0:7a64fbb4069d | 271 | * @return checksum (as u16_t) to be saved directly in the protocol header |
screamer | 0:7a64fbb4069d | 272 | */ |
screamer | 0:7a64fbb4069d | 273 | u16_t |
screamer | 0:7a64fbb4069d | 274 | inet_chksum_pseudo(struct pbuf *p, |
screamer | 0:7a64fbb4069d | 275 | struct ip_addr *src, struct ip_addr *dest, |
screamer | 0:7a64fbb4069d | 276 | u8_t proto, u16_t proto_len) |
screamer | 0:7a64fbb4069d | 277 | { |
screamer | 0:7a64fbb4069d | 278 | u32_t acc; |
screamer | 0:7a64fbb4069d | 279 | struct pbuf *q; |
screamer | 0:7a64fbb4069d | 280 | u8_t swapped; |
screamer | 0:7a64fbb4069d | 281 | |
screamer | 0:7a64fbb4069d | 282 | acc = 0; |
screamer | 0:7a64fbb4069d | 283 | swapped = 0; |
screamer | 0:7a64fbb4069d | 284 | /* iterate through all pbuf in chain */ |
screamer | 0:7a64fbb4069d | 285 | for(q = p; q != NULL; q = q->next) { |
screamer | 0:7a64fbb4069d | 286 | LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", |
screamer | 0:7a64fbb4069d | 287 | (void *)q, (void *)q->next)); |
screamer | 0:7a64fbb4069d | 288 | acc += LWIP_CHKSUM(q->payload, q->len); |
screamer | 0:7a64fbb4069d | 289 | /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ |
screamer | 0:7a64fbb4069d | 290 | /* just executing this next line is probably faster that the if statement needed |
screamer | 0:7a64fbb4069d | 291 | to check whether we really need to execute it, and does no harm */ |
screamer | 0:7a64fbb4069d | 292 | acc = FOLD_U32T(acc); |
screamer | 0:7a64fbb4069d | 293 | if (q->len % 2 != 0) { |
screamer | 0:7a64fbb4069d | 294 | swapped = 1 - swapped; |
screamer | 0:7a64fbb4069d | 295 | acc = SWAP_BYTES_IN_WORD(acc); |
screamer | 0:7a64fbb4069d | 296 | } |
screamer | 0:7a64fbb4069d | 297 | /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ |
screamer | 0:7a64fbb4069d | 298 | } |
screamer | 0:7a64fbb4069d | 299 | |
screamer | 0:7a64fbb4069d | 300 | if (swapped) { |
screamer | 0:7a64fbb4069d | 301 | acc = SWAP_BYTES_IN_WORD(acc); |
screamer | 0:7a64fbb4069d | 302 | } |
screamer | 0:7a64fbb4069d | 303 | acc += (src->addr & 0xffffUL); |
screamer | 0:7a64fbb4069d | 304 | acc += ((src->addr >> 16) & 0xffffUL); |
screamer | 0:7a64fbb4069d | 305 | acc += (dest->addr & 0xffffUL); |
screamer | 0:7a64fbb4069d | 306 | acc += ((dest->addr >> 16) & 0xffffUL); |
screamer | 0:7a64fbb4069d | 307 | acc += (u32_t)htons((u16_t)proto); |
screamer | 0:7a64fbb4069d | 308 | acc += (u32_t)htons(proto_len); |
screamer | 0:7a64fbb4069d | 309 | |
screamer | 0:7a64fbb4069d | 310 | /* Fold 32-bit sum to 16 bits |
screamer | 0:7a64fbb4069d | 311 | calling this twice is propably faster than if statements... */ |
screamer | 0:7a64fbb4069d | 312 | acc = FOLD_U32T(acc); |
screamer | 0:7a64fbb4069d | 313 | acc = FOLD_U32T(acc); |
screamer | 0:7a64fbb4069d | 314 | LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); |
screamer | 0:7a64fbb4069d | 315 | return (u16_t)~(acc & 0xffffUL); |
screamer | 0:7a64fbb4069d | 316 | } |
screamer | 0:7a64fbb4069d | 317 | |
screamer | 0:7a64fbb4069d | 318 | /* inet_chksum_pseudo: |
screamer | 0:7a64fbb4069d | 319 | * |
screamer | 0:7a64fbb4069d | 320 | * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. |
screamer | 0:7a64fbb4069d | 321 | * IP addresses are expected to be in network byte order. |
screamer | 0:7a64fbb4069d | 322 | * |
screamer | 0:7a64fbb4069d | 323 | * @param p chain of pbufs over that a checksum should be calculated (ip data part) |
screamer | 0:7a64fbb4069d | 324 | * @param src source ip address (used for checksum of pseudo header) |
screamer | 0:7a64fbb4069d | 325 | * @param dst destination ip address (used for checksum of pseudo header) |
screamer | 0:7a64fbb4069d | 326 | * @param proto ip protocol (used for checksum of pseudo header) |
screamer | 0:7a64fbb4069d | 327 | * @param proto_len length of the ip data part (used for checksum of pseudo header) |
screamer | 0:7a64fbb4069d | 328 | * @return checksum (as u16_t) to be saved directly in the protocol header |
screamer | 0:7a64fbb4069d | 329 | */ |
screamer | 0:7a64fbb4069d | 330 | /* Currently only used by UDPLITE, although this could change in the future. */ |
screamer | 0:7a64fbb4069d | 331 | #if LWIP_UDPLITE |
screamer | 0:7a64fbb4069d | 332 | u16_t |
screamer | 0:7a64fbb4069d | 333 | inet_chksum_pseudo_partial(struct pbuf *p, |
screamer | 0:7a64fbb4069d | 334 | struct ip_addr *src, struct ip_addr *dest, |
screamer | 0:7a64fbb4069d | 335 | u8_t proto, u16_t proto_len, u16_t chksum_len) |
screamer | 0:7a64fbb4069d | 336 | { |
screamer | 0:7a64fbb4069d | 337 | u32_t acc; |
screamer | 0:7a64fbb4069d | 338 | struct pbuf *q; |
screamer | 0:7a64fbb4069d | 339 | u8_t swapped; |
screamer | 0:7a64fbb4069d | 340 | u16_t chklen; |
screamer | 0:7a64fbb4069d | 341 | |
screamer | 0:7a64fbb4069d | 342 | acc = 0; |
screamer | 0:7a64fbb4069d | 343 | swapped = 0; |
screamer | 0:7a64fbb4069d | 344 | /* iterate through all pbuf in chain */ |
screamer | 0:7a64fbb4069d | 345 | for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) { |
screamer | 0:7a64fbb4069d | 346 | LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", |
screamer | 0:7a64fbb4069d | 347 | (void *)q, (void *)q->next)); |
screamer | 0:7a64fbb4069d | 348 | chklen = q->len; |
screamer | 0:7a64fbb4069d | 349 | if (chklen > chksum_len) { |
screamer | 0:7a64fbb4069d | 350 | chklen = chksum_len; |
screamer | 0:7a64fbb4069d | 351 | } |
screamer | 0:7a64fbb4069d | 352 | acc += LWIP_CHKSUM(q->payload, chklen); |
screamer | 0:7a64fbb4069d | 353 | chksum_len -= chklen; |
screamer | 0:7a64fbb4069d | 354 | LWIP_ASSERT("delete me", chksum_len < 0x7fff); |
screamer | 0:7a64fbb4069d | 355 | /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ |
screamer | 0:7a64fbb4069d | 356 | /* fold the upper bit down */ |
screamer | 0:7a64fbb4069d | 357 | acc = FOLD_U32T(acc); |
screamer | 0:7a64fbb4069d | 358 | if (q->len % 2 != 0) { |
screamer | 0:7a64fbb4069d | 359 | swapped = 1 - swapped; |
screamer | 0:7a64fbb4069d | 360 | acc = SWAP_BYTES_IN_WORD(acc); |
screamer | 0:7a64fbb4069d | 361 | } |
screamer | 0:7a64fbb4069d | 362 | /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ |
screamer | 0:7a64fbb4069d | 363 | } |
screamer | 0:7a64fbb4069d | 364 | |
screamer | 0:7a64fbb4069d | 365 | if (swapped) { |
screamer | 0:7a64fbb4069d | 366 | acc = SWAP_BYTES_IN_WORD(acc); |
screamer | 0:7a64fbb4069d | 367 | } |
screamer | 0:7a64fbb4069d | 368 | acc += (src->addr & 0xffffUL); |
screamer | 0:7a64fbb4069d | 369 | acc += ((src->addr >> 16) & 0xffffUL); |
screamer | 0:7a64fbb4069d | 370 | acc += (dest->addr & 0xffffUL); |
screamer | 0:7a64fbb4069d | 371 | acc += ((dest->addr >> 16) & 0xffffUL); |
screamer | 0:7a64fbb4069d | 372 | acc += (u32_t)htons((u16_t)proto); |
screamer | 0:7a64fbb4069d | 373 | acc += (u32_t)htons(proto_len); |
screamer | 0:7a64fbb4069d | 374 | |
screamer | 0:7a64fbb4069d | 375 | /* Fold 32-bit sum to 16 bits |
screamer | 0:7a64fbb4069d | 376 | calling this twice is propably faster than if statements... */ |
screamer | 0:7a64fbb4069d | 377 | acc = FOLD_U32T(acc); |
screamer | 0:7a64fbb4069d | 378 | acc = FOLD_U32T(acc); |
screamer | 0:7a64fbb4069d | 379 | LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); |
screamer | 0:7a64fbb4069d | 380 | return (u16_t)~(acc & 0xffffUL); |
screamer | 0:7a64fbb4069d | 381 | } |
screamer | 0:7a64fbb4069d | 382 | #endif /* LWIP_UDPLITE */ |
screamer | 0:7a64fbb4069d | 383 | |
screamer | 0:7a64fbb4069d | 384 | /* inet_chksum: |
screamer | 0:7a64fbb4069d | 385 | * |
screamer | 0:7a64fbb4069d | 386 | * Calculates the Internet checksum over a portion of memory. Used primarily for IP |
screamer | 0:7a64fbb4069d | 387 | * and ICMP. |
screamer | 0:7a64fbb4069d | 388 | * |
screamer | 0:7a64fbb4069d | 389 | * @param dataptr start of the buffer to calculate the checksum (no alignment needed) |
screamer | 0:7a64fbb4069d | 390 | * @param len length of the buffer to calculate the checksum |
screamer | 0:7a64fbb4069d | 391 | * @return checksum (as u16_t) to be saved directly in the protocol header |
screamer | 0:7a64fbb4069d | 392 | */ |
screamer | 0:7a64fbb4069d | 393 | |
screamer | 0:7a64fbb4069d | 394 | u16_t |
screamer | 0:7a64fbb4069d | 395 | inet_chksum(void *dataptr, u16_t len) |
screamer | 0:7a64fbb4069d | 396 | { |
screamer | 0:7a64fbb4069d | 397 | return ~LWIP_CHKSUM(dataptr, len); |
screamer | 0:7a64fbb4069d | 398 | } |
screamer | 0:7a64fbb4069d | 399 | |
screamer | 0:7a64fbb4069d | 400 | /** |
screamer | 0:7a64fbb4069d | 401 | * Calculate a checksum over a chain of pbufs (without pseudo-header, much like |
screamer | 0:7a64fbb4069d | 402 | * inet_chksum only pbufs are used). |
screamer | 0:7a64fbb4069d | 403 | * |
screamer | 0:7a64fbb4069d | 404 | * @param p pbuf chain over that the checksum should be calculated |
screamer | 0:7a64fbb4069d | 405 | * @return checksum (as u16_t) to be saved directly in the protocol header |
screamer | 0:7a64fbb4069d | 406 | */ |
screamer | 0:7a64fbb4069d | 407 | u16_t |
screamer | 0:7a64fbb4069d | 408 | inet_chksum_pbuf(struct pbuf *p) |
screamer | 0:7a64fbb4069d | 409 | { |
screamer | 0:7a64fbb4069d | 410 | u32_t acc; |
screamer | 0:7a64fbb4069d | 411 | struct pbuf *q; |
screamer | 0:7a64fbb4069d | 412 | u8_t swapped; |
screamer | 0:7a64fbb4069d | 413 | |
screamer | 0:7a64fbb4069d | 414 | acc = 0; |
screamer | 0:7a64fbb4069d | 415 | swapped = 0; |
screamer | 0:7a64fbb4069d | 416 | for(q = p; q != NULL; q = q->next) { |
screamer | 0:7a64fbb4069d | 417 | acc += LWIP_CHKSUM(q->payload, q->len); |
screamer | 0:7a64fbb4069d | 418 | acc = FOLD_U32T(acc); |
screamer | 0:7a64fbb4069d | 419 | if (q->len % 2 != 0) { |
screamer | 0:7a64fbb4069d | 420 | swapped = 1 - swapped; |
screamer | 0:7a64fbb4069d | 421 | acc = SWAP_BYTES_IN_WORD(acc); |
screamer | 0:7a64fbb4069d | 422 | } |
screamer | 0:7a64fbb4069d | 423 | } |
screamer | 0:7a64fbb4069d | 424 | |
screamer | 0:7a64fbb4069d | 425 | if (swapped) { |
screamer | 0:7a64fbb4069d | 426 | acc = SWAP_BYTES_IN_WORD(acc); |
screamer | 0:7a64fbb4069d | 427 | } |
screamer | 0:7a64fbb4069d | 428 | return (u16_t)~(acc & 0xffffUL); |
screamer | 0:7a64fbb4069d | 429 | } |