Inline generating IP checksum to save a function call

This commit is contained in:
goldsimon 2010-04-28 19:36:51 +00:00
parent 51061fb61e
commit 01d2a87f5d
2 changed files with 42 additions and 0 deletions

View File

@ -13,6 +13,9 @@ HISTORY
++ New features:
2010-04-28: Patch by Bill Auerbach
* ip.c: Inline generating IP checksum to save a function call
2010-04-14: Simon Goldschmidt
* tcpip.h/.c, timers.c: Added an overridable define to get informed when the
tcpip_thread processes messages or timeouts to implement a watchdog.

View File

@ -58,6 +58,17 @@
#include <string.h>
/** Set this to 0 in the rare case of wanting to call an extra function to
* generate the IP checksum (in contrast to calculating it on-the-fly). */
#ifndef LWIP_INLINE_IP_CHKSUM
#define LWIP_INLINE_IP_CHKSUM 1
#endif
#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP
#define CHECKSUM_GEN_IP_INLINE 1
#else
#define CHECKSUM_GEN_IP_INLINE 0
#endif
/**
* The interface that provided the packet for the current callback
* invocation.
@ -537,6 +548,9 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
#endif /* IP_OPTIONS_SEND */
struct ip_hdr *iphdr;
static u16_t ip_id = 0;
#if CHECKSUM_GEN_IP_INLINE
u32_t chk_sum;
#endif /* CHECKSUM_GEN_IP_INLINE */
/* pbufs passed to IP must have a ref-count of 1 as their payload pointer
gets altered as the packet is passed down the stack */
@ -582,14 +596,30 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
IPH_TTL_SET(iphdr, ttl);
IPH_PROTO_SET(iphdr, proto);
#if CHECKSUM_GEN_IP_INLINE
chk_sum = (proto << 8) | ttl;
#endif /* CHECKSUM_GEN_IP_INLINE */
/* dest cannot be NULL here */
ip_addr_copy(iphdr->dest, *dest);
#if CHECKSUM_GEN_IP_INLINE
chk_sum += iphdr->dest.addr & 0xFFFF;
chk_sum += iphdr->dest.addr >> 16;
#endif /* CHECKSUM_GEN_IP_INLINE */
IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos);
#if CHECKSUM_GEN_IP_INLINE
chk_sum += iphdr->_v_hl_tos;
#endif /* CHECKSUM_GEN_IP_INLINE */
IPH_LEN_SET(iphdr, htons(p->tot_len));
#if CHECKSUM_GEN_IP_INLINE
chk_sum += iphdr->_len;
#endif /* CHECKSUM_GEN_IP_INLINE */
IPH_OFFSET_SET(iphdr, 0);
IPH_ID_SET(iphdr, htons(ip_id));
#if CHECKSUM_GEN_IP_INLINE
chk_sum += iphdr->_id;
#endif /* CHECKSUM_GEN_IP_INLINE */
++ip_id;
if (ip_addr_isany(src)) {
@ -599,10 +629,19 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
ip_addr_copy(iphdr->src, *src);
}
#if CHECKSUM_GEN_IP_INLINE
chk_sum += iphdr->src.addr & 0xFFFF;
chk_sum += iphdr->src.addr >> 16;
chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
chk_sum = (chk_sum >> 16) + chk_sum;
chk_sum = ~chk_sum;
iphdr->_chksum = chk_sum; /* network order */
#else /* CHECKSUM_GEN_IP_INLINE */
IPH_CHKSUM_SET(iphdr, 0);
#if CHECKSUM_GEN_IP
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
#endif
#endif /* CHECKSUM_GEN_IP_INLINE */
} else {
/* IP header already included in p */
iphdr = (struct ip_hdr *)p->payload;