Instead of the BSD approach of generic buffers, the sequential API uses netbufs, which are based on pbufs. This allows users to manage buffers directly, including even allowing data to come from ROM. Since pbufs, and hence netbufs, can be chained, this also allows the application and lwIP to avoid the need for large regions of entirely contiguous memory in order to hold data. Instead data can be constructed in chunks, and chained together.
When the application wishes to send data, it can send a netbuf directly with UDP. TCP is different as it is intrinsically a buffering, streaming protocol, which requires data to be kept aside to allow for retransmissions. As a result data is sent using just a pointer to memory and a length. However since TCP data can also reside in ROM, it is possible to indicate that the data does not need copying, and so will persist even if the stack needs to queue the data. This can lead to huge savings of memory. For example, static web page content can reside in ROM, and never need to be copied to RAM.
For both TCP and UDP, incoming data is passed to the application as
netbufs. The application can use API functions to extract the data from
the netbufs - care must be taken as the received data may in fact be
a chain. A convenience function exists to copy out the entirety of
data across the whole chain into a single contiguous region of memory.
Otherwise the application can process data in each netbuf in the
chain in turn. The functions
netbuf_next() can be used to iterate
throught the chain.