Added Curt McDowell's platform-independent optimized checksum routine.

This commit is contained in:
likewise 2005-12-14 22:51:35 +00:00
parent 6facaf8f05
commit 02b575e9e4
3 changed files with 140 additions and 1 deletions

View File

@ -11,6 +11,15 @@ FUTURE
HISTORY HISTORY
2005-12-15 Christiaan Simons
* inet.c: Standard checksum routine fixed in proper portable C.
2005-12-14 Leon Woestenberg <leon.woestenberg@gmx.net>
* inet.c: Duplicate FIN ACK race condition fix by Kelvin Lawson.
Added Curt McDowell's optimized checksumming routine for future
inclusion. Need to create test case for unaliged, aligned, odd,
even length combination of cases on various endianess machines.
2005-07-17 Leon Woestenberg <leon.woestenberg@gmx.net> 2005-07-17 Leon Woestenberg <leon.woestenberg@gmx.net>
* inet.c: Fixed unaligned 16-bit access in the standard checksum * inet.c: Fixed unaligned 16-bit access in the standard checksum
routine by Peter Jolasson. routine by Peter Jolasson.

View File

@ -80,7 +80,7 @@ lwip_standard_chksum(void *dataptr, u16_t len)
octetptr = (u8_t*)dataptr; octetptr = (u8_t*)dataptr;
while (len > 1) while (len > 1)
{ {
/* delacre first octet as most significant /* declare first octet as most significant
thus assume network order, ignoring host order */ thus assume network order, ignoring host order */
src = (*octetptr) << 8; src = (*octetptr) << 8;
octetptr++; octetptr++;
@ -109,6 +109,133 @@ lwip_standard_chksum(void *dataptr, u16_t len)
#endif #endif
Curt McDowell
Broadcom Corp.
csm@broadcom.com
/*
* IP checksum two bytes at a time with support for
* unaligned buffer.
* Works for len up to and including 0x20000.
* by Curt McDowell, Broadcom Corp. 12/08/2005
*/
static u16_t
lwip_standard_chksum2(void *dataptr, int len)
{
u8_t *pb = dataptr;
u16_t *ps, t = 0;
u32_t sum = 0;
int odd = ((u32_t)pb & 1);
/* Get aligned to u16_t */
if (odd && len > 0) {
((u8_t *)&t)[1] = *pb++;
len--;
}
/* Add the bulk of the data */
ps = (u16_t *)pb;
while (len > 1) {
sum += *ps++;
len -= 2;
}
/* Consume left-over byte, if any */
if (len > 0)
((u8_t *)&t)[0] = *(u8_t *)ps;;
/* Add end bytes */
sum += t;
/* Fold 32-bit sum to 16 bits */
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
/* Swap if alignment was odd */
if (odd)
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
return sum;
}
#if 0
/**
* An optimized checksum routine. Basically, it uses loop-unrolling on
* the checksum loop, treating the head and tail bytes specially, whereas
* the inner loop acts on 8 bytes at a time.
*
* @arg start of buffer to be checksummed. May be an odd byte address.
* @len number of bytes in the buffer to be checksummed.
*
* @todo First argument type conflicts with generic checksum routine.
*
* by Curt McDowell, Broadcom Corp. December 8th, 2005
*/
static u16_t
lwip_standard_chksum4(u8_t *pb, int len)
{
u16_t *ps, t = 0;
u32_t *pl;
u32_t sum = 0, tmp;
/* starts at odd byte address? */
int odd = ((u32_t)pb & 1);
if (odd && len > 0) {
((u8_t *)&t)[1] = *pb++;
len--;
}
ps = (u16_t *)pb;
if (((u32_t)ps & 3) && len > 1) {
sum += *ps++;
len -= 2;
}
pl = (u32_t *)ps;
while (len > 7) {
tmp = sum + *pl++; /* ping */
if (tmp < sum)
tmp++; /* add back carry */
sum = tmp + *pl++; /* pong */
if (sum < tmp)
sum++; /* add back carry */
len -= 8;
}
/* make room in upper bits */
sum = (sum >> 16) + (sum & 0xffff);
ps = (u16_t *)pl;
/* 16-bit aligned word remaining? */
while (len > 1) {
sum += *ps++;
len -= 2;
}
/* dangling tail byte remaining? */
if (len > 0) /* include odd byte */
((u8_t *)&t)[0] = *(u8_t *)ps;
sum += t; /* add end bytes */
while (sum >> 16) /* combine halves */
sum = (sum >> 16) + (sum & 0xffff);
if (odd)
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
return sum;
}
#endif
/* inet_chksum_pseudo: /* inet_chksum_pseudo:
* *
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.

View File

@ -39,6 +39,9 @@
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
u16_t inet_chksum(void *dataptr, u16_t len); u16_t inet_chksum(void *dataptr, u16_t len);
#if 0 // optimized routine
u16_t inet_chksum4(u8_t *dataptr, u16_t len);
#endif
u16_t inet_chksum_pbuf(struct pbuf *p); u16_t inet_chksum_pbuf(struct pbuf *p);
u16_t inet_chksum_pseudo(struct pbuf *p, u16_t inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest, struct ip_addr *src, struct ip_addr *dest,