Packet buffers (PBUF)
Infrastructure

## Macros

#define | PBUF_NEEDS_COPY(p) ((p)->type_internal & PBUF_TYPE_FLAG_DATA_VOLATILE)

## Enumerations

enum | pbuf_layer { PBUF_TRANSPORT = 0 + (14 + 0 ) + 40 + 20, PBUF_IP = 0 + (14 + 0 ) + 40, PBUF_LINK = 0 + (14 + 0 ), PBUF_RAW_TX = 0, PBUF_RAW = 0 }
enum | pbuf_type { PBUF_RAM = ( 0x0200 | 0x80 | 0x00 ), PBUF_ROM = 0x01, PBUF_REF = ( 0x40 | 0x01 ), PBUF_POOL = ( 0x0100 | 0x80 | 0x02 ) }

## Functions

struct pbuf * | pbuf_alloc (pbuf_layer layer, u16_t length, pbuf_type type)
struct pbuf * | pbuf_alloc_reference (void *payload, u16_t length, pbuf_type type)
struct pbuf * | pbuf_alloced_custom (pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p, void *payload_mem, u16_t payload_mem_len)
void | pbuf_realloc (struct pbuf *p, u16_t new_len)
u8_t | pbuf_free (struct pbuf *p)
void | pbuf_ref (struct pbuf *p)
void | pbuf_cat (struct pbuf *h, struct pbuf *t)
void | pbuf_chain (struct pbuf *h, struct pbuf *t)
err_t | pbuf_copy (struct pbuf *p_to, const struct pbuf *p_from)
err_t | pbuf_copy_partial_pbuf (struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset)
u16_t | pbuf_copy_partial (const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
void * | pbuf_get_contiguous (const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset)
struct pbuf * | pbuf_skip (struct pbuf *in, u16_t in_offset, u16_t *out_offset)
err_t | pbuf_take (struct pbuf *buf, const void *dataptr, u16_t len)
err_t | pbuf_take_at (struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset)
struct pbuf * | pbuf_coalesce (struct pbuf *p, pbuf_layer layer)
struct pbuf * | pbuf_clone (pbuf_layer layer, pbuf_type type, struct pbuf *p)
u8_t | pbuf_get_at (const struct pbuf *p, u16_t offset)
int | pbuf_try_get_at (const struct pbuf *p, u16_t offset)
void | pbuf_put_at (struct pbuf *p, u16_t offset, u8_t data)
u16_t | pbuf_memcmp (const struct pbuf *p, u16_t offset, const void *s2, u16_t n)
u16_t | pbuf_memfind (const struct pbuf *p, const void *mem, u16_t mem_len, u16_t start_offset)

## Detailed Description

Packets are built from the pbuf data structure. It supports dynamic memory allocation for packet contents or can reference externally managed packet contents both in RAM and ROM. Quick allocation for incoming packets is provided through pools with fixed sized pbufs.

A packet may span over multiple pbufs, chained as a singly linked list. This is called a "pbuf chain".

Multiple packets may be queued, also using this singly linked list. This is called a "packet queue".

So, a packet queue consists of one or more pbuf chains, each of which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE NOT SUPPORTED!!! Use helper structs to queue multiple packets.

The differences between a pbuf chain and a packet queue are very precise but subtle.

The last pbuf of a packet has a ->tot_len field that equals the ->len field. It can be found by traversing the list. If the last pbuf of a packet has a ->next field other than NULL, more packets are on the queue.

Therefore, looping through a pbuf of a single packet, has an loop end condition (tot_len == p->len), NOT (next == NULL).

Example of custom pbuf usage: Zero-copy RX

## Macro Definition Documentation

## PBUF_NEEDS_COPY

#define PBUF_NEEDS_COPY | ( |  | p | ) | ((p)->type_internal & PBUF_TYPE_FLAG_DATA_VOLATILE)

PBUF_NEEDS_COPY(p): return a boolean value indicating whether the given pbuf needs to be copied in order to be kept around beyond the current call stack without risking being corrupted. The default setting provides safety: it will make a copy iof any pbuf chain that does not consist entirely of PBUF_ROM type pbufs. For setups with zero-copy support, it may be redefined to evaluate to true in all cases, for example. However, doing so also has an effect on the application side: any buffers that are not copied must also not be reused by the application after passing them to lwIP. For example, when setting PBUF_NEEDS_COPY to (0), after using udp_send() with a PBUF_RAM pbuf, the application must free the pbuf immediately, rather than reusing it for other purposes. For more background information on this, see tasks #6735 and #7896, and bugs #11400 and #49914.

## Enumeration Type Documentation

## pbuf_layer

enum pbuf_layer

Enumeration of pbuf layers

Enumerator
PBUF_TRANSPORT | Includes spare room for transport layer header, e.g. UDP header. Use this if you intend to pass the pbuf to functions like udp_send().
PBUF_IP | Includes spare room for IP header. Use this if you intend to pass the pbuf to functions like raw_send().

PBUF_LINK

Includes spare room for link layer header (ethernet header). Use this if you intend to pass the pbuf to functions like ethernet_output().

See also
  PBUF_LINK_HLEN

PBUF_RAW_TX

Includes spare room for additional encapsulation header before ethernet headers (e.g. 802.11). Use this if you intend to pass the pbuf to functions like netif->linkoutput().

See also
  PBUF_LINK_ENCAPSULATION_HLEN

PBUF_RAW | Use this for input packets in a netif driver when calling netif->input() in the most common case - ethernet-layer netif driver.

## pbuf_type

enum pbuf_type

Enumeration of pbuf types

Enumerator
PBUF_RAM | pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payload are allocated in one piece of contiguous memory (so the first payload byte can be calculated from struct pbuf). pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that might change in future versions). This should be used for all OUTGOING packets (TX).
PBUF_ROM | pbuf data is stored in ROM, i.e. struct pbuf and its payload are located in totally different memory areas. Since it points to ROM, payload does not have to be copied when queued for transmission.
PBUF_REF | pbuf comes from the pbuf pool. Much like PBUF_ROM but payload might change so it has to be duplicated when queued before transmitting, depending on who has a 'ref' to it.

PBUF_POOL

pbuf payload refers to RAM. This one comes from a pool and should be used for RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, struct pbuf and its payload are allocated in one piece of contiguous memory (so the first payload byte can be calculated from struct pbuf). Don't use this for TX, if the pool becomes empty e.g. because of TCP queuing, you are unable to receive TCP acks!

## Function Documentation

## pbuf_alloc()

struct pbuf* pbuf_alloc | ( | pbuf_layer | layer,
|  | u16_t | length,
|  | pbuf_type | type
| ) |  |

Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).

The actual memory allocated for the pbuf is determined by the layer at which the pbuf is allocated and the requested size (from the size parameter).

Parameters

  layer | header size
  length | size of the pbuf's payload
  type | this parameter decides how and where the pbuf should be allocated as follows:

- PBUF_RAM: buffer memory for pbuf is allocated as one large chunk. This includes protocol headers as well.
- PBUF_ROM: no buffer memory is allocated for the pbuf, even for protocol headers. Additional headers must be prepended by allocating another pbuf and chain in to the front of the ROM pbuf. It is assumed that the memory used is really similar to ROM in that it is immutable and will not be changed. Memory which is dynamic should generally not be attached to PBUF_ROM pbufs. Use PBUF_REF instead.
- PBUF_REF: no buffer memory is allocated for the pbuf, even for protocol headers. It is assumed that the pbuf is only being used in a single thread. If the pbuf gets queued, then pbuf_take should be called to copy the buffer.
- PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from the pbuf pool that is allocated during pbuf_init().

Returns
  the allocated pbuf. If multiple pbufs where allocated, this is the first pbuf of a pbuf chain.

## pbuf_alloc_reference()

struct pbuf* pbuf_alloc_reference | ( | void * | payload,
|  | u16_t | length,
|  | pbuf_type | type
| ) |  |

Allocates a pbuf for referenced data. Referenced data can be volatile (PBUF_REF) or long-lived (PBUF_ROM).

The actual memory allocated for the pbuf is determined by the layer at which the pbuf is allocated and the requested size (from the size parameter).

Parameters

  payload | referenced payload
  length | size of the pbuf's payload
  type | this parameter decides how and where the pbuf should be allocated as follows:

- PBUF_ROM: It is assumed that the memory used is really similar to ROM in that it is immutable and will not be changed. Memory which is dynamic should generally not be attached to PBUF_ROM pbufs. Use PBUF_REF instead.
- PBUF_REF: It is assumed that the pbuf is only being used in a single thread. If the pbuf gets queued, then pbuf_take should be called to copy the buffer.

Returns
  the allocated pbuf.

## pbuf_alloced_custom()

struct pbuf* pbuf_alloced_custom | ( | pbuf_layer | l,
|  | u16_t | length,
|  | pbuf_type | type,
|  | struct pbuf_custom * | p,
|  | void * | payload_mem,
|  | u16_t | payload_mem_len
| ) |  |

Initialize a custom pbuf (already allocated). Example of custom pbuf usage: Zero-copy RX

Parameters

  l | header size
  length | size of the pbuf's payload
  type | type of the pbuf (only used to treat the pbuf accordingly, as this function allocates no memory)
  p | pointer to the custom pbuf to initialize (already allocated)
  payload_mem | pointer to the buffer that is used for payload and headers, must be at least big enough to hold 'length' plus the header size, may be NULL if set later. ATTENTION: The caller is responsible for correct alignment of this buffer!!
  payload_mem_len | the size of the 'payload_mem' buffer, must be at least big enough to hold 'length' plus the header size

## pbuf_cat()

void pbuf_cat | ( | struct pbuf * | h,
|  | struct pbuf * | t
| ) |  |

Concatenate two pbufs (each may be a pbuf chain) and take over the caller's reference of the tail pbuf.

Note
  The caller MAY NOT reference the tail pbuf afterwards. Use pbuf_chain() for that purpose.

This function explicitly does not check for tot_len overflow to prevent failing to queue too long pbufs. This can produce invalid pbufs, so handle with care!

See also
  pbuf_chain()

## pbuf_chain()

void pbuf_chain | ( | struct pbuf * | h,
|  | struct pbuf * | t
| ) |  |

Chain two pbufs (or pbuf chains) together.

The caller MUST call pbuf_free(t) once it has stopped using it. Use pbuf_cat() instead if you no longer use t.

Parameters

  h | head pbuf (chain)
  t | tail pbuf (chain)

Note
  The pbufs MUST belong to the same packet.
  MAY NOT be called on a packet queue.

The ->tot_len fields of all pbufs of the head chain are adjusted. The ->next field of the last pbuf of the head chain is adjusted. The ->ref field of the first pbuf of the tail chain is adjusted.

## pbuf_clone()

struct pbuf* pbuf_clone | ( | pbuf_layer | layer,
|  | pbuf_type | type,
|  | struct pbuf * | p
| ) |  |

Allocates a new pbuf of same length (via pbuf_alloc()) and copies the source pbuf into this new pbuf (using pbuf_copy()).

Parameters

  layer | pbuf_layer of the new pbuf
  type | this parameter decides how and where the pbuf should be allocated (

See also
  pbuf_alloc())

Parameters

  p | the source pbuf

Returns
  a new pbuf or NULL if allocation fails

## pbuf_coalesce()

struct pbuf* pbuf_coalesce | ( | struct pbuf * | p,
|  | pbuf_layer | layer
| ) |  |

Creates a single pbuf out of a queue of pbufs.

Remarks
  : Either the source pbuf 'p' is freed by this function or the original pbuf 'p' is returned, therefore the caller has to check the result!

Parameters

  p | the source pbuf
  layer | pbuf_layer of the new pbuf

Returns
  a new, single pbuf (p->next is NULL) or the old pbuf if allocation fails

## pbuf_copy()

err_t pbuf_copy | ( | struct pbuf * | p_to,
|  | const struct pbuf * | p_from
| ) |  |

Copy the contents of one packet buffer into another.

Note
  Only one packet is copied, no packet queue!

Parameters

  p_to | pbuf destination of the copy
  p_from | pbuf source of the copy

Returns
  ERR_OK if pbuf was copied ERR_ARG if one of the pbufs is NULL or p_to is not big enough to hold p_from ERR_VAL if any of the pbufs are part of a queue

## pbuf_copy_partial()

u16_t pbuf_copy_partial | ( | const struct pbuf * | buf,
|  | void * | dataptr,
|  | u16_t | len,
|  | u16_t | offset
| ) |  |

Copy (part of) the contents of a packet buffer to an application supplied buffer.

Parameters

  buf | the pbuf from which to copy data
  dataptr | the application supplied buffer
  len | length of data to copy (dataptr must be big enough). No more than buf->tot_len will be copied, irrespective of len
  offset | offset into the packet buffer from where to begin copying len bytes

Returns
  the number of bytes copied, or 0 on failure

## pbuf_copy_partial_pbuf()

err_t pbuf_copy_partial_pbuf | ( | struct pbuf * | p_to,
|  | const struct pbuf * | p_from,
|  | u16_t | copy_len,
|  | u16_t | offset
| ) |  |

Copy part or all of one packet buffer into another, to a specified offset.

Note
  Only data in one packet is copied, no packet queue!
  Argument order is shared with pbuf_copy, but different than pbuf_copy_partial.

Parameters

  p_to | pbuf destination of the copy
  p_from | pbuf source of the copy
  copy_len | number of bytes to copy
  offset | offset in destination pbuf where to copy to

Returns
  ERR_OK if copy_len bytes were copied ERR_ARG if one of the pbufs is NULL or p_from is shorter than copy_len or p_to is not big enough to hold copy_len at offset ERR_VAL if any of the pbufs are part of a queue

## pbuf_free()

u8_t pbuf_free | ( | struct pbuf * | p | ) |

Dereference a pbuf chain or queue and deallocate any no-longer-used pbufs at the head of this chain or queue.

Decrements the pbuf reference count. If it reaches zero, the pbuf is deallocated.

For a pbuf chain, this is repeated for each pbuf in the chain, up to the first pbuf which has a non-zero reference count after decrementing. So, when all reference counts are one, the whole chain is free'd.

Parameters

  p | The pbuf (chain) to be dereferenced.

Returns
  the number of pbufs that were de-allocated from the head of the chain.

Note
  the reference counter of a pbuf equals the number of pointers that refer to the pbuf (or into the pbuf).

## pbuf_get_at()

u8_t pbuf_get_at | ( | const struct pbuf * | p,
|  | u16_t | offset
| ) |  |

Get one byte from the specified position in a pbuf WARNING: returns zero for offset >= p->tot_len

Parameters

  p | pbuf to parse
  offset | offset into p of the byte to return

Returns
  byte at an offset into p OR ZERO IF 'offset' >= p->tot_len

## pbuf_get_contiguous()

void* pbuf_get_contiguous | ( | const struct pbuf * | p,
|  | void * | buffer,
|  | size_t | bufsize,
|  | u16_t | len,
|  | u16_t | offset
| ) |  |

Get part of a pbuf's payload as contiguous memory. The returned memory is either a pointer into the pbuf's payload or, if split over multiple pbufs, a copy into the user-supplied buffer.

Parameters

  p | the pbuf from which to copy data
  buffer | the application supplied buffer. May be NULL if the caller does not want to copy. In this case, offset + len should be checked against p->tot_len, since there's no way for the caller to know why NULL is returned.
  bufsize | size of the application supplied buffer (when buffer is != NULL)
  len | length of data to copy (p and buffer must be big enough)
  offset | offset into the packet buffer from where to begin copying len bytes

Returns
  - pointer into pbuf payload if that is already contiguous (no copy needed)
  - pointer to 'buffer' if data was not contiguous and had to be copied
  - NULL on error

## pbuf_memcmp()

u16_t pbuf_memcmp | ( | const struct pbuf * | p,
|  | u16_t | offset,
|  | const void * | s2,
|  | u16_t | n
| ) |  |

Compare pbuf contents at specified offset with memory s2, both of length n

Parameters

  p | pbuf to compare
  offset | offset into p at which to start comparing
  s2 | buffer to compare
  n | length of buffer to compare

Returns
  zero if equal, nonzero otherwise (0xffff if p is too short, diffoffset+1 otherwise)

## pbuf_memfind()

u16_t pbuf_memfind | ( | const struct pbuf * | p,
|  | const void * | mem,
|  | u16_t | mem_len,
|  | u16_t | start_offset
| ) |  |

Find occurrence of mem (with length mem_len) in pbuf p, starting at offset start_offset.

Parameters

  p | pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as return value 'not found'
  mem | search for the contents of this buffer
  mem_len | length of 'mem'
  start_offset | offset into p at which to start searching

Returns
  0xFFFF if substr was not found in p or the index where it was found

## pbuf_put_at()

void pbuf_put_at | ( | struct pbuf * | p,
|  | u16_t | offset,
|  | u8_t | data
| ) |  |

Put one byte to the specified position in a pbuf WARNING: silently ignores offset >= p->tot_len

Parameters

  p | pbuf to fill
  offset | offset into p of the byte to write
  data | byte to write at an offset into p

## pbuf_realloc()

void pbuf_realloc | ( | struct pbuf * | p,
|  | u16_t | new_len
| ) |  |

Shrink a pbuf chain to a desired length.

Parameters

  p | pbuf to shrink.
  new_len | desired new length of pbuf chain

Depending on the desired length, the first few pbufs in a chain might be skipped and left unchanged. The new last pbuf in the chain will be resized, and any remaining pbufs will be freed.

Note
  If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.
  May not be called on a packet queue.
  Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain).

## pbuf_ref()

void pbuf_ref | ( | struct pbuf * | p | ) |

Increment the reference count of the pbuf.

Parameters

  p | pbuf to increase reference counter of

## pbuf_skip()

struct pbuf* pbuf_skip | ( | struct pbuf * | in,
|  | u16_t | in_offset,
|  | u16_t * | out_offset
| ) |  |

Skip a number of bytes at the start of a pbuf

Parameters

  in | input pbuf
  in_offset | offset to skip
  out_offset | resulting offset in the returned pbuf

Returns
  the pbuf in the queue where the offset is or NULL when the offset is too high

## pbuf_take()

err_t pbuf_take | ( | struct pbuf * | buf,
|  | const void * | dataptr,
|  | u16_t | len
| ) |  |

Copy application supplied data into a pbuf. This function can only be used to copy the equivalent of buf->tot_len data.

Parameters

  buf | pbuf to fill with data
  dataptr | application supplied data buffer
  len | length of the application supplied data buffer

Returns
  ERR_OK if successful, ERR_MEM if the pbuf is not big enough

## pbuf_take_at()

err_t pbuf_take_at | ( | struct pbuf * | buf,
|  | const void * | dataptr,
|  | u16_t | len,
|  | u16_t | offset
| ) |  |

Same as pbuf_take() but puts data at an offset

Parameters

  buf | pbuf to fill with data
  dataptr | application supplied data buffer
  len | length of the application supplied data buffer
  offset | offset in pbuf where to copy dataptr to

Returns
  ERR_OK if successful, ERR_MEM if the pbuf is not big enough

## pbuf_try_get_at()

int pbuf_try_get_at | ( | const struct pbuf * | p,
|  | u16_t | offset
| ) |  |

Get one byte from the specified position in a pbuf

Parameters

  p | pbuf to parse
  offset | offset into p of the byte to return

Returns
  byte at an offset into p [0..0xFF] OR negative if 'offset' >= p->tot_len