tc 流量控制

qdisc

qdisc (队列规则 queueing discipline) 是 Linux 中用于管理网络流量的机制;它允许用户定义如何处理和调度网络数据包, 我们可以将其看作一个具有一定规则的队列; 当tc处理网络包时, 会将包入队到qdisc中, 这些包会根据指定的规则被内核按照一定顺序取出

例如执行 ip l 的时候, 可以看到一些类似的信息:

1
2
3
4
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp1s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether d4:6d:50:cf:9d:de brd ff:ff:ff:ff:ff:ff

也就是说这里有 qdisc noqueueqdisc mq 两种类型的队列规则

tbf

tbf (令牌桶过滤器 token bucket filter) 是一种流量控制机制

tbf_concept.png

到来的数据包需要获取的令牌与数据包的大小有关, 并且任意大小的数据包都需要消耗令牌, 如果某个数据包没有足够的令牌, 将会放入队列中, 等待令牌补充, 后续到来的数据包同样进入队列中等待, 直到队列被填满, 后续包将被丢弃

如果我们限制桶的容量, 或者限制令牌的补充速度, 就可以限制整体的包处理速度

流量控制

1
tc qdisc add dev ethX root tbf rate ${RATE} burst ${BURST} latency ${LATENCY}
  • dev ethX 指定网络设备, 例如 enp1s0f1
  • rate ${RATE} 指定速率, 例如 1mbit
  • burst ${BURST} 指定 Bucket Size, 例如 32k, 一般取 rate * 10ms
  • latency ${LATENCY} 允许突发的最大排队延迟

handle 编号/句柄

handle 实际上是给对应的 qdisc/ class/ filter 添加一个唯一标识符, 方便后续引用, 修改或者删除

可以通过 handle MAJOR:MINOR 来建立继承关系

不同 handle 序号之间只有命名差异, 没有重要性差异

继承关系

handle 的继承关系决定了子 qdisc(netem)挂在哪个父 qdisc(tbf)上, 也就是整条流量控制链路的"拓扑"

我们在每一条初等指令中加入的 root 关键字就表明这是最高层的根节点的指令规则

handle 可以建立规则之间的继承关系, 例如:

1
2
tc qdisc add dev eth0 root handle 1: tbf rate 1mbit burst 32k latency 10ms
tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 100ms limit 1000

第一个指令中, tbf 的根 handle 是 1:, 执行之后相当于在系统内部设备树中建立了一个根节点, 这个节点的 handle 是 1:

1
2
DEV (root)
└─ qdisc tbf handle 1:0 (即 1:)

第二个指令中会在 TBF 下再挂一个 Netem, parent 1:1 的 1:1 指的就是 Major=1, Minor=1这个挂载点

虽然 TBF 本身不产生 class, 但 Linux TC 允许你把子 qdisc 直接挂到它的"默认子节点"1:1 上——也就是给这条链路人为划了一个 slot, 让你能往里再插 netem, 从而获得如下的层级结构:

1
2
3
4
DEV (root)
└─ qdisc tbf handle 1:0
└─ slot 1:1 (虚拟子节点)
└─ qdisc netem handle 10:0

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%