Fixed lwip_standard_chksum() for unaligned memory access. Verified to work on c16x and BSD on P4.

This commit is contained in:
christiaans 2005-12-09 08:59:08 +00:00
parent 33fbb06604
commit 43d448e73f

View File

@ -60,37 +60,50 @@
*/ */
#ifndef LWIP_CHKSUM #ifndef LWIP_CHKSUM
#define LWIP_CHKSUM lwip_standard_chksum #define LWIP_CHKSUM lwip_standard_chksum
/**
* lwip checksum
*
* @param dataptr points to start of data to be summed at any boundary
* @param len length of data to be summed
* @return network order (!) lwip checksum (non-inverted Internet sum)
*
* @note accumulator size limits summable lenght to 64k
* @note host endianess is irrelevant (p3 RFC1071)
*/
static u16_t static u16_t
lwip_standard_chksum(void *dataptr, int len) lwip_standard_chksum(void *dataptr, u16_t len)
{ {
u32_t acc; u32_t acc;
LWIP_DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %"S16_F")\n", (void *)dataptr, len)); u16_t src;
u8_t *octetptr;
/* iterate by two bytes at once */ acc = 0;
for(acc = 0; len > 1; len -= 2) { /* dataptr may be at odd or even addresses */
/* WAS: acc = acc + *((u16_t *)dataptr)++; BUT THIS IS BROKEN FOR octetptr = (u8_t*)dataptr;
* ARCHITECTURES WHICH DO NOT ALLOW UNALIGNED 16-BIT ACCESSES */ while (len > 1)
#if MEM_ALIGNMENT >= 2 {
acc += htons( ((u16_t)(((u8_t *)dataptr)[0])<<8) | ((u8_t *)dataptr)[1] ); /* first octet is most significant */
(void *)((u16_t *)dataptr + 1); src = (*octetptr) << 8;
#else octetptr++;
acc += *(u16_t *)dataptr; /* second octet is least significant */
dataptr = (void *)((u16_t *)dataptr + 1); src |= (*octetptr);
#endif octetptr++;
acc += src;
len -= 2;
} }
if (len > 0)
/* add up any last odd byte */ {
if (len == 1) { /* accumulate remaining octet */
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"));
} }
acc = (acc >> 16) + (acc & 0xffffUL); /* add deferred carry bits */
acc = (acc >> 16) + (acc & 0x0000ffffUL);
if ((acc & 0xffff0000) != 0) { if ((acc & 0xffff0000) != 0) {
acc = (acc >> 16) + (acc & 0xffffUL); acc = (acc >> 16) + (acc & 0x0000ffffUL);
} }
return (u16_t)acc; /* caller must invert bits for Internet sum ! */
return htons((u16_t)acc);
} }
#endif #endif