【问题标题】:Call traffic control (tc) from within Linux kernel从 Linux 内核调用流量控制 (tc)
【发布时间】:2021-03-14 10:29:38
【问题描述】:

有一个名为tc(8) 的用户空间工具用于流量整形,即

tc qdisc add dev eth0 root tbf rate 10mbit latency 100ms burst 5000.

tc 命令的内部实现使用 netlink 将特定消息发送到内核,这反过来会相应地改变事情。 但是,对于这个特定过程,内核代码没有公共接口——例如,没有像 tc_qdisc_add(x,y,z) 这样的公共 API——因为一切都取决于来自 netlink 消息本身的数据。

那么,有没有什么技巧可以简化流程并模拟来自内核的消息?有没有办法绕过对tc 的用户空间调用并仅从内核上下文中获得相同的结果?

【问题讨论】:

  • 考虑将systemd用于此类目的或编写您自己的/sbin/init
  • 您想从内核模块调整tc 学科?
  • 是的,我想从内核中模拟(特定)tc 调用的行为。

标签: c linux networking linux-kernel trafficshaping


【解决方案1】:

有没有什么技巧可以简化流程并模拟来自内核的消息?

我看不出有什么方法可以让它变得简单。

如果不深入具体tc-commands的实现细节,只考虑内核内部现有的API,我们可以看到所有与netlink talk和qdiscs添加代码相关的代码都位于/net/sched 子目录。注册 qdisc 的主要函数位于 /net/sched/sch_api.c 中,名为register_qdisc()。我们还可以在pktsched_init() 中看到注册基本的 qdiscs 和 netlink 操作。

Qdisc 操作通过struct Qdisc_ops 描述,包括初始化、入队、更改等。

知道了这一点,我们可以看看这是如何在tbf 模块(net/sched/sch_tbf.c)中实现的。它有几个用tbf_qdisc_ops 描述的操作。这里有一个改变被调用的操作,通常被调用,如tc_modify_qdisc() -> qdisc_change() -> tbf_change()

因此,根据您要调整的具体内容,您可以通过某种方式获取特定的 qdisc,构建适当的网络链接消息(结构 nlmsghdr,因为它在用户模式下完成)并调用例如->change(...) qdisc 方法。

答案并不声称是正确的。我只是想稍微澄清一下情况。

【讨论】:

  • 感谢您的回答。我已经深入研究了 net/sched/ 代码并找到了您提到的函数,但最终归结为抓取接收到的 netlink 消息并将其填充到无穷无尽的结构中。问题是从 3.x 到 4.x 和 5.x 有相当大的变化,这将导致在对 netlink 消息进行硬编码和使用内部(私有)函数时代码损坏。似乎包含所有 qdisc 更改信息的有效负载没有记录在内核源代码的任何地方。
  • “在对 netlink 消息进行硬编码和使用内部(私有)函数时,这将导致代码损坏” - 绝对是的。这就是为什么如果存在特殊的组织实用程序,从内核执行此操作是一个坏主意。无法想象您为什么要尝试从内核空间实现这样的目标。这看起来像是一个可疑的架构决策。
  • 因为它是从内核中的模块执行的,我不想在不需要时调用用户空间。更清楚地说:底层模块仅在内核中可用(低级)。
  • 我知道这是模块,这是在内核中。但是你为什么不想产生一些用户模式进程或守护进程来做用户模式的事情呢?并通过 netlink/ioctl/procfs/... 将其连接到您的模块。面向事件的用户模式处理:您的模块生成事件 - 用户模式进程处理它。
  • “当我不需要它时” - 但似乎你需要:)
猜你喜欢
  • 2017-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多