Part 1
요약·해설
Pool allocation, user data, FIFO chain 규칙, Add·Remove·Push·Pull과 reference counting을 설명합니다.
Pool · Headroom · Tailroom
Add · Remove · Push · Pull
Reference count
Part 2
접을 수 있는 영어 원문 전체
영어 원문 전체 펼치기
87988F6F4BDE91103EBA882DC520BC02C2958292D356BB4D04BF71DFB4ADC65F
.. _net_buf_interface:
Network Buffer
##############
.. contents::
:local:
:depth: 2
Overview
********
Network buffers are a core concept of how the networking stack
(as well as the Bluetooth stack) pass data around. The API for them is
defined in :zephyr_file:`include/zephyr/net/buf.h`:.
Creating buffers
****************
Network buffers are created by first defining a pool of them:
.. code-block:: c
NET_BUF_POOL_DEFINE(pool_name, buf_count, buf_size, user_data_size, NULL);
The pool is a static variable, so if it's needed to be exported to
another module a separate pointer is needed.
Once the pool has been defined, buffers can be allocated from it with:
.. code-block:: c
buf = net_buf_alloc(&pool_name, timeout);
There is no explicit initialization function for the pool or its
buffers, rather this is done implicitly as :c:func:`net_buf_alloc` gets
called.
If there is a need to reserve space in the buffer for protocol headers
to be prepended later, it's possible to reserve this headroom with:
.. code-block:: c
net_buf_reserve(buf, headroom);
In addition to actual protocol data and generic parsing context, network
buffers may also contain protocol-specific context, known as user data.
Both the maximum data and user data capacity of the buffers is
compile-time defined when declaring the buffer pool.
The buffers have native support for being passed through k_fifo kernel
objects. This is a very practical feature when the buffers need to be
passed from one thread to another. However, since a net_buf may have a
fragment chain attached to it, instead of using the :c:func:`k_fifo_put`
and :c:func:`k_fifo_get` APIs, special :c:func:`net_buf_put` and
:c:func:`net_buf_get` APIs must be used when passing buffers through
FIFOs. These APIs ensure that the buffer chains stay intact. The same
applies for passing buffers through a singly linked list, in which case
the :c:func:`net_buf_slist_put` and :c:func:`net_buf_slist_get`
functions must be used instead of :c:func:`sys_slist_append` and
:c:func:`sys_slist_get`.
Common Operations
*****************
The network buffer API provides some useful helpers for encoding and
decoding data in the buffers. To fully understand these helpers it's
good to understand the basic names of operations used with them:
Add
Add data to the end of the buffer. Modifies the data length value
while leaving the actual data pointer intact. Requires that there is
enough tailroom in the buffer. Some examples of APIs for adding data:
.. code-block:: c
void *net_buf_add(struct net_buf *buf, size_t len);
void *net_buf_add_mem(struct net_buf *buf, const void *mem, size_t len);
uint8_t *net_buf_add_u8(struct net_buf *buf, uint8_t value);
void net_buf_add_le16(struct net_buf *buf, uint16_t value);
void net_buf_add_le32(struct net_buf *buf, uint32_t value);
Remove
Remove data from the end of the buffer. Modifies the data length value
while leaving the actual data pointer intact. Some examples of APIs for
removing data:
.. code-block:: c
void *net_buf_remove_mem(struct net_buf *buf, size_t len);
uint8_t net_buf_remove_u8(struct net_buf *buf);
uint16_t net_buf_remove_le16(struct net_buf *buf);
uint32_t net_buf_remove_le32(struct net_buf *buf);
Push
Prepend data to the beginning of the buffer. Modifies both the data
length value as well as the data pointer. Requires that there is
enough headroom in the buffer. Some examples of APIs for pushing data:
.. code-block:: c
void *net_buf_push(struct net_buf *buf, size_t len);
void *net_buf_push_mem(struct net_buf *buf, const void *mem, size_t len);
void net_buf_push_u8(struct net_buf *buf, uint8_t value);
void net_buf_push_le16(struct net_buf *buf, uint16_t value);
Pull
Remove data from the beginning of the buffer. Modifies both the data
length value as well as the data pointer. Some examples of APIs for
pulling data:
.. code-block:: c
void *net_buf_pull(struct net_buf *buf, size_t len);
void *net_buf_pull_mem(struct net_buf *buf, size_t len);
uint8_t net_buf_pull_u8(struct net_buf *buf);
uint16_t net_buf_pull_le16(struct net_buf *buf);
uint32_t net_buf_pull_le32(struct net_buf *buf);
The Add and Push operations are used when encoding data into the buffer,
whereas the Remove and Pull operations are used when decoding data from a
buffer.
Reference Counting
******************
Each network buffer is reference counted. The buffer is initially
acquired from a free buffers pool by calling :c:func:`net_buf_alloc()`,
resulting in a buffer with reference count 1. The reference count can be
incremented with :c:func:`net_buf_ref()` or decremented with
:c:func:`net_buf_unref()`. When the count drops to zero the buffer is
automatically placed back to the free buffers pool.
API Reference
*************
.. doxygengroup:: net_buf
Part 3
한국어 전문 번역
Network Buffer
Overview
Network buffer는 networking stack과 Bluetooth stack이 data를 전달하는 핵심 개념입니다. API는 include/zephyr/net/buf.h에 정의돼 있습니다.
Creating buffers
Network buffer를 만들려면 먼저 buffer pool을 정의합니다.
NET_BUF_POOL_DEFINE(pool_name, buf_count, buf_size, user_data_size, NULL);Pool은 static variable입니다. 다른 module로 export해야 한다면 별도 pointer가 필요합니다.
Pool을 정의한 뒤 다음과 같이 buffer를 할당합니다.
buf = net_buf_alloc(&pool_name, timeout);net_buf_alloc()이 호출될 때 pool과 buffer가 암묵적으로 initialize되므로 명시적인 initialization function은 없습니다.
나중에 protocol header를 앞에 붙일 공간이 필요하면 다음처럼 headroom을 reserve할 수 있습니다.
net_buf_reserve(buf, headroom);실제 protocol data와 일반 parsing context 외에 protocol-specific context인 user data를 network buffer에 넣을 수 있습니다. 최대 data capacity와 user-data capacity는 buffer pool 선언 시 compile time에 정합니다.
k_fifo kernel object로 buffer를 전달하는 기능을 기본 지원하므로 thread 사이에서 buffer를 넘기기 편합니다. 하지만 net_buf에는 fragment chain이 연결될 수 있으므로 FIFO에서는 k_fifo_put()·k_fifo_get() 대신 net_buf_put()·net_buf_get()을 사용해야 chain이 유지됩니다.
Singly linked list에서도 같은 이유로 sys_slist_append()·sys_slist_get() 대신 net_buf_slist_put()·net_buf_slist_get()을 사용해야 합니다.
Common Operations
Network buffer API는 data encoding과 decoding helper를 제공합니다. 각 operation 이름의 의미는 다음과 같습니다.
Add
Buffer 끝에 data를 추가합니다. Data pointer는 그대로 두고 data length를 바꾸며 충분한 tailroom이 필요합니다.
void *net_buf_add(struct net_buf *buf, size_t len);
void *net_buf_add_mem(struct net_buf *buf, const void *mem, size_t len);
uint8_t *net_buf_add_u8(struct net_buf *buf, uint8_t value);
void net_buf_add_le16(struct net_buf *buf, uint16_t value);
void net_buf_add_le32(struct net_buf *buf, uint32_t value);Remove
Buffer 끝에서 data를 제거합니다. Data pointer는 그대로 두고 data length를 바꿉니다.
void *net_buf_remove_mem(struct net_buf *buf, size_t len);
uint8_t net_buf_remove_u8(struct net_buf *buf);
uint16_t net_buf_remove_le16(struct net_buf *buf);
uint32_t net_buf_remove_le32(struct net_buf *buf);Push
Buffer 시작 부분 앞에 data를 붙입니다. Data length와 data pointer를 모두 바꾸며 충분한 headroom이 필요합니다.
void *net_buf_push(struct net_buf *buf, size_t len);
void *net_buf_push_mem(struct net_buf *buf, const void *mem, size_t len);
void net_buf_push_u8(struct net_buf *buf, uint8_t value);
void net_buf_push_le16(struct net_buf *buf, uint16_t value);Pull
Buffer 시작 부분에서 data를 제거합니다. Data length와 data pointer를 모두 바꿉니다.
void *net_buf_pull(struct net_buf *buf, size_t len);
void *net_buf_pull_mem(struct net_buf *buf, size_t len);
uint8_t net_buf_pull_u8(struct net_buf *buf);
uint16_t net_buf_pull_le16(struct net_buf *buf);
uint32_t net_buf_pull_le32(struct net_buf *buf);Add와 Push는 buffer에 data를 encoding할 때 사용하고 Remove와 Pull은 buffer에서 data를 decoding할 때 사용합니다.
Reference Counting
net_buf_alloc()으로 free-buffer pool에서 얻은 network buffer의 initial reference count는 1입니다. net_buf_ref()로 늘리고 net_buf_unref()로 줄입니다. Count가 0이 되면 buffer가 자동으로 free-buffer pool로 돌아갑니다.
API Reference
Doxygen group net_buf가 API reference를 제공합니다.
Source
출처
영어 원문에는 문단, 문서 지시문, 표, 코드, 코드 심벌, 경로를 그대로 보존했습니다.