6. 网络控制指令
tc 流量控制
qdisc
qdisc (队列规则 queueing discipline) 是 Linux 中用于管理网络流量的机制;它允许用户定义如何处理和调度网络数据包, 我们可以将其看作一个具有一定规则的队列; 当tc处理网络包时, 会将包入队到qdisc中, 这些包会根据指定的规则被内核按照一定顺序取出
例如执行 ip l 的时候, 可以看到一些类似的信息:
1 | 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 |
也就是说这里有 qdisc noqueue 和 qdisc mq 两种类型的队列规则
tbf
tbf (令牌桶过滤器 token bucket filter) 是一种流量控制机制

到来的数据包需要获取的令牌与数据包的大小有关, 并且任意大小的数据包都需要消耗令牌, 如果某个数据包没有足够的令牌, 将会放入队列中, 等待令牌补充, 后续到来的数据包同样进入队列中等待, 直到队列被填满, 后续包将被丢弃
如果我们限制桶的容量, 或者限制令牌的补充速度, 就可以限制整体的包处理速度
流量控制
1 | tc qdisc add dev ethX root tbf rate ${RATE} burst ${BURST} latency ${LATENCY} |
dev ethX指定网络设备, 例如 enp1s0f1rate ${RATE}指定速率, 例如 1mbitburst ${BURST}指定 Bucket Size, 例如 32k, 一般取rate * 10mslatency ${LATENCY}允许突发的最大排队延迟
handle 编号/句柄
handle 实际上是给对应的 qdisc/ class/ filter 添加一个唯一标识符, 方便后续引用, 修改或者删除
可以通过 handle MAJOR:MINOR 来建立继承关系
不同 handle 序号之间只有命名差异, 没有重要性差异
继承关系
handle 的继承关系决定了子 qdisc(netem)挂在哪个父 qdisc(tbf)上, 也就是整条流量控制链路的"拓扑"
我们在每一条初等指令中加入的 root 关键字就表明这是最高层的根节点的指令规则
handle 可以建立规则之间的继承关系, 例如:
1 | tc qdisc add dev eth0 root handle 1: tbf rate 1mbit burst 32k latency 10ms |
第一个指令中, tbf 的根 handle 是 1:, 执行之后相当于在系统内部设备树中建立了一个根节点, 这个节点的 handle 是 1:
1 | DEV (root) |
第二个指令中会在 TBF 下再挂一个 Netem, parent 1:1 的 1:1 指的就是 Major=1, Minor=1这个挂载点
虽然 TBF 本身不产生 class, 但 Linux TC 允许你把子 qdisc 直接挂到它的"默认子节点"1:1 上——也就是给这条链路人为划了一个 slot, 让你能往里再插 netem, 从而获得如下的层级结构:
1 | DEV (root) |
netem 关键字
这是一个 网络模拟指令, 可以模拟网络延迟, 丢包, 重复包等情况
1 | sudo tc qdisc add dev eth0 root netem delay 100ms # 延迟 100 毫秒 |
模拟延时波动
1 | sudo tc qdisc add dev eth0 root netem delay 100ms 10ms # 延迟 100 毫秒, 波动 10 毫秒 |
模拟丢包
1 | sudo tc qdisc add dev eth0 root netem loss 10% # 丢包率 10% |
