12345678901234567890123456789012345678901234567890123456789012345678901234567890 | |
pbuf vs. netbuf | |
=============== | |
pbuf -- internal representation of a packet (should not be directly accessed | |
when using netconn or socket API). | |
PBUF_POOL -- one struct containing header + data buffer (+ space reserved for | |
headers) obtained from a pool of limited amount of statically allocated | |
structs (i.e. slab allocator). | |
The size of the whole struct is fixed, in case the data are bigger than the | |
pre-allocated buffer in a struct, multiple pbufs are chained together | |
This kind of pbuf is mostly used for RX. | |
PBUF_RAM -- Pbuf allocated dynamically on a heap (internal heap of the lwip). | |
The advantage is that the exact amount of buffer space is allocated (data + | |
headers). The disadvantage is that the allocation takes some time (+ general | |
heap allocation issues like fragmentation etc.) | |
This kind of pbuf is mostly used for TX. | |
PBUF_ROM -- Pbuf header is allocated on heap, the payload is stored on some | |
ROM/Flash device, referenced from the pbuf header. | |
Used for transmitting statically allocated payloads/data (hard-coded HTML | |
webpage?) | |
netbuf -- may contain chain of pbufs. Datatype used when receiving/transmitting | |
with the netconn API | |
Reusing pbufs (https://lists.gnu.org/archive/html/lwip-users/2010-02/msg00198.html) | |
------------- | |
> I have a simple application that sends out a UDP packet every few seconds. | |
> When using the raw API, I created a raw pbuf in ram, filled the payload, | |
> and then had udp_send() send that same pbuf over and over from my lwip | |
> task. | |
This is only valid when you don't have a DMA-enabled MAC. Or in other words you | |
may only re-use the pbufs (after udp_send returns), when their reference | |
coutner (p->ref) is 1 (which means noone else is using it). With a DMA-enabled | |
MAC, the driver calls pbuf_ref (p->ref++) and enqueues the packet for sending, | |
which means udp_send can return before the packet is sent. If you then pass the | |
pbuf to udp_send again, the IP and ethernet headers (which are in the same | |
pbuf!) get changed and the previous packet may get corrupted while sending | |
through DMA. | |
[...] | |
> Are netbufs only designed to be used once and then thrown away? | |
I think they are. | |
APIs | |
==== | |
/-------------------------------\ | |
|/----------------\ | | |
||/-----\ | | | |
||| Raw | Netconn | BSD sockets | | |
||\-----/ | | | |
|\----------------/ | | |
\-------------------------------/ | |
Raw API | |
------- | |
* non-blocking (does not require thread context -- used without an OS) | |
* event-driven (callbacks) | |
* without an OS | |
* zero-copy | |
tcp_recv() sets a callback used to receive the data. You must call tcp_recved() | |
to tell lwip when you have processed the received data. | |
Netconn API | |
----------- | |
* sequential blocking API (requires thread context) | |
* used with an OS | |
* zero-copy | |
netconn_recv() returns a netbuf which may contain a chain of pbufs | |
BSD sockets | |
----------- | |
* compatible with BSD sockets (surprisingly) | |
LwIP configuration | |
================== | |
include/arch/lwipopts.h: (http://lwip.wikia.com/wiki/Tuning_TCP) | |
user-defined options. Might be overridden by include/lwip/opt.h | |
| https://lists.gnu.org/archive/html/lwip-users/2007-04/msg00006.html | |
| >I want to know why there is need for two files lwipopts.h , opts.h. | |
| >They look redundant. | |
| opt.h defines what can be configured and a standard option for this. | |
| lwipopts.h is for the user to configure the stack. The two file are | |
| needed because the options are tested using #if LWIP_XXX, which means | |
| they _must_ exist (in contrast to #ifdef). If opt.h was not included, | |
| nobody would know all the existing options... | |
MEM_SIZE -- lwip heap size. Used for allocating PBUF_RAM pbufs. | |
MEMP_NUM_PBUF -- | |
MEMP_NUM_TCP_PCB -- Each active TCP connection is represented by the TCB structure | |
in the OS (holding information about IP addresses, ports, sliding window, etc.). | |
The number of simultaneously active TCP connections. | |
MEMP_NUM_TCP_PCB_LISTEN -- The number of listening TCP connections. | |
PBUF_POOL_SIZE -- The number of statically allocated PBUF_POOL pbufs. These are | |
mostly used for RX. | |
LWIP_SO_SNDTIMEO -- Enable send timeout for sockets/netconns | |
LWIP_SO_RCVTIMEO -- Enable receive timeout for sockets/netconns | |
TCP_MSS -- https://en.wikipedia.org/wiki/Maximum_segment_size | |
The maximum segment size (MSS) is a parameter of the TCP protocol that | |
specifies the largest amount of data, specified in octets, that a computer | |
or communications device can receive in a single TCP segment. It does not | |
count the TCP header or the IP header. | |
For maximum throughput, set this as high as possible for your network | |
(i.e. 1460 bytes for standard Ethernet). | |
TCP_WND -- TCP window size. | |
Do keep in mind that this should be at least twice the size of TCP_MSS. | |
If memory allows it, set this as high as possible (16-bit, so 0xFFFF is | |
the highest value), but keep in mind that for every active connection, | |
the full window may have to be buffered until it is acknowledged by the | |
remote side. | |
TCP_SND_BUF -- | |
LWIP_STATS_DISPLAY -- | |
Further reading | |
=============== | |
[] https://www.sics.se/~adam/thesis.pdf | |
Adam Dunkels, 2001, LwIP Technical Report | |
old but still *very* valid document describing the LwIP architecture | |
[] http://www.atmel.com/Images/Atmel-42233-Using-the-lwIP-Network-Stack_AP-Note_AT04055.pdf | |
Atmel Application Note, Using the LwIP network stack | |
Good explanation of different APIs, pbuf structure, code examples | |
[] http://lwip.wikia.com/wiki/LwIP_Wiki | |
Official LwIP wiki | |
Full of annoying ads but still a good source of information |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment