> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/man/man9/mbuf_tags.9.md).

# mbuf\_tags.9

`mbuf_tags` — 通用数据包属性框架

## 名称

`mbuf_tags`

## 概要

`#include <sys/mbuf.h>`

`Ft struct m_tag * Fn m_tag_alloc uint32_t cookie uint16_t type int len int wait Ft struct m_tag * Fn m_tag_copy struct m_tag *t int how Ft int Fn m_tag_copy_chain struct mbuf *to const struct mbuf *from int how Ft void Fn m_tag_delete struct mbuf *m struct m_tag *t Ft void Fn m_tag_delete_chain struct mbuf *m struct m_tag *t Ft void Fn m_tag_delete_nonpersistent struct mbuf *m Ft struct m_tag * Fn m_tag_find struct mbuf *m uint16_t type struct m_tag *start Ft struct m_tag * Fn m_tag_first struct mbuf *m Ft void Fn m_tag_free struct m_tag *t Ft struct m_tag * Fn m_tag_get uint16_t type int len int wait Ft void Fn m_tag_init struct mbuf *m Ft struct m_tag * Fn m_tag_locate struct mbuf *m uint32_t cookie uint16_t type struct m_tag *t Ft struct m_tag * Fn m_tag_next struct mbuf *m struct m_tag *t Ft void Fn m_tag_prepend struct mbuf *m struct m_tag *t Ft void Fn m_tag_unlink struct mbuf *m struct m_tag *t`

## 描述

Mbuf 标签允许通过提供一种将额外内核内存标记到数据包头 mbuf 上的机制，将额外的元数据与传输中的数据包相关联。标签在 [mbuf(9)](/man/man9/mbuf.9.md) 头部的链中维护，并使用一系列 API 调用来分配、搜索和删除标签。标签使用唯一标识一类标记到数据包上的数据的 ID 和 cookie 来标识，并且可以包含任意数量的额外存储。mbuf 标签的典型用途包括 [mac(9)](/man/man9/mac.9.md) 中描述的强制访问控制（MAC）标签、[ipsec(4)](/man/man4/ipsec.4.md) 中描述的 IPsec 策略信息以及 [pf(4)](/man/man4/pf.4.md) 使用的数据包过滤器标签。

标签会在各种操作中维护，包括使用 `M_COPY_PKTHDR` 和 `M_MOVE_PKTHDR` 等工具复制数据包头。与 mbuf 头部相关联的任何标签将在 mbuf 释放时自动释放，尽管某些子系统希望在此之前删除标签。

不同的内核 API 使用数据包标签来跟踪对数据包已完成或计划执行的操作。每个数据包标签可以通过其类型和 cookie 来区分。cookie 用于标识特定的模块或 API。数据包标签附加到 mbuf 数据包头。

标签的前 `sizeof(struct m_tag)` 字节包含一个 `struct m_tag`：

```c
struct m_tag {
	SLIST_ENTRY(m_tag)	m_tag_link;	/* 数据包标签列表 */
	uint16_t		m_tag_id;	/* 标签 ID */
	uint16_t		m_tag_len;	/* 数据长度 */
	uint32_t		m_tag_cookie;	/* ABI/模块 ID */
	void			(*m_tag_free)(struct m_tag *);
};
```

`m_tag_link` 字段用于将标签链接在一起（详见 [queue(3)](/man/misc/queue.3.md)）。`m_tag_id`、`m_tag_len` 和 `m_tag_cookie` 字段分别设置为类型、长度和 cookie。`m_tag_free` 指向 `m_tag_free_default`。在此结构之后是 `m_tag_len` 字节的空间，可用于存储标签特定信息。寻址此数据区域可能有些棘手。一种安全的方法是将 `struct m_tag` 嵌入到私有数据结构中，如下所示：

```c
struct foo {
	struct m_tag	tag;
	...
};
struct foo *p = (struct foo *)m_tag_alloc(...);
struct m_tag *mtag = &p->tag;
```

注意，OpenBSD 不支持 cookie，它需要 `m_tag_id` 全局唯一。为了与 OpenBSD 保持兼容，提供了 cookie `MTAG_ABI_COMPAT` 以及一些兼容性函数。编写 OpenBSD 兼容代码时，应注意不要使用已使用的标签类型。标签类型定义于

`#include <sys/mbuf.h>`

### 数据包标签操作函数

**`m_tag_alloc(cookie, type, len, wait)`** 分配一个类型为 `type`、cookie 为 `cookie` 的新标签，标签头之后有 `len` 字节的空间。`wait` 参数直接传递给 [malloc(9)](/man/man9/malloc.9.md)。如果成功，`m_tag_alloc` 返回一个 (`len` + `sizeof(struct m_tag)`) 字节的内存缓冲区。否则，返回 `NULL`。还提供了一个兼容函数 `m_tag_get`。

**`m_tag_copy(tag, how)`** 分配 `tag` 的副本。`how` 参数直接传递给 `m_tag_alloc`。返回值与 `m_tag_alloc` 中的相同。

**`m_tag_copy_chain(tombuf, frommbuf, how)`** 分配并将 mbuf `frommbuf` 的所有标签复制到 mbuf `tombuf`。成功时返回 1，失败时返回 0。在后一种情况下，mbuf `tombuf` 将丢失其所有标签，甚至包括之前存在的标签。

**`m_tag_delete(mbuf, tag)`** 从 `mbuf` 的列表中删除 `tag` 并释放它。

**`m_tag_delete_chain(mbuf, tag)`** 从 `tag` 开始删除并释放数据包标签链。如果 `tag` 为 `NULL`，则删除所有标签。

**`m_tag_delete_nonpersistent(mbuf)`** 遍历 `mbuf` 的标签并删除那些未设置 `MTAG_PERSISTENT` 标志的标签。

**`m_tag_first(mbuf)`** 返回与 `mbuf` 相关联的第一个标签。

**`m_tag_free(tag)`** 使用其 `m_tag_free` 方法释放 `tag`。默认使用 `m_tag_free_default` 函数。

**`m_tag_init(mbuf)`** 为数据包 `mbuf` 初始化标签存储。

**`m_tag_locate(mbuf, cookie, type, tag)`** 在 `mbuf` 中搜索由 `type` 和 `cookie` 定义的标签，从 `tag` 指定的位置开始。如果后者为 `NULL`，则搜索整个列表。成功时，返回指向第一个找到的标签的指针。在任何情况下，都返回 `NULL`。还提供了一个兼容函数 `m_tag_find`。

**`m_tag_next(mbuf, tag)`** 返回 `mbuf` 中 `tag` 之后的标签。如果不存在，则返回 `NULL`。

**`m_tag_prepend(mbuf, tag)`** 将新标签 `tag` 添加到数据包 `mbuf` 的标签列表的头部。

**`m_tag_unlink(mbuf, tag)`** 从数据包 `mbuf` 的标签列表中删除标签 `tag`。

## 代码参考

标签操作代码包含在文件 `sys/kern/uipc_mbuf2.c` 中。内联函数定义于

`#include <sys/mbuf.h>`

## 参见

[queue(3)](/man/misc/queue.3.md), [mbuf(9)](/man/man9/mbuf.9.md)

## 历史

数据包标签首次出现于 OpenBSD 2.9，由 Angelos D. Keromytis <angelos@openbsd.org> 编写。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/man/man9/mbuf_tags.9.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
