Unaligned 16-bit access fix for the standard checksum routine by Peter Jolasson.

This commit is contained in:
likewise 2005-07-17 15:30:27 +00:00
parent e11d57c883
commit f05d392920

View File

@ -51,7 +51,8 @@
/* This is a reference implementation of the checksum algorithm /* This is a reference implementation of the checksum algorithm
- it may not work on all architectures, and all processors, particularly - it may not work on all architectures, and all processors, particularly
if they have issues with alignment and 16 bit access. if they have issues with alignment and 16 bit access (although this should
be fixed since inet.c 1.22).
- in this case you will need to port it to your architecture and - in this case you will need to port it to your architecture and
#define LWIP_CHKSUM <your_checksum_routine> #define LWIP_CHKSUM <your_checksum_routine>
@ -63,15 +64,22 @@ static u16_t
lwip_standard_chksum(void *dataptr, int len) lwip_standard_chksum(void *dataptr, int len)
{ {
u32_t acc; u32_t acc;
LWIP_DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %d)\n", (void *)dataptr, len)); LWIP_DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %d)\n", (void *)dataptr, len));
/* iterate by two bytes at once */
for(acc = 0; len > 1; len -= 2) { for(acc = 0; len > 1; len -= 2) {
/* acc = acc + *((u16_t *)dataptr)++;*/ /* WAS: acc = acc + *((u16_t *)dataptr)++; BUT THIS IS BROKEN FOR
* ARCHITECTURES WHICH DO NOT ALLOW UNALIGNED 16-BIT ACCESSES */
#if MEM_ALIGNMENT >= 2
acc += htons( ((u16_t)(((u8_t *)dataptr)[0])<<8) | ((u8_t *)dataptr)[1] );
dataptr += 2;
#else
acc += *(u16_t *)dataptr; acc += *(u16_t *)dataptr;
dataptr = (void *)((u16_t *)dataptr + 1); dataptr = (void *)((u16_t *)dataptr + 1);
#endif
} }
/* add up any odd byte */ /* add up any last odd byte */
if (len == 1) { if (len == 1) {
acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8); acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8);
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", (unsigned int)(*(u8_t *)dataptr))); LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", (unsigned int)(*(u8_t *)dataptr)));
@ -79,13 +87,12 @@ lwip_standard_chksum(void *dataptr, int len)
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: no odd byte\n")); LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: no odd byte\n"));
} }
acc = (acc >> 16) + (acc & 0xffffUL); acc = (acc >> 16) + (acc & 0xffffUL);
if ((acc & 0xffff0000) != 0) { if ((acc & 0xffff0000) != 0) {
acc = (acc >> 16) + (acc & 0xffffUL); acc = (acc >> 16) + (acc & 0xffffUL);
} }
return (u16_t)acc; return (u16_t)acc;
} }
#endif #endif
/* inet_chksum_pseudo: /* inet_chksum_pseudo: