ProjetoBB

Dependencies:   F7_Ethernet WebSocketClient mbed mcp3008

Fork of Nucleo_F746ZG_Ethernet by Dieter Graef

Committer:
DieterGraef
Date:
Sat Jun 18 10:49:12 2016 +0000
Revision:
0:f9b6112278fe
Ethernet for the NUCLEO STM32F746 Board Testprogram uses DHCP and NTP to set the clock

Who changed what in which revision?

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