3. TC 限速常用命令详解
TC(Traffic Control)是 Linux 内核提供的流量控制工具,通过三种核心对象——qdisc(队列规则)、class(类)和filter(过滤器)——实现精细化的带宽管理。每个对象都支持 add、del、change、show 四种操作。本章逐一拆解这些命令的语法、参数含义和实战用法。
3.1 命令体系总览
三条命令的通用结构如下:
tc [qdisc | class | filter] [ add | del | change | show ] [dev 网卡名] [参数...]
下表对比了三种对象的核心差异:
| 对象 | 作用层级 | 核心参数 | 典型场景 |
|---|---|---|---|
| qdisc | 网卡根节点或类子节点 | root、handle、parent |
设置根队列规则(如 htb、pfifo_fast) |
| class | qdisc 下的子分支 | classid、parent、rate、ceil |
划分带宽层级,分配保障速率和最大速率 |
| filter | 挂载在 qdisc 或 class 上 | parent、protocol、prio、u32 match |
按 IP、端口、协议等条件匹配流量到指定 class |
操作记忆口诀:“qdisc 管队列,class 分带宽,filter 做匹配;add 创建,del 删除,change 修改,show 查看。”
3.2 tc qdisc 命令详解
qdisc 是流量进入网卡后的第一个处理节点。根 qdisc 必须绑定在 root 上,子 qdisc 挂载在 class 下。
3.2.1 添加根 qdisc
# 添加 HTB 根队列,默认 handle 1:0
tc qdisc add dev eth0 root handle 1: htb default 30
# 参数说明:
# dev eth0 —— 目标网卡
# root —— 根节点
# handle 1: —— 队列句柄(1:0 可简写为 1:)
# htb —— 队列算法(Hierarchical Bucket)
# default 30 —— 未匹配 filter 的流量默认进入 class 1:30
3.2.2 删除 qdisc
# 删除 eth0 上的根 qdisc(会级联删除所有子 class 和 filter)
tc qdisc del dev eth0 root
# 删除指定 handle 的 qdisc
tc qdisc del dev eth0 parent 1:1 handle 10: htb
⚠ 删除风险:删除根 qdisc 会清空该网卡上所有 TC 规则,生产环境操作前务必执行
tc qdisc show dev eth0 确认现有规则。
3.2.3 修改 qdisc 参数
# 修改根 qdisc 的 default 值
tc qdisc change dev eth0 root handle 1: htb default 50
# 注意:change 只能修改部分运行时参数,不能改变队列算法类型
3.2.4 查看 qdisc
# 查看所有网卡的 qdisc
tc qdisc show
# 查看指定网卡
tc qdisc show dev eth0
# 查看详细统计(包含丢包、超限等)
tc -s qdisc show dev eth0
3.3 tc class 命令详解
class 必须在已有 qdisc 下创建,用于划分带宽子通道。每个 class 通过 classid 唯一标识,格式为 主编号:子编号。
3.3.1 添加 class
# 在根 qdisc 1: 下创建三个子类
tc class add dev eth0 parent 1: classid 1:10 htb rate 10mbit ceil 20mbit
tc class add dev eth0 parent 1: classid 1:20 htb rate 20mbit ceil 30mbit
tc class add dev eth0 parent 1: classid 1:30 htb rate 5mbit ceil 10mbit
# 参数说明:
# parent 1: —— 父节点为根 qdisc
# classid 1:10 —— 本类 ID
# rate —— 保障带宽
# ceil —— 最大带宽(允许突发借用)
3.3.2 删除 class
# 删除指定 class(必须先删除其下的子 qdisc 和 filter)
tc class del dev eth0 classid 1:20
# 注意:如果 class 下有子 qdisc 或子类,必须先清理下级对象
3.3.3 修改 class
# 修改 class 的带宽参数
tc class change dev eth0 classid 1:10 htb rate 15mbit ceil 25mbit
# 限制:不能修改 parent 和 classid,只能调整 rate/ceil/burst 等参数
3.3.4 查看 class
# 查看所有 class
tc class show dev eth0
# 查看带统计信息的 class
tc -s class show dev eth0
📊 统计字段解读:
Sent —— 已发送字节数/包数rate —— 当前瞬时速率dropped —— 因超限丢弃的包数(回滚验证的关键指标)
3.4 tc filter 命令详解
filter 决定流量进入哪个 class。最常用的是 u32 匹配器,支持按 IP、端口、协议等字段过滤。
3.4.1 添加 filter
# 将源 IP 192.168.1.100 的流量匹配到 class 1:10
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 \
match ip src 192.168.1.100/32 flowid 1:10
# 将目标端口 80 的流量匹配到 class 1:20
tc filter add dev eth0 parent 1: protocol ip prio 2 u32 \
match ip dport 80 0xffff flowid 1:20
# 参数说明:
# parent 1: —— 挂载到根 qdisc
# protocol ip —— 只匹配 IP 包
# prio —— 优先级(数字越小越优先)
# u32 —— 匹配器类型
# match ip src —— 匹配源 IP
# flowid —— 目标 class ID
3.4.2 删除 filter
# 删除指定 parent 和 prio 的 filter
tc filter del dev eth0 parent 1: prio 1
# 删除所有 filter(谨慎使用)
tc filter del dev eth0 parent 1:
3.4.3 修改 filter
# filter 不支持直接 change,需要先删除再添加
# 错误示例(会报错):
# tc filter change dev eth0 parent 1: prio 1 u32 match ip src 10.0.0.1/32 flowid 1:30
# 正确做法:
tc filter del dev eth0 parent 1: prio 1
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 \
match ip src 10.0.0.1/32 flowid 1:30
3.4.4 查看 filter
# 查看所有 filter
tc filter show dev eth0
# 查看指定 parent 的 filter
tc filter show dev eth0 parent 1:
3.5 命令组合实战示例
以下是一个完整的“创建 → 查看 → 修改 → 删除”闭环示例:
# 1. 创建根 qdisc
tc qdisc add dev eth0 root handle 1: htb default 30
# 2. 创建三个 class
tc class add dev eth0 parent 1: classid 1:10 htb rate 10mbit ceil 20mbit
tc class add dev eth0 parent 1: classid 1:20 htb rate 20mbit ceil 30mbit
tc class add dev eth0 parent 1: classid 1:30 htb rate 5mbit ceil 10mbit
# 3. 添加 filter
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 \
match ip src 192.168.1.100/32 flowid 1:10
tc filter add dev eth0 parent 1: protocol ip prio 2 u32 \
match ip dport 80 0xffff flowid 1:20
# 4. 查看当前配置
tc -s qdisc show dev eth0
tc -s class show dev eth0
tc filter show dev eth0
# 5. 修改 class 带宽(回滚场景常用)
tc class change dev eth0 classid 1:10 htb rate 5mbit ceil 10mbit
# 6. 删除 filter 并重新添加
tc filter del dev eth0 parent 1: prio 1
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 \
match ip src 10.0.0.1/32 flowid 1:30
# 7. 清理全部规则
tc qdisc del dev eth0 root
💡 回滚验证要点:在修改 class 或 filter 前后,使用
tc -s class show dev eth0 对比 dropped 和 rate 字段,确认限速策略是否按预期生效。这是后续章节“回滚验证”的核心操作基础。
3.6 常见错误与排查
| 错误信息 | 原因 | 解决方法 |
|---|---|---|
RTNETLINK answers: No such file or directory |
指定的 parent 或 classid 不存在 | 先执行 tc qdisc show 确认现有节点 |
RTNETLINK answers: Invalid argument |
参数值超出范围或语法错误 | 检查 rate/ceil 单位(mbit/kbit),确认 handle 格式 |
RTNETLINK answers: File exists |
重复添加相同的 handle 或 classid | 使用 change 修改或先 del 再 add |
filter 不生效 |
prio 冲突或 protocol 不匹配 | 检查 prio 唯一性,确认 protocol ip 与流量类型一致 |
⚠ 生产环境建议:在执行
del 操作前,务必使用 tc qdisc show dev eth0 和 tc filter show dev eth0 备份当前规则。批量删除时,建议逐级删除(先 filter → 再 class → 最后 qdisc),避免因依赖关系导致删除失败。