lwIP does not only possess features allowing it by itself to maintain a small footprint,
but also has design aspects which allow it to work with the application to reduce
footprint. One important case of this is lwIP packet data buffers.
Packet data buffers in lwIP are termed
pbufs. Pbufs can be chained together in fairly
arbitrary ways to create a pbuf chain. The idea
is that the application can pass the stack a pbuf of data to transmit,
and the stack can prepend and possibly append other pbufs to encapsulate
the data in protocol headers/footers without having to copy the data
elsewhere, thus saving resources. In some cases, depending on precisely
how the pbuf was allocated, the stack may even be able to fit protocol
headers inside the pbuf passed to it. It also means that the
application can itself provide data allocated in differing ways and from
different locations, but assembled together as a pbuf chain. This will
ensure that the data is treated as if it were all allocated
contiguously. When using the sequential API, the underlying pbufs are
wrapped in a netbuf construct in order to provide a
simpler API to manipulate data in buffers; but the underlying
functionality remains based on pbufs.
When a pbuf is created, it must be one of a variety of types:
PBUF_RAM
This is a conventional buffer, which points to data allocated from a pool in RAM
managed by lwIP. On creation the buffer size must be given.
PBUF_ROM
This is a buffer pointing to immutable read-only data. This allows fixed
literal data to be stored in ROM/Flash rather than using up precious
RAM. Note that data pointed at by a PBUF_ROM pbuf does not literally
have to point at read-only memory. All it means is that the data must
not change, even if control has returned to the application. The pbuf
data may still be being referenced as part of a packet waiting in a
queue to be transmitted, or more often, waiting in a queue in case
retransmission is necessary.
PBUF_REF
This is a buffer pointing to mutable data, passed in by reference. This
means data provided by the application allocated from its own resources,
and which could change in the future. This differs from PBUF_RAM packets
in that the data is allocated by the application, and not from lwip's
PBUF_RAM buffer memory pool. As the application could change the data
after control is returned to it, if lwIP finds it must enqueue the pbuf,
it will internally copy the data to a new PBUF_RAM. The benefits of this
type of packet occur when the packet does not need to be enqueued, and
so no PBUF_RAM pbuf needs to be allocated.