mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-12-23 21:14:18 +00:00
Added Curt McDowell's platform-independent optimized checksum routine.
This commit is contained in:
parent
6facaf8f05
commit
02b575e9e4
@ -11,6 +11,15 @@ FUTURE
|
||||
|
||||
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>
|
||||
* inet.c: Fixed unaligned 16-bit access in the standard checksum
|
||||
routine by Peter Jolasson.
|
||||
|
129
src/core/inet.c
129
src/core/inet.c
@ -80,7 +80,7 @@ lwip_standard_chksum(void *dataptr, u16_t len)
|
||||
octetptr = (u8_t*)dataptr;
|
||||
while (len > 1)
|
||||
{
|
||||
/* delacre first octet as most significant
|
||||
/* declare first octet as most significant
|
||||
thus assume network order, ignoring host order */
|
||||
src = (*octetptr) << 8;
|
||||
octetptr++;
|
||||
@ -109,6 +109,133 @@ lwip_standard_chksum(void *dataptr, u16_t len)
|
||||
|
||||
#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:
|
||||
*
|
||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||
|
@ -39,6 +39,9 @@
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
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_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
|
Loading…
Reference in New Issue
Block a user