mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-04 14:29:39 +00:00
task #6849: added udp_send(_to/_if) functions that take a precalculated checksum, added pbuf_fill_chksum() to copy data into a pbuf and at the same time calculating the checksum for that data
This commit is contained in:
parent
3685bc4828
commit
f98e5717e5
@ -13,6 +13,11 @@ HISTORY
|
||||
|
||||
++ New features:
|
||||
|
||||
2010-04-30: Simon Goldschmidt
|
||||
* udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that
|
||||
take a precalculated checksum, added pbuf_fill_chksum() to copy data
|
||||
into a pbuf and at the same time calculating the checksum for that data
|
||||
|
||||
2010-04-29: Simon Goldschmidt
|
||||
* ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying
|
||||
2-byte-aligned IP addresses and MAC addresses
|
||||
|
@ -73,6 +73,9 @@
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
#include "lwip/tcp_impl.h"
|
||||
#endif
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
#include "lwip/inet_chksum.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -927,3 +930,44 @@ pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
|
||||
pbuf_free(p);
|
||||
return q;
|
||||
}
|
||||
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
/**
|
||||
* Copies data into a single pbuf (*not* into a pbuf queue!) and updates
|
||||
* the checksum while copying
|
||||
*
|
||||
* @param p the pbuf to copy data into
|
||||
* @param start_offset offset of p->payload where to copy the data to
|
||||
* @param dataptr data to copy into the pbuf
|
||||
* @param len length of data to copy into the pbuf
|
||||
* @param chksum pointer to the checksum which is updated
|
||||
* @return ERR_OK if successful, another error if the data does not fit
|
||||
* within the (first) pbuf (no pbuf queues!)
|
||||
*/
|
||||
err_t
|
||||
pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
|
||||
u16_t len, u16_t *chksum)
|
||||
{
|
||||
u32_t acc;
|
||||
u16_t copy_chksum;
|
||||
char *dst_ptr;
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
LWIP_ASSERT("dataptr != NULL", dataptr != NULL);
|
||||
LWIP_ASSERT("chksum != NULL", chksum != NULL);
|
||||
LWIP_ASSERT("len != 0", len != 0);
|
||||
|
||||
if ((start_offset >= p->len) || (start_offset + len > p->len)) {
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
dst_ptr = ((char*)p->payload) + start_offset;
|
||||
copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len);
|
||||
if ((start_offset & 1) != 0) {
|
||||
copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum);
|
||||
}
|
||||
acc = *chksum;
|
||||
acc += copy_chksum;
|
||||
*chksum = FOLD_U32T(acc);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
@ -336,6 +336,19 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port);
|
||||
}
|
||||
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
/** Same as udp_send() but with checksum
|
||||
*/
|
||||
err_t
|
||||
udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
u8_t have_chksum, u16_t chksum)
|
||||
{
|
||||
/* send to the packet using remote ip and port stored in the pcb */
|
||||
return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port,
|
||||
have_chksum, chksum);
|
||||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
/**
|
||||
* Send data to a specified address using UDP.
|
||||
*
|
||||
@ -357,6 +370,16 @@ err_t
|
||||
udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port)
|
||||
{
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0);
|
||||
}
|
||||
|
||||
/** Same as udp_sendto(), but with checksum */
|
||||
err_t
|
||||
udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
u16_t dst_port, u8_t have_chksum, u16_t chksum)
|
||||
{
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
struct netif *netif;
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
|
||||
@ -375,7 +398,11 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum);
|
||||
#else /* LWIP_CHECKSUM_ON_COPY */
|
||||
return udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
}
|
||||
|
||||
/**
|
||||
@ -401,6 +428,17 @@ err_t
|
||||
udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif)
|
||||
{
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0);
|
||||
}
|
||||
|
||||
/** Same as udp_sendto_if(), but with checksum */
|
||||
err_t
|
||||
udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
u16_t dst_port, struct netif *netif, u8_t have_chksum,
|
||||
u16_t chksum)
|
||||
{
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
struct udp_hdr *udphdr;
|
||||
ip_addr_t *src_ip;
|
||||
err_t err;
|
||||
@ -501,7 +539,18 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
|
||||
IP_PROTO_UDPLITE, q->tot_len, chklen);
|
||||
IP_PROTO_UDPLITE, q->tot_len,
|
||||
#if !LWIP_CHECKSUM_ON_COPY
|
||||
chklen);
|
||||
#else /* !LWIP_CHECKSUM_ON_COPY */
|
||||
(have_chksum ? UDP_HLEN : chklen));
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
acc = udphdr->chksum + (u16_t)~(chksum);
|
||||
udphdr->chksum = FOLD_U32T(acc);
|
||||
}
|
||||
#endif /* !LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) {
|
||||
udphdr->chksum = 0xffff;
|
||||
@ -524,11 +573,25 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
||||
udphdr->chksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) {
|
||||
udphdr->chksum = 0xffff;
|
||||
u16_t udpchksum;
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP,
|
||||
q->tot_len, UDP_HLEN);
|
||||
acc = udpchksum + (u16_t)~(chksum);
|
||||
udpchksum = FOLD_U32T(acc);
|
||||
} else
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
{
|
||||
udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
|
||||
}
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udpchksum == 0x0000) {
|
||||
udpchksum = 0xffff;
|
||||
}
|
||||
udphdr->chksum = udpchksum;
|
||||
}
|
||||
#endif /* CHECKSUM_GEN_UDP */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
|
||||
|
@ -111,6 +111,10 @@ err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from);
|
||||
u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
|
||||
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
|
||||
struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer);
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
|
||||
u16_t len, u16_t *chksum);
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -135,6 +135,18 @@ err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port);
|
||||
err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);
|
||||
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port,
|
||||
struct netif *netif, u8_t have_chksum,
|
||||
u16_t chksum);
|
||||
err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port,
|
||||
u8_t have_chksum, u16_t chksum);
|
||||
err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
u8_t have_chksum, u16_t chksum);
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
#define udp_flags(pcb) ((pcb)->flags)
|
||||
#define udp_setflags(pcb, f) ((pcb)->flags = (f))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user