mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-17 17:10:03 +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
|
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.
|
||||||
|
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;
|
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.
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user