Packet Management

Overview

Network packets are the main data the networking stack manipulates. Such data is represented through the net_pkt structure which provides a means to hold the packet, write and read it, as well as necessary metadata for the core to hold important information. Such an object is called net_pkt in this document.

The data structure and the whole API around it are defined in include/zephyr/net/net_pkt.h.

Architectural notes

There are two network packets flows within the stack, TX for the transmission path, and RX for the reception one. In both paths, each net_pkt is written and read from the beginning to the end, or more specifically from the headers to the payload.

Memory management

Allocation

All net_pkt objects come from a pre-defined pool of struct net_pkt. Such pool is defined via

NET_PKT_SLAB_DEFINE(name, count)

Note, however, one will rarely have to use it, as the core provides already two pools, one for the TX path and one for the RX path.

Allocating a raw net_pkt can be done through:

pkt = net_pkt_alloc(timeout);

However, by its nature, a raw net_pkt is useless without a buffer and needs various metadata information to become relevant as well. It requires at least to get the network interface it is meant to be sent through or through which it was received. As this is a very common operation, a helper exist:

pkt = net_pkt_alloc_on_iface(iface, timeout);

A more complete allocator exists, where both the net_pkt and its buffer can be allocated at once:

pkt = net_pkt_alloc_with_buffer(iface, size, family, proto, timeout);

See below how the buffer is allocated.

Buffer allocation

The net_pkt object does not define its own buffer, but instead uses an existing object for this: net_buf. (See Network Buffer for more information). However, it mostly hides the usage of such a buffer because net_pkt brings network awareness to buffer allocation and, as we will see later, its operation too.

To allocate a buffer, a net_pkt needs to have at least its network interface set. This works if the family of the packet is unknown at the time of buffer allocation. Then one could do:

net_pkt_alloc_buffer(pkt, size, proto, timeout);

Where proto could be 0 if unknown (there is no IPPROTO_UNSPEC).

As seen previously, the net_pkt and its buffer can be allocated at once via net_pkt_alloc_with_buffer(). It is actually the most widely used allocator.

The network interface, the family, and the protocol of the packet are used by the buffer allocation to determine if the requested size can be allocated. Indeed, the allocator will use the network interface to know the MTU and then the family and protocol for the headers space (if only these 2 are specified). If the whole fits within the MTU, the allocated space will be of the requested size plus, eventually, the headers space. If there is insufficient MTU space, the requested size will be shrunk so the possible headers space and new size will fit within the MTU.

For instance, on an Ethernet network interface, with an MTU of 1500 bytes:

pkt = net_pkt_alloc_with_buffer(iface, 800, AF_INET4, IPPROTO_UDP, K_FOREVER);

will successfully allocate 800 + 20 + 8 bytes of buffer for the new net_pkt where:

pkt = net_pkt_alloc_with_buffer(iface, 1600, AF_INET4, IPPROTO_UDP, K_FOREVER);

will successfully allocate 1500 bytes, and where 20 + 8 bytes (IPv4 + UDP headers) will not be used for the payload.

On the receiving side, when the family and protocol are not known:

pkt = net_pkt_rx_alloc_with_buffer(iface, 800, AF_UNSPEC, 0, K_FOREVER);

will allocate 800 bytes and no extra header space. But a:

pkt = net_pkt_rx_alloc_with_buffer(iface, 1600, AF_UNSPEC, 0, K_FOREVER);

will allocate 1514 bytes, the MTU + Ethernet header space.

One can increase the amount of buffer space allocated by calling net_pkt_alloc_buffer(), as it will take into account the existing buffer. It will also account for the header space if net_pkt’s family is a valid one, as well as the proto parameter. In that case, the newly allocated buffer space will be appended to the existing one, and not inserted in the front. Note however such a use case is rather limited. Usually, one should know from the start how much size should be requested.

Deallocation

Each net_pkt is reference counted. At allocation, the reference is set to 1. The reference count can be incremented with net_pkt_ref() or decremented with net_pkt_unref(). When the count drops to zero the buffer is also un-referenced and net_pkt is automatically placed back into the free net_pkt_slabs

If net_pkt’s buffer is needed even after net_pkt deallocation, one will need to reference once more all the chain of net_buf before calling last net_pkt_unref. See Network Buffer for more information.

Operations

There are two ways to access the net_pkt buffer, explained in the following sections: basic read/write access and data access, the latter being the preferred way.

Read and Write access

As said earlier, though net_pkt uses net_buf for its buffer, it provides its own API to access it. Indeed, a network packet might be scattered over a chain of net_buf objects, the functions provided by net_buf are then limited for such case. Instead, net_pkt provides functions which hide all the complexity of potential non-contiguous access.

Data movement into the buffer is made through a cursor maintained within each net_pkt. All read/write operations affect this cursor. Note as well that read or write functions are strict on their length parameters: if it cannot r/w the given length it will fail. Length is not interpreted as an upper limit, it is instead the exact amount of data that must be read or written.

As there are two paths, TX and RX, there are two access modes: write and overwrite. This might sound a bit unusual, but is in fact simple and provides flexibility.

In write mode, whatever is written in the buffer affects the length of actual data present in the buffer. Buffer length should not be confused with the buffer size which is a limit any mode cannot pass. In overwrite mode then, whatever is written must happen on valid data, and will not affect the buffer length. By default, a newly allocated net_pkt is on write mode, and its cursor points to the beginning of its buffer.

Let’s see now, step by step, the functions and how they behave depending on the mode.

When freshly allocated with a buffer of 500 bytes, a net_pkt has 0 length, which means no valid data is in its buffer. One could verify this by:

len = net_pkt_get_len(pkt);

Now, let’s write 8 bytes:

net_pkt_write(pkt, data, 8);

The buffer length is now 8 bytes. There are various helpers to write a byte, or big endian uint16_t, uint32_t.

net_pkt_write_u8(pkt, &foo);
net_pkt_write_be16(pkt, &ba);
net_pkt_write_be32(pkt, &bar);

Logically, net_pkt’s length is now 15. But if we try to read at this point, it will fail because there is nothing to read at the cursor where we are at in the net_pkt. It is possible, while in write mode, to read what has been already written by resetting the cursor of the net_pkt. For instance:

net_pkt_cursor_init(pkt);
net_pkt_read(pkt, data, 15);

This will reset the cursor of the pkt to the beginning of the buffer and then let you read the actual 15 bytes present. The cursor is then again pointing at the end of the buffer.

To set a large area with the same byte, a memset function is provided:

net_pkt_memset(pkt, 0, 5);

Our net_pkt has now a length of 20 bytes.

Switching between modes can be achieved via net_pkt_set_overwrite() function. It is possible to switch mode back and forth at any time. The net_pkt will be set to overwrite and its cursor reset:

net_pkt_set_overwrite(pkt, true);
net_pkt_cursor_init(pkt);

Now the same operators can be used, but it will be limited to the existing data in the buffer, i.e. 20 bytes.

If it is necessary to know how much space is available in the net_pkt call:

net_pkt_available_buffer(pkt);

Or, if headers space needs to be accounted for, call:

net_pkt_available_payload_buffer(pkt, proto);

If you want to place the cursor at a known position use the function net_pkt_skip(). For example, to go after the IP header, use:

net_pkt_cursor_init(pkt);
net_pkt_skip(pkt, net_pkt_ip_header_len(pkt));

Data access

Though the API shown previously is rather simple, it involves always copying things to and from the net_pkt buffer. In many occasions, it is more relevant to access the information stored in the buffer contiguously, especially with network packets which embed headers.

These headers are, most of the time, a known fixed set of bytes. It is then more natural to have a structure representing a certain type of header. In addition to this, if it is known the header size appears in a contiguous area of the buffer, it will be way more efficient to cast the actual position in the buffer to the type of header. Either for reading or writing the fields of such header, accessing it directly will save memory.

Net pkt comes with a dedicated API for this, built on top of the previously described API. It is able to handle both contiguous and non-contiguous access transparently.

There are two macros used to define a data access descriptor: NET_PKT_DATA_ACCESS_DEFINE when it is not possible to tell if the data will be in a contiguous area, and NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE when it is guaranteed the data is in a contiguous area.

Let’s take the example of IP and UDP. Both IPv4 and IPv6 headers are always found at the beginning of the packet and are small enough to fit in a net_buf of 128 bytes (for instance, though 64 bytes could be chosen).

NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv4_access, struct net_ipv4_hdr);
struct net_ipv4_hdr *ipv4_hdr;

ipv4_hdr = (struct net_ipv4_hdr *)net_pkt_get_data(pkt, &ipv4_access);

It would be the same for struct net_ipv4_hdr. For a UDP header it is likely not to be in a contiguous area in IPv6 for instance so:

NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr);
struct net_udp_hdr *udp_hdr;

udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt, &udp_access);

At this point, the cursor of the net_pkt points at the beginning of the requested data. On the RX path, these headers will be read but not modified so to proceed further the cursor needs to advance past the data. There is a function dedicated for this:

net_pkt_acknowledge_data(pkt, &ipv4_access);

On the TX path, however, the header fields have been modified. In such a case:

net_pkt_set_data(pkt, &ipv4_access);

If the data are in a contiguous area, it will advance the cursor relevantly. If not, it will write the data and the cursor will be updated. Note that net_pkt_set_data() could be used in the RX path as well, but it is slightly faster to use net_pkt_acknowledge_data() as this one does not care about contiguity at all, it just advances the cursor via net_pkt_skip() directly.

API Reference

group net_pkt

Network packet management library.

Defines

NET_PKT_SLAB_DEFINE(name, count)

Create a net_pkt slab.

A net_pkt slab is used to store meta-information about network packets. It must be coupled with a data fragment pool (NET_PKT_DATA_POOL_DEFINE) used to store the actual packet data. The macro can be used by an application to define additional custom per-context TX packet slabs (see net_context_setup_pools()).

Parameters:
  • name – Name of the slab.

  • count – Number of net_pkt in this slab.

NET_PKT_DATA_POOL_DEFINE(name, count)

Create a data fragment net_buf pool.

A net_buf pool is used to store actual data for network packets. It must be coupled with a net_pkt slab (NET_PKT_SLAB_DEFINE) used to store the packet meta-information. The macro can be used by an application to define additional custom per-context TX packet pools (see net_context_setup_pools()).

Parameters:
  • name – Name of the pool.

  • count – Number of net_buf in this pool.

net_pkt_print_frags(pkt)

Print fragment list and the fragment sizes.

Only available if debugging is activated.

Parameters:
  • pkt – Network pkt.

Functions

struct net_buf *net_pkt_get_reserve_data(struct net_buf_pool *pool, size_t min_len, k_timeout_t timeout)

Get a data buffer from a given pool.

Normally this version is not useful for applications but is mainly used by network fragmentation code.

Parameters:
  • pool – The net_buf pool to use.

  • min_len – Minimum length of the requested fragment.

  • timeout – Affects the action taken should the net buf pool be empty. If K_NO_WAIT, then return immediately. If K_FOREVER, then wait as long as necessary. Otherwise, wait up to the specified time.

Returns:

Network buffer if successful, NULL otherwise.

struct net_buf *net_pkt_get_reserve_rx_data(size_t min_len, k_timeout_t timeout)

Get RX DATA buffer from pool.

Normally you should use net_pkt_get_frag() instead.

Normally this version is not useful for applications but is mainly used by network fragmentation code.

Parameters:
  • min_len – Minimum length of the requested fragment.

  • timeout – Affects the action taken should the net buf pool be empty. If K_NO_WAIT, then return immediately. If K_FOREVER, then wait as long as necessary. Otherwise, wait up to the specified time.

Returns:

Network buffer if successful, NULL otherwise.

struct net_buf *net_pkt_get_reserve_tx_data(size_t min_len, k_timeout_t timeout)

Get TX DATA buffer from pool.

Normally you should use net_pkt_get_frag() instead.

Normally this version is not useful for applications but is mainly used by network fragmentation code.

Parameters:
  • min_len – Minimum length of the requested fragment.

  • timeout – Affects the action taken should the net buf pool be empty. If K_NO_WAIT, then return immediately. If K_FOREVER, then wait as long as necessary. Otherwise, wait up to the specified time.

Returns:

Network buffer if successful, NULL otherwise.

struct net_buf *net_pkt_get_frag(struct net_pkt *pkt, size_t min_len, k_timeout_t timeout)

Get a data fragment that might be from user specific buffer pool or from global DATA pool.

Parameters:
  • pkt – Network packet.

  • min_len – Minimum length of the requested fragment.

  • timeout – Affects the action taken should the net buf pool be empty. If K_NO_WAIT, then return immediately. If K_FOREVER, then wait as long as necessary. Otherwise, wait up to the specified time.

Returns:

Network buffer if successful, NULL otherwise.

void net_pkt_unref(struct net_pkt *pkt)

Place packet back into the available packets slab.

Releases the packet to other use. This needs to be called by application after it has finished with the packet.

Parameters:
  • pkt – Network packet to release.

struct net_pkt *net_pkt_ref(struct net_pkt *pkt)

Increase the packet ref count.

Mark the packet to be used still.

Parameters:
  • pkt – Network packet to ref.

Returns:

Network packet if successful, NULL otherwise.

struct net_buf *net_pkt_frag_ref(struct net_buf *frag)

Increase the packet fragment ref count.

Mark the fragment to be used still.

Parameters:
  • frag – Network fragment to ref.

Returns:

a pointer on the referenced Network fragment.

void net_pkt_frag_unref(struct net_buf *frag)

Decrease the packet fragment ref count.

Parameters:
  • frag – Network fragment to unref.

struct net_buf *net_pkt_frag_del(struct net_pkt *pkt, struct net_buf *parent, struct net_buf *frag)

Delete existing fragment from a packet.

Parameters:
  • pkt – Network packet from which frag belongs to.

  • parent – parent fragment of frag, or NULL if none.

  • frag – Fragment to delete.

Returns:

Pointer to the following fragment, or NULL if it had no further fragments.

void net_pkt_frag_add(struct net_pkt *pkt, struct net_buf *frag)

Add a fragment to a packet at the end of its fragment list.

Parameters:
  • pkt – pkt Network packet where to add the fragment

  • frag – Fragment to add

void net_pkt_frag_insert(struct net_pkt *pkt, struct net_buf *frag)

Insert a fragment to a packet at the beginning of its fragment list.

Parameters:
  • pkt – pkt Network packet where to insert the fragment

  • frag – Fragment to insert

void net_pkt_compact(struct net_pkt *pkt)

Compact the fragment list of a packet.

After this there is no more any free space in individual fragments.

Parameters:
  • pkt – Network packet.

void net_pkt_get_info(struct k_mem_slab **rx, struct k_mem_slab **tx, struct net_buf_pool **rx_data, struct net_buf_pool **tx_data)

Get information about predefined RX, TX and DATA pools.

Parameters:
  • rx – Pointer to RX pool is returned.

  • tx – Pointer to TX pool is returned.

  • rx_data – Pointer to RX DATA pool is returned.

  • tx_data – Pointer to TX DATA pool is returned.

struct net_pkt *net_pkt_alloc(k_timeout_t timeout)

Allocate an initialized net_pkt.

for the time being, 2 pools are used. One for TX and one for RX. This allocator has to be used for TX.

Parameters:
  • timeout – Maximum time to wait for an allocation.

Returns:

a pointer to a newly allocated net_pkt on success, NULL otherwise.

struct net_pkt *net_pkt_alloc_from_slab(struct k_mem_slab *slab, k_timeout_t timeout)

Allocate an initialized net_pkt from a specific slab.

unlike net_pkt_alloc() which uses core slabs, this one will use an external slab (see NET_PKT_SLAB_DEFINE()). Do not use it unless you know what you are doing. Basically, only net_context should be using this, in order to allocate packet and then buffer on its local slab/pool (if any).

Parameters:
  • slab – The slab to use for allocating the packet

  • timeout – Maximum time to wait for an allocation.

Returns:

a pointer to a newly allocated net_pkt on success, NULL otherwise.

struct net_pkt *net_pkt_rx_alloc(k_timeout_t timeout)

Allocate an initialized net_pkt for RX.

for the time being, 2 pools are used. One for TX and one for RX. This allocator has to be used for RX.

Parameters:
  • timeout – Maximum time to wait for an allocation.

Returns:

a pointer to a newly allocated net_pkt on success, NULL otherwise.

struct net_pkt *net_pkt_alloc_on_iface(struct net_if *iface, k_timeout_t timeout)

Allocate a network packet for a specific network interface.

Parameters:
  • iface – The network interface the packet is supposed to go through.

  • timeout – Maximum time to wait for an allocation.

Returns:

a pointer to a newly allocated net_pkt on success, NULL otherwise.

int net_pkt_alloc_buffer(struct net_pkt *pkt, size_t size, enum net_ip_protocol proto, k_timeout_t timeout)

Allocate buffer for a net_pkt.

: such allocator will take into account space necessary for headers, MTU, and existing buffer (if any). Beware that, due to all these criteria, the allocated size might be smaller/bigger than requested one.

Parameters:
  • pkt – The network packet requiring buffer to be allocated.

  • size – The size of buffer being requested.

  • proto – The IP protocol type (can be 0 for none).

  • timeout – Maximum time to wait for an allocation.

Returns:

0 on success, negative errno code otherwise.

int net_pkt_alloc_buffer_raw(struct net_pkt *pkt, size_t size, k_timeout_t timeout)

Allocate buffer for a net_pkt, of specified size, w/o any additional preconditions.

: The actual buffer size may be larger than requested one if fixed size buffers are in use.

Parameters:
  • pkt – The network packet requiring buffer to be allocated.

  • size – The size of buffer being requested.

  • timeout – Maximum time to wait for an allocation.

Returns:

0 on success, negative errno code otherwise.

struct net_pkt *net_pkt_alloc_with_buffer(struct net_if *iface, size_t size, sa_family_t family, enum net_ip_protocol proto, k_timeout_t timeout)

Allocate a network packet and buffer at once.

Parameters:
  • iface – The network interface the packet is supposed to go through.

  • size – The size of buffer.

  • family – The family to which the packet belongs.

  • proto – The IP protocol type (can be 0 for none).

  • timeout – Maximum time to wait for an allocation.

Returns:

a pointer to a newly allocated net_pkt on success, NULL otherwise.

void net_pkt_append_buffer(struct net_pkt *pkt, struct net_buf *buffer)

Append a buffer in packet.

Parameters:
  • pkt – Network packet where to append the buffer

  • buffer – Buffer to append

size_t net_pkt_available_buffer(struct net_pkt *pkt)

Get available buffer space from a pkt.

Note

Reserved bytes (headroom) in any of the fragments are not considered to be available.

Parameters:
  • pkt – The net_pkt which buffer availability should be evaluated

Returns:

the amount of buffer available

size_t net_pkt_available_payload_buffer(struct net_pkt *pkt, enum net_ip_protocol proto)

Get available buffer space for payload from a pkt.

Unlike net_pkt_available_buffer(), this will take into account the headers space.

Note

Reserved bytes (headroom) in any of the fragments are not considered to be available.

Parameters:
  • pkt – The net_pkt which payload buffer availability should be evaluated

  • proto – The IP protocol type (can be 0 for none).

Returns:

the amount of buffer available for payload

void net_pkt_trim_buffer(struct net_pkt *pkt)

Trim net_pkt buffer.

This will basically check for unused buffers and deallocate them relevantly

Parameters:
  • pkt – The net_pkt which buffer will be trimmed

int net_pkt_remove_tail(struct net_pkt *pkt, size_t length)

Remove length bytes from tail of packet.

This function does not take packet cursor into account. It is a helper to remove unneeded bytes from tail of packet (like appended CRC). It takes care of buffer deallocation if removed bytes span whole buffer(s).

Parameters:
  • pkt – Network packet

  • length – Number of bytes to be removed

Return values:
  • 0 – On success.

  • -EINVAL – If packet length is shorter than length.

void net_pkt_cursor_init(struct net_pkt *pkt)

Initialize net_pkt cursor.

This will initialize the net_pkt cursor from its buffer.

Parameters:
  • pkt – The net_pkt whose cursor is going to be initialized

static inline void net_pkt_cursor_backup(struct net_pkt *pkt, struct net_pkt_cursor *backup)

Backup net_pkt cursor.

Parameters:
  • pkt – The net_pkt whose cursor is going to be backed up

  • backup – The cursor where to backup net_pkt cursor

static inline void net_pkt_cursor_restore(struct net_pkt *pkt, struct net_pkt_cursor *backup)

Restore net_pkt cursor from a backup.

Parameters:
  • pkt – The net_pkt whose cursor is going to be restored

  • backup – The cursor from where to restore net_pkt cursor

static inline void *net_pkt_cursor_get_pos(struct net_pkt *pkt)

Returns current position of the cursor.

Parameters:
  • pkt – The net_pkt whose cursor position is going to be returned

Returns:

cursor’s position

int net_pkt_skip(struct net_pkt *pkt, size_t length)

Skip some data from a net_pkt.

net_pkt’s cursor should be properly initialized Cursor position will be updated after the operation. Depending on the value of pkt->overwrite bit, this function will affect the buffer length or not. If it’s true, it will advance the cursor to the requested length. If it’s false, it will do the same but if the cursor was already also at the end of existing data, it will increment the buffer length. So in this case, its behavior is just like net_pkt_write or net_pkt_memset, difference being that it will not affect the buffer content itself (which may be just garbage then).

Parameters:
  • pkt – The net_pkt whose cursor will be updated to skip given amount of data from the buffer.

  • length – Amount of data to skip in the buffer

Returns:

0 in success, negative errno code otherwise.

int net_pkt_memset(struct net_pkt *pkt, int byte, size_t length)

Memset some data in a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The net_pkt whose buffer to fill starting at the current cursor position.

  • byte – The byte to write in memory

  • length – Amount of data to memset with given byte

Returns:

0 in success, negative errno code otherwise.

int net_pkt_copy(struct net_pkt *pkt_dst, struct net_pkt *pkt_src, size_t length)

Copy data from a packet into another one.

Both net_pkt cursors should be properly initialized and, if needed, positioned using net_pkt_skip. The cursors will be updated after the operation.

Parameters:
  • pkt_dst – Destination network packet.

  • pkt_src – Source network packet.

  • length – Length of data to be copied.

Returns:

0 on success, negative errno code otherwise.

struct net_pkt *net_pkt_clone(struct net_pkt *pkt, k_timeout_t timeout)

Clone pkt and its buffer.

The cloned packet will be allocated on the same pool as the original one.

Parameters:
  • pkt – Original pkt to be cloned

  • timeout – Timeout to wait for free buffer

Returns:

NULL if error, cloned packet otherwise.

struct net_pkt *net_pkt_rx_clone(struct net_pkt *pkt, k_timeout_t timeout)

Clone pkt and its buffer.

The cloned packet will be allocated on the RX packet poll.

Parameters:
  • pkt – Original pkt to be cloned

  • timeout – Timeout to wait for free buffer

Returns:

NULL if error, cloned packet otherwise.

struct net_pkt *net_pkt_shallow_clone(struct net_pkt *pkt, k_timeout_t timeout)

Clone pkt and increase the refcount of its buffer.

Parameters:
  • pkt – Original pkt to be shallow cloned

  • timeout – Timeout to wait for free packet

Returns:

NULL if error, cloned packet otherwise.

int net_pkt_read(struct net_pkt *pkt, void *data, size_t length)

Read some data from a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet from where to read some data

  • data – The destination buffer where to copy the data

  • length – The amount of data to copy

Returns:

0 on success, negative errno code otherwise.

static inline int net_pkt_read_u8(struct net_pkt *pkt, uint8_t *data)

Read a byte (uint8_t) from a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet from where to read

  • data – The destination uint8_t where to copy the data

Returns:

0 on success, negative errno code otherwise.

int net_pkt_read_be16(struct net_pkt *pkt, uint16_t *data)

Read uint16_t big endian data from a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet from where to read

  • data – The destination uint16_t where to copy the data

Returns:

0 on success, negative errno code otherwise.

int net_pkt_read_le16(struct net_pkt *pkt, uint16_t *data)

Read uint16_t little endian data from a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet from where to read

  • data – The destination uint16_t where to copy the data

Returns:

0 on success, negative errno code otherwise.

int net_pkt_read_be32(struct net_pkt *pkt, uint32_t *data)

Read uint32_t big endian data from a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet from where to read

  • data – The destination uint32_t where to copy the data

Returns:

0 on success, negative errno code otherwise.

int net_pkt_write(struct net_pkt *pkt, const void *data, size_t length)

Write data into a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet where to write

  • data – Data to be written

  • length – Length of the data to be written

Returns:

0 on success, negative errno code otherwise.

static inline int net_pkt_write_u8(struct net_pkt *pkt, uint8_t data)

Write a byte (uint8_t) data to a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet from where to read

  • data – The uint8_t value to write

Returns:

0 on success, negative errno code otherwise.

static inline int net_pkt_write_be16(struct net_pkt *pkt, uint16_t data)

Write a uint16_t big endian data to a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet from where to read

  • data – The uint16_t value in host byte order to write

Returns:

0 on success, negative errno code otherwise.

static inline int net_pkt_write_be32(struct net_pkt *pkt, uint32_t data)

Write a uint32_t big endian data to a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet from where to read

  • data – The uint32_t value in host byte order to write

Returns:

0 on success, negative errno code otherwise.

static inline int net_pkt_write_le32(struct net_pkt *pkt, uint32_t data)

Write a uint32_t little endian data to a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet from where to read

  • data – The uint32_t value in host byte order to write

Returns:

0 on success, negative errno code otherwise.

static inline int net_pkt_write_le16(struct net_pkt *pkt, uint16_t data)

Write a uint16_t little endian data to a net_pkt.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet from where to read

  • data – The uint16_t value in host byte order to write

Returns:

0 on success, negative errno code otherwise.

size_t net_pkt_remaining_data(struct net_pkt *pkt)

Get the amount of data which can be read from current cursor position.

Parameters:
  • pkt – Network packet

Returns:

Amount of data which can be read from current pkt cursor

int net_pkt_update_length(struct net_pkt *pkt, size_t length)

Update the overall length of a packet.

Unlike net_pkt_pull() below, this does not take packet cursor into account. It’s mainly a helper dedicated for ipv4 and ipv6 input functions. It shrinks the overall length by given parameter.

Parameters:
  • pkt – Network packet

  • length – The new length of the packet

Returns:

0 on success, negative errno code otherwise.

int net_pkt_pull(struct net_pkt *pkt, size_t length)

Remove data from the packet at current location.

net_pkt’s cursor should be properly initialized and, eventually, properly positioned using net_pkt_skip/read/write. Note that net_pkt’s cursor is reset by this function.

Parameters:
  • pkt – Network packet

  • length – Number of bytes to be removed

Returns:

0 on success, negative errno code otherwise.

uint16_t net_pkt_get_current_offset(struct net_pkt *pkt)

Get the actual offset in the packet from its cursor.

Parameters:
  • pkt – Network packet.

Returns:

a valid offset on success, 0 otherwise as there is nothing that can be done to evaluate the offset.

bool net_pkt_is_contiguous(struct net_pkt *pkt, size_t size)

Check if a data size could fit contiguously.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip.

Parameters:
  • pkt – Network packet.

  • size – The size to check for contiguity

Returns:

true if that is the case, false otherwise.

size_t net_pkt_get_contiguous_len(struct net_pkt *pkt)

Get the contiguous buffer space.

Parameters:
  • pkt – Network packet

Returns:

The available contiguous buffer space in bytes starting from the current cursor position. 0 in case of an error.

void *net_pkt_get_data(struct net_pkt *pkt, struct net_pkt_data_access *access)

Get data from a network packet in a contiguous way.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Unlike other functions, cursor position will not be updated after the operation.

Parameters:
  • pkt – The network packet from where to get the data.

  • access – A pointer to a valid net_pkt_data_access describing the data to get in a contiguous way.

Returns:

a pointer to the requested contiguous data, NULL otherwise.

int net_pkt_set_data(struct net_pkt *pkt, struct net_pkt_data_access *access)

Set contiguous data into a network packet.

net_pkt’s cursor should be properly initialized and, if needed, positioned using net_pkt_skip. Cursor position will be updated after the operation.

Parameters:
  • pkt – The network packet to where the data should be set.

  • access – A pointer to a valid net_pkt_data_access describing the data to set.

Returns:

0 on success, a negative errno otherwise.

static inline int net_pkt_acknowledge_data(struct net_pkt *pkt, struct net_pkt_data_access *access)

Acknowledge previously contiguous data taken from a network packet Packet needs to be set to overwrite mode.

struct net_pkt
#include <net_pkt.h>

Network packet.

Note that if you add new fields into net_pkt, remember to update net_pkt_clone() function.

Public Members

intptr_t fifo

The fifo is used by RX/TX threads and by socket layer.

The net_pkt is queued via fifo to the processing thread.

struct k_mem_slab *slab

Slab pointer from where it belongs to.

struct net_buf *frags

buffer fragment

struct net_buf *buffer

alias to a buffer fragment

union net_pkt.[anonymous] [anonymous]

buffer holding the packet

struct net_pkt_cursor cursor

Internal buffer iterator used for reading/writing.

struct net_context *context

Network connection context.

struct net_if *iface

Network interface.