mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-10-02 12:52:10 +00:00
task #7013: Added option LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only one pbuf to help MACs that don't support scatter-gather DMA.
This commit is contained in:
parent
105d72a3c2
commit
22d6558f13
@ -19,6 +19,11 @@ HISTORY
|
|||||||
|
|
||||||
++ New features:
|
++ New features:
|
||||||
|
|
||||||
|
2009-05-10 Simon Goldschmidt
|
||||||
|
* opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option
|
||||||
|
LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only
|
||||||
|
one pbuf to help MACs that don't support scatter-gather DMA.
|
||||||
|
|
||||||
2009-05-09 Simon Goldschmidt
|
2009-05-09 Simon Goldschmidt
|
||||||
* icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming
|
* icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming
|
||||||
ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||||
|
@ -668,7 +668,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||||||
{
|
{
|
||||||
struct lwip_socket *sock;
|
struct lwip_socket *sock;
|
||||||
struct ip_addr remote_addr;
|
struct ip_addr remote_addr;
|
||||||
int err;
|
err_t err;
|
||||||
u16_t short_size;
|
u16_t short_size;
|
||||||
#if !LWIP_TCPIP_CORE_LOCKING
|
#if !LWIP_TCPIP_CORE_LOCKING
|
||||||
struct netbuf buf;
|
struct netbuf buf;
|
||||||
@ -740,15 +740,23 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
|
||||||
|
|
||||||
/* make the buffer point to the data that should be sent */
|
/* make the buffer point to the data that should be sent */
|
||||||
if ((err = netbuf_ref(&buf, data, short_size)) == ERR_OK) {
|
#if LWIP_NETIF_TX_SINGLE_PBUF
|
||||||
|
/* Allocate a new netbuf and copy the data into it. */
|
||||||
|
if (netbuf_alloc(&buf, short_size) == NULL) {
|
||||||
|
err = ERR_MEM;
|
||||||
|
} else {
|
||||||
|
err = netbuf_take(&buf, data, short_size);
|
||||||
|
}
|
||||||
|
#else /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
|
err = netbuf_ref(&buf, data, short_size);
|
||||||
|
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
|
if (err == ERR_OK) {
|
||||||
/* send the data */
|
/* send the data */
|
||||||
err = netconn_send(sock->conn, &buf);
|
err = netconn_send(sock->conn, &buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* deallocated the buffer */
|
/* deallocated the buffer */
|
||||||
if (buf.p != NULL) {
|
netbuf_free(&buf);
|
||||||
pbuf_free(buf.p);
|
|
||||||
}
|
|
||||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||||
sock_set_errno(sock, err_to_errno(err));
|
sock_set_errno(sock, err_to_errno(err));
|
||||||
return (err == ERR_OK ? short_size : -1);
|
return (err == ERR_OK ? short_size : -1);
|
||||||
|
@ -790,8 +790,8 @@ pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
|||||||
u16_t buf_copy_len;
|
u16_t buf_copy_len;
|
||||||
u16_t copied_total = 0;
|
u16_t copied_total = 0;
|
||||||
|
|
||||||
LWIP_ERROR("netbuf_copy_partial: invalid buf", (buf != NULL), return 0;);
|
LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;);
|
||||||
LWIP_ERROR("netbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);
|
LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);
|
||||||
|
|
||||||
left = 0;
|
left = 0;
|
||||||
|
|
||||||
@ -819,3 +819,76 @@ pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
|||||||
}
|
}
|
||||||
return copied_total;
|
return copied_total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy application supplied data into a pbuf.
|
||||||
|
* This function can only be used to copy the equivalent of buf->tot_len data.
|
||||||
|
*
|
||||||
|
* @param buf pbuf to fill with data
|
||||||
|
* @param dataptr application supplied data buffer
|
||||||
|
* @param len length of the application supplied data buffer
|
||||||
|
*
|
||||||
|
* @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
|
||||||
|
{
|
||||||
|
struct pbuf *p;
|
||||||
|
u16_t buf_copy_len;
|
||||||
|
u16_t total_copy_len = len;
|
||||||
|
u16_t copied_total = 0;
|
||||||
|
|
||||||
|
LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;);
|
||||||
|
LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;);
|
||||||
|
|
||||||
|
if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) {
|
||||||
|
return ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
|
||||||
|
for(p = buf; total_copy_len != 0; p = p->next) {
|
||||||
|
LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL);
|
||||||
|
buf_copy_len = total_copy_len;
|
||||||
|
if (buf_copy_len > p->len) {
|
||||||
|
/* this pbuf cannot hold all remaining data */
|
||||||
|
buf_copy_len = p->len;
|
||||||
|
}
|
||||||
|
/* copy the necessary parts of the buffer */
|
||||||
|
MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len);
|
||||||
|
total_copy_len -= buf_copy_len;
|
||||||
|
copied_total += buf_copy_len;
|
||||||
|
}
|
||||||
|
LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a single pbuf out of a queue of pbufs.
|
||||||
|
*
|
||||||
|
* @remark: The source pbuf 'p' is not freed by this function because that can
|
||||||
|
* be illegal in some places!
|
||||||
|
*
|
||||||
|
* @param p the source pbuf
|
||||||
|
* @param layer pbuf_layer of the new pbuf
|
||||||
|
*
|
||||||
|
* @return a new, single pbuf (p->next is NULL)
|
||||||
|
* or the old pbuf if allocation fails
|
||||||
|
*/
|
||||||
|
struct pbuf*
|
||||||
|
pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
|
||||||
|
{
|
||||||
|
struct pbuf *q;
|
||||||
|
err_t err;
|
||||||
|
if (p->next == NULL) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
q = pbuf_alloc(layer, p->tot_len, PBUF_RAM);
|
||||||
|
if (q == NULL) {
|
||||||
|
/* @todo: what do we do now? */
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
err = pbuf_copy(q, p);
|
||||||
|
LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
|
||||||
|
pbuf_free(p);
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
@ -65,6 +65,7 @@ void netbuf_first (struct netbuf *buf);
|
|||||||
#define netbuf_copy_partial(buf, dataptr, len, offset) \
|
#define netbuf_copy_partial(buf, dataptr, len, offset) \
|
||||||
pbuf_copy_partial((buf)->p, (dataptr), (len), (offset))
|
pbuf_copy_partial((buf)->p, (dataptr), (len), (offset))
|
||||||
#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
|
#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
|
||||||
|
#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len)
|
||||||
#define netbuf_len(buf) ((buf)->p->tot_len)
|
#define netbuf_len(buf) ((buf)->p->tot_len)
|
||||||
#define netbuf_fromaddr(buf) ((buf)->addr)
|
#define netbuf_fromaddr(buf) ((buf)->addr)
|
||||||
#define netbuf_fromport(buf) ((buf)->port)
|
#define netbuf_fromport(buf) ((buf)->port)
|
||||||
|
@ -965,6 +965,19 @@
|
|||||||
#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS)
|
#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data
|
||||||
|
* to be sent into one single pbuf. This is for compatibility with DMA-enabled
|
||||||
|
* MACs that do not support scatter-gather.
|
||||||
|
* Beware that this might involve CPU-memcpy before transmitting that would not
|
||||||
|
* be needed without this flag! Use this only if you need to!
|
||||||
|
*
|
||||||
|
* @todo: TCP and IP-frag do not work with this, yet:
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_NETIF_TX_SINGLE_PBUF
|
||||||
|
#define LWIP_NETIF_TX_SINGLE_PBUF 0
|
||||||
|
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
------------------------------------
|
------------------------------------
|
||||||
---------- LOOPIF options ----------
|
---------- LOOPIF options ----------
|
||||||
|
@ -110,6 +110,8 @@ void pbuf_chain(struct pbuf *head, struct pbuf *tail);
|
|||||||
struct pbuf *pbuf_dechain(struct pbuf *p);
|
struct pbuf *pbuf_dechain(struct pbuf *p);
|
||||||
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from);
|
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);
|
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);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user