60 |
*/ |
*/ |
61 |
#ifndef LWIP_CHKSUM |
#ifndef LWIP_CHKSUM |
62 |
#define LWIP_CHKSUM lwip_standard_chksum |
#define LWIP_CHKSUM lwip_standard_chksum |
63 |
|
|
64 |
|
/** |
65 |
|
* lwip checksum |
66 |
|
* |
67 |
|
* @param dataptr points to start of data to be summed at any boundary |
68 |
|
* @param len length of data to be summed |
69 |
|
* @return network order (!) lwip checksum (non-inverted Internet sum) |
70 |
|
* |
71 |
|
* @note accumulator size limits summable lenght to 64k |
72 |
|
* @note host endianess is irrelevant (p3 RFC1071) |
73 |
|
*/ |
74 |
static u16_t |
static u16_t |
75 |
lwip_standard_chksum(void *dataptr, int len) |
lwip_standard_chksum(void *dataptr, u16_t len) |
76 |
{ |
{ |
77 |
u32_t acc; |
u32_t acc; |
78 |
LWIP_DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %"S16_F")\n", (void *)dataptr, len)); |
u16_t src; |
79 |
|
u8_t *octetptr; |
80 |
|
|
81 |
/* iterate by two bytes at once */ |
acc = 0; |
82 |
for(acc = 0; len > 1; len -= 2) { |
/* dataptr may be at odd or even addresses */ |
83 |
/* WAS: acc = acc + *((u16_t *)dataptr)++; BUT THIS IS BROKEN FOR |
octetptr = (u8_t*)dataptr; |
84 |
* ARCHITECTURES WHICH DO NOT ALLOW UNALIGNED 16-BIT ACCESSES */ |
while (len > 1) |
85 |
#if MEM_ALIGNMENT >= 2 |
{ |
86 |
acc += htons( ((u16_t)(((u8_t *)dataptr)[0])<<8) | ((u8_t *)dataptr)[1] ); |
/* first octet is most significant */ |
87 |
(void *)((u16_t *)dataptr + 1); |
src = (*octetptr) << 8; |
88 |
#else |
octetptr++; |
89 |
acc += *(u16_t *)dataptr; |
/* second octet is least significant */ |
90 |
dataptr = (void *)((u16_t *)dataptr + 1); |
src |= (*octetptr); |
91 |
#endif |
octetptr++; |
92 |
|
acc += src; |
93 |
|
len -= 2; |
94 |
} |
} |
95 |
|
if (len > 0) |
96 |
/* add up any last odd byte */ |
{ |
97 |
if (len == 1) { |
/* accumulate remaining octet */ |
98 |
acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8); |
acc += (*octetptr); |
|
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %"U16_F"\n", (u16_t)(*(u8_t *)dataptr))); |
|
|
} else { |
|
|
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: no odd byte\n")); |
|
99 |
} |
} |
100 |
acc = (acc >> 16) + (acc & 0xffffUL); |
/* add deferred carry bits */ |
101 |
|
acc = (acc >> 16) + (acc & 0x0000ffffUL); |
102 |
if ((acc & 0xffff0000) != 0) { |
if ((acc & 0xffff0000) != 0) { |
103 |
acc = (acc >> 16) + (acc & 0xffffUL); |
acc = (acc >> 16) + (acc & 0x0000ffffUL); |
104 |
} |
} |
105 |
return (u16_t)acc; |
/* caller must invert bits for Internet sum ! */ |
106 |
|
return htons((u16_t)acc); |
107 |
} |
} |
108 |
|
|
109 |
#endif |
#endif |