Logo

Linux 内核

6.13.0-rc6

快速搜索

目录

  • 开发流程
  • 提交补丁
  • 行为准则
  • 维护者手册
  • 所有开发流程文档
  • 核心 API
  • 驱动程序 API
  • 子系统
  • 锁
  • 许可规则
  • 编写文档
  • 开发工具
  • 测试指南
  • 黑客指南
  • 跟踪
  • 故障注入
  • 实时补丁
  • Rust
  • 管理
  • 构建系统
  • 报告问题
  • 用户空间工具
  • 用户空间 API
    • 系统调用
    • 安全相关接口
    • 设备和 I/O
    • 其他所有内容
      • Linux 特有的 ELF 特性
      • Netlink 手册
      • 平台配置文件选择 (例如 /sys/firmware/acpi/platform_profile)
      • VDUSE - “用户空间的 vDPA 设备”
      • futex2
      • Perf 环形缓冲区
  • 固件
  • 固件和设备树
  • CPU 架构
  • 未分类的文档
  • 翻译

本页

  • 显示源码

使用 Netlink 协议规范¶

本文档是使用 Netlink 协议规范的快速入门指南。有关规范的更详细描述,请参阅 Netlink 协议规范(YAML 格式)。

简单 CLI¶

内核附带一个简单的 CLI 工具,在开发与 Netlink 相关的代码时应该很有用。该工具用 Python 实现,可以使用 YAML 规范向内核发出 Netlink 请求。仅支持通用 Netlink。

该工具位于 tools/net/ynl/cli.py。它接受一些参数,最重要的参数是

  • --spec - 指向规范文件

  • --do $name / --dump $name - 发出请求 $name

  • --json $attrs - 为请求提供属性

  • --subscribe $group - 接收来自 $group 的通知

YAML 规范可以在 Documentation/netlink/specs/ 下找到。

使用示例

$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/ethtool.yaml \
      --do rings-get \
      --json '{"header":{"dev-index": 18}}'
{'header': {'dev-index': 18, 'dev-name': 'eni1np1'},
 'rx': 0,
 'rx-jumbo': 0,
 'rx-jumbo-max': 4096,
 'rx-max': 4096,
 'rx-mini': 0,
 'rx-mini-max': 4096,
 'tx': 0,
 'tx-max': 4096,
 'tx-push': 0}

输入参数被解析为 JSON,而输出仅以 Python 漂亮的格式打印。这是因为某些 Netlink 类型无法直接表示为 JSON。如果输入中需要此类属性,则需要对脚本进行一些修改。

规范和 Netlink 内部结构被分解为一个独立的库 - 重用 cli.py 中的代码应该很容易编写 Python 工具/测试。

生成内核代码¶

tools/net/ynl/ynl-regen.sh 扫描内核树,查找需要更新的自动生成文件。使用此工具是生成/更新自动生成代码的最简单方法。

默认情况下,仅当规范比源文件新时才重新生成代码,要强制重新生成,请使用 -f。

ynl-regen.sh 在文件内容中搜索 YNL-GEN (请注意,它仅扫描 git 索引中的文件,即仅由 git 跟踪的文件!)。例如,fou_nl.c 内核源代码包含

/*    Documentation/netlink/specs/fou.yaml */
/* YNL-GEN kernel source */

ynl-regen.sh 将找到此标记,并使用基于 fou.yaml 的内核源代码替换该文件。

基于规范生成新文件的最简单方法是将上面的两个标记行添加到文件中,将该文件添加到 git,然后运行重新生成工具。在树中 grep YNL-GEN 以查看其他示例。

代码生成本身由 tools/net/ynl/ynl-gen-c.py 执行,但它需要一些参数,因此直接为每个文件调用它很快就会变得繁琐。

YNL 库¶

tools/net/ynl/lib/ 包含一个 C 库(基于 libmnl)的实现,该库与 tools/net/ynl/ynl-gen-c.py 生成的代码集成,以创建易于使用的 netlink 包装器。

YNL 基础知识¶

YNL 库由两部分组成 - 通用代码(函数前缀为 ynl_)和每个系列的自动生成代码(前缀为系列的名称)。

要创建 YNL 套接字,请调用 ynl_sock_create(),并传递系列结构(系列结构由自动生成的代码导出)。ynl_sock_destroy() 关闭套接字。

YNL 请求¶

发出 YNL 请求的步骤最好用一个例子来解释。此示例中的所有函数和类型都来自自动生成的代码(在本例中为 netdev 系列)

// 0. Request and response pointers
struct netdev_dev_get_req *req;
struct netdev_dev_get_rsp *d;

// 1. Allocate a request
req = netdev_dev_get_req_alloc();
// 2. Set request parameters (as needed)
netdev_dev_get_req_set_ifindex(req, ifindex);

// 3. Issues the request
d = netdev_dev_get(ys, req);
// 4. Free the request arguments
netdev_dev_get_req_free(req);
// 5. Error check (the return value from step 3)
if (!d) {
     // 6. Print the YNL-generated error
     fprintf(stderr, "YNL: %s\n", ys->err.msg);
     return -1;
}

// ... do stuff with the response @d

// 7. Free response
netdev_dev_get_rsp_free(d);

YNL 转储¶

执行转储遵循与请求类似的模式。转储返回一个对象列表,以特殊标记终止,或者在错误时返回 NULL。使用 ynl_dump_foreach() 迭代结果。

YNL 通知¶

YNL 库支持将同一套接字用于通知和请求。如果在处理请求期间收到通知,则会在内部排队,并且可以在稍后检索。

要订阅通知,请使用 ynl_subscribe()。通知必须从套接字中读取,ynl_socket_get_fd() 返回底层套接字 fd,该 fd 可以插入到适当的异步 IO API 中,例如 poll 或 select。

可以使用 ynl_ntf_dequeue() 检索通知,并且必须使用 ynl_ntf_free() 释放通知。由于我们事先不知道通知类型,因此通知以 struct ynl_ntf_base_type * 的形式返回,并且用户应根据 cmd 成员将其转换为适当的完整类型。

©内核开发社区。 | 由 Sphinx 5.3.0 & Alabaster 0.7.16 提供支持 | 页面来源