[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: [lwip-users] lwip_standard_chksum()
From: |
Curt McDowell |
Subject: |
RE: [lwip-users] lwip_standard_chksum() |
Date: |
Thu, 8 Dec 2005 16:41:31 -0800 |
Timmy Brolin wrote:
> Yes, I think I might have a better idea.
> This solution would even improve performance on machines
> which support unaligned memory accesses [...]
Tim, I've done what you've suggested before.
I'd like to contribute the following two masterpieces for inclusion in lwip
:-) They handle arbitrary alignment and are "reasonably" fast. While I've
done quite a bit of testing, of course there is no warranty on this code
express or implied -- use at your own risk.
Regards,
Curt McDowell
Broadcom Corp.
address@hidden
/*
* 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;
}
/*
* IP checksum four bytes at a time with support for
* unaligned buffer. Works for any length.
* by Curt McDowell, Broadcom Corp. 12/08/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;
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;
while (len > 1) { /* add 0-3 shorts */
sum += *ps++;
len -= 2;
}
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;
}
- [lwip-users] lwip_standard_chksum(), Christiaan Simons, 2005/12/07
- Re: [lwip-users] lwip_standard_chksum(), Atte Kojo, 2005/12/08
- Re: [lwip-users] lwip_standard_chksum(), Timmy Brolin, 2005/12/08
- RE: [lwip-users] lwip_standard_chksum(),
Curt McDowell <=
- RE: [lwip-users] lwip_standard_chksum(), Christiaan Simons, 2005/12/09
- Re: [lwip-users] lwip_standard_chksum(), Leon Woestenberg, 2005/12/09
- Re: [lwip-users] lwip_standard_chksum(), Leon Woestenberg, 2005/12/09
- RE: [lwip-users] lwip_standard_chksum(), Curt McDowell, 2005/12/09
- Re: [lwip-users] lwip_standard_chksum(), Leon Woestenberg, 2005/12/10
- Re: [lwip-users] lwip_standard_chksum(), Timmy Brolin, 2005/12/10
- Re: [lwip-users] lwip_standard_chksum(), Christiaan Simons, 2005/12/09