2. TC核心对象与命令体系

Linux TC(Traffic Control)并不是一个单一命令,而是一套围绕“对象”组织起来的流量控制框架。理解 TC 的关键,是先分清四个核心对象:qdisc(排队规则)、class(类)、filter(过滤器)和action(动作)。它们之间存在明确的挂载与引用关系,而不是彼此独立的配置项。只有先建立对象模型,才能正确写出 tc 命令,并在排障时知道该查哪一层。

一、四个核心对象的概念模型

qdisc 是 TC 的基本调度单元,挂载在网络设备的某个方向上。每个网卡默认存在一个根 qdisc(root qdisc),例如 pfifo_fast 或 noqueue。qdisc 分为两类:无类 qdisc(如 pfifo、fq_codel、tbf)和可分类 qdisc(如 htb、hfsc、prio)。无类 qdisc 只做整体排队与调度;可分类 qdisc 内部可以再挂载 class,形成层级结构。

class 只存在于可分类 qdisc 内部,用于把流量划分成不同类别,并分别施加带宽、速率、优先级等参数。class 可以继续嵌套 class,形成树状层级。例如 HTB 中,根 class 下可以再分多个子 class,每个子 class 拥有独立的 rate 和 ceil。

filter 负责“把报文分到哪个 class”。它挂载在 qdisc 或 class 上,通过匹配条件(如 IP、端口、TOS、fwmark)决定报文进入哪个 class。filter 是分类决策点,没有 filter,可分类 qdisc 就无法把流量导向不同 class。

action 是 filter 匹配后可以执行的附加操作,例如 drop、mirred、police、gact 等。action 让 TC 不仅能“分类”,还能“处置”,例如限速丢弃、镜像到另一网卡、修改标记等。

TC 对象模型:qdisc / class / filter / action 的挂载关系 网络设备 eth0 / ens33 root qdisc handle 1: htb 可分类 qdisc class 1:1 rate 100mbit class 1:10 rate 30mbit class 1:20 rate 50mbit filter match ip dport 80 flowid 1:10 action police / drop mirred / gact 挂载关系:qdisc 挂在设备上 → class 挂在可分类 qdisc 内 → filter 挂在 qdisc/class 上 → action 挂在 filter 上。 handle 用于标识 qdisc/class,flowid 用于指定 filter 的目标 class,二者是 tc 命令中最关键的定位参数。

二、tc 命令语法与对象管理方法

tc 命令的基本语法为:tc [ OPTIONS ] OBJECT { COMMAND | help }。其中 OBJECT 可以是 qdisc、class、filter、action 等;COMMAND 通常是 add、del、change、replace、show 等。所有对象都通过 dev 指定网络设备,通过 parent 指定父对象,通过 handle 指定自身标识。

下面以 HTB 为例,给出一组可直接参考的示例命令。假设在 eth0 出方向建立根 qdisc,handle 为 1:,并创建两个子 class:

# 1. 挂载根 qdisc(可分类 HTB)
tc qdisc add dev eth0 root handle 1: htb default 20

# 2. 创建根 class 1:1,限定总带宽
tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit

# 3. 创建子 class 1:10 和 1:20
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 30mbit ceil 60mbit
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 50mbit ceil 100mbit

# 4. 为子 class 挂载叶子 qdisc(可选,用于精细排队)
tc qdisc add dev eth0 parent 1:10 handle 10: fq_codel
tc qdisc add dev eth0 parent 1:20 handle 20: fq_codel

# 5. 添加 filter,把 80 端口流量分到 1:10
tc filter add dev eth0 protocol ip parent 1:0 prio 1 \
  u32 match ip dport 80 0xffff flowid 1:10

# 6. 查看对象
tc qdisc show dev eth0
tc class show dev eth0
tc filter show dev eth0

这组命令体现了 TC 对象管理的核心逻辑:先建 qdisc,再建 class,然后挂 filter,最后按需加 action。每一步都依赖上一步的 handle 或 classid。如果顺序颠倒,例如先加 filter 再建 class,filter 会因找不到目标 class 而失败。

三、对象标识与定位规则

TC 中每个对象都有唯一标识。qdisc 和 class 使用 handle 或 classid,格式为 主号:次号,例如 1:、1:1、1:10。filter 使用 prio 表示优先级,数值越小越先匹配。action 则通过 filter 的 action 子句挂载。

parent 的写法需要特别注意:根 qdisc 的 parent 是 root;class 的 parent 是所属 qdisc 或父 class 的 handle;filter 的 parent 通常是 qdisc 的 handle 加 :0,例如 parent 1:0。如果 parent 写错,命令会报 “Cannot find device” 或 “Parent Qdisc doesn't exist” 之类的错误。

排障提示:当 tc 命令报错时,优先检查三件事:dev 是否正确、parent 是否存在、handle 是否冲突。使用 tc qdisc show dev eth0 和 tc class show dev eth0 可以快速确认当前对象树。

四、对象生命周期与常用管理命令

TC 对象支持增、删、改、查四类操作。新增用 add,删除用 del,修改用 change,替换用 replace,查看用 show。删除 qdisc 时,其下挂的 class、filter 会一并删除;删除 class 时,其子 class 和挂载的 qdisc 也会被清理。因此删除操作通常从叶子向根进行,或者直接删除根 qdisc 以清空整棵树。

操作 命令示例 说明
新增 qdisc tc qdisc add dev eth0 root handle 1: htb 在 eth0 出方向挂载根 HTB
新增 class tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit 在 1: 下创建 1:1
新增 filter tc filter add dev eth0 parent 1:0 u32 match ip dport 80 0xffff flowid 1:10 把 80 端口流量指向 1:10
修改 class tc class change dev eth0 classid 1:10 htb rate 40mbit 调整 1:10 的速率
删除 qdisc tc qdisc del dev eth0 root 清空整棵对象树
查看统计 tc -s qdisc show dev eth0 显示队列统计与丢包计数