From 84ed9de21a1305cc7ceaa176355e332a10438ac3 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Sun, 14 Mar 2010 11:23:37 +0000 Subject: [PATCH] Prepared for checksum-on-copy (task #6849): - Added option LWIP_CHECKSUM_ON_COPY; - Added function + define lwip_chksum_copy to create checksum when copying data --- src/core/ipv4/inet_chksum.c | 36 +++++++++++++++++------------ src/include/ipv4/lwip/inet_chksum.h | 34 +++++++++++++++++++++++++-- src/include/lwip/opt.h | 9 +++++++- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/core/ipv4/inet_chksum.c b/src/core/ipv4/inet_chksum.c index 18a3bb53..fbba7bcc 100644 --- a/src/core/ipv4/inet_chksum.c +++ b/src/core/ipv4/inet_chksum.c @@ -42,6 +42,7 @@ #include "lwip/def.h" #include +#include /* These are some reference implementations of the checksum algorithm, with the * aim of being simple, correct and fully portable. Checksumming is the @@ -65,18 +66,6 @@ # define LWIP_CHKSUM_ALGORITHM 0 #endif -/** Like the name says... */ -#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) -/* little endian and PLATFORM_BYTESWAP defined */ -#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w) -#else -/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */ -#define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8) -#endif - -/** Split an u32_t in two u16_ts and add them up */ -#define FOLD_U32T(u) ((u >> 16) + (u & 0x0000ffffUL)) - #if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ /** * lwip checksum @@ -339,8 +328,6 @@ inet_chksum_pseudo(struct pbuf *p, * @param proto_len length of the ip data part (used for checksum of pseudo header) * @return checksum (as u16_t) to be saved directly in the protocol header */ -/* Currently only used by UDPLITE, although this could change in the future. */ -#if LWIP_UDPLITE u16_t inet_chksum_pseudo_partial(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, @@ -394,7 +381,6 @@ inet_chksum_pseudo_partial(struct pbuf *p, LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); return (u16_t)~(acc & 0xffffUL); } -#endif /* LWIP_UDPLITE */ /* inet_chksum: * @@ -442,3 +428,23 @@ inet_chksum_pbuf(struct pbuf *p) } return (u16_t)~(acc & 0xffffUL); } + +/* These are some implementations for LWIP_CHKSUM_COPY, which copies data + * like MEMCPY but generates a checksum at the same time. Since this is a + * performance-sensitive function, you might want to create your own version + * in assembly targeted at your hardware by defining it in lwipopts.h: + * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) + */ + +#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ +/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. + * For architectures with big caches, data might still be in cache when + * generating the checksum after copying. + */ +u16_t +lwip_chksum_copy(void *dst, const void *src, u16_t len) +{ + MEMCPY(dst, src, len); + return LWIP_CHKSUM(dst, len); +} +#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */ diff --git a/src/include/ipv4/lwip/inet_chksum.h b/src/include/ipv4/lwip/inet_chksum.h index 033de82f..79a2d90f 100644 --- a/src/include/ipv4/lwip/inet_chksum.h +++ b/src/include/ipv4/lwip/inet_chksum.h @@ -37,6 +37,35 @@ #include "lwip/pbuf.h" #include "lwip/ip_addr.h" +/** Swap the bytes in an u16_t: much like htons() for little-endian */ +#ifndef SWAP_BYTES_IN_WORD +#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) +/* little endian and PLATFORM_BYTESWAP defined */ +#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w) +#else /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) */ +/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */ +#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) +#endif /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)*/ +#endif /* SWAP_BYTES_IN_WORD */ + +/** Split an u32_t in two u16_ts and add them up */ +#ifndef FOLD_U32T +#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL)) +#endif + +#if LWIP_CHECKSUM_ON_COPY +/** Function-like macro: same as MEMCPY but returns the checksum of copied data + as u16_t */ +#ifndef LWIP_CHKSUM_COPY +#define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len) +#ifndef LWIP_CHKSUM_COPY_ALGORITHM +#define LWIP_CHKSUM_COPY_ALGORITHM 1 +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ +#endif /* LWIP_CHKSUM_COPY */ +#else /* LWIP_CHECKSUM_ON_COPY */ +#define LWIP_CHKSUM_COPY_ALGORITHM 0 +#endif /* LWIP_CHECKSUM_ON_COPY */ + #ifdef __cplusplus extern "C" { #endif @@ -46,11 +75,12 @@ u16_t inet_chksum_pbuf(struct pbuf *p); u16_t inet_chksum_pseudo(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t proto, u16_t proto_len); -#if LWIP_UDPLITE u16_t inet_chksum_pseudo_partial(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t proto, u16_t proto_len, u16_t chksum_len); -#endif +#if LWIP_CHKSUM_COPY_ALGORITHM +u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len); +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ #ifdef __cplusplus } diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 6109a916..d3796c2b 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -444,7 +444,6 @@ #define ETH_PAD_SIZE 0 #endif - /* -------------------------------- ---------- IP options ---------- @@ -1708,6 +1707,14 @@ #define CHECKSUM_CHECK_TCP 1 #endif +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#ifndef LWIP_CHECKSUM_ON_COPY +#define LWIP_CHECKSUM_ON_COPY 0 +#endif + /* --------------------------------------- ---------- Debugging options ----------