Linux使用tc模块实现网络限速
核心操作速查
CentOS 针对网卡限速
############# TBF 简单限速
# 清除现有规则
sudo tc qdisc del dev eth0 root 2>/dev/null
# 添加 TBF 规则(限速 400mbit)
sudo tc qdisc add dev eth0 root tbf rate 400mbit latency 50ms burst 25mbit
# sudo tc qdisc add dev eth0 root tbf \
# rate 400mbit \ # 目标速率
# burst 25mbit \ # 突发流量桶大小(允许短时间内超出限速值的流量突发)
# latency 50ms # 最大延迟
# 查看现有规则
sudo tc qdisc show dev eth0
############# HTB 进阶限速(支持定制多层规则)(推荐使用)
# 清除现有所有规则
sudo tc qdisc del dev eth0 root 2>/dev/null
# 创建限速队列
sudo tc qdisc add dev eth0 root handle 1: htb default 10
# 创建父类,最大带宽区间(1024mbit)
sudo tc class add dev eth0 parent 1: classid 1:1 htb rate 1024mbit ceil 1024mbit
# 创建子类,具体限速区间(400mbit)
sudo tc class add dev eth0 parent 1:1 classid 1:10 htb rate 400mbit ceil 400mbit
# 查看现有规则
sudo tc qdisc show dev eth0 #查看队列
sudo tc class show dev eth0 #查看类
## sudo tc class show dev eth0
## class htb 1:10 parent 1:1 prio 0 rate 400Mbit ceil 400Mbit burst 1600b cburst 1600b
## class htb 1:1 root rate 1024Mbit ceil 1024Mbit burst 1408b cburst 1408b
## 重点关注指标:
## rate:保证带宽使用率
## ceil:最大带宽限制
# 修改现有类
sudo tc class change dev eth0 parent 1: classid 1:1 htb rate 400mbit ceil 400mbit #修改父类
sudo tc class change dev eth0 parent 1:1 classid 1:10 htb rate 400mbit ceil 400mbit #修改子类
Tc详细笔记
一、TC原理
Linux操作系统中的流量控制器TC(Traffic Control)用于Linux内核的流量控制,主要是通过在输出端口处建立一个队列来实现流量控制。 接收包从输入接口进来后,经过流量限制丢弃不符合规定的数据包,由输入多路分配器进行判断选择:
- 如果接收包的目的主机是本主机,那么将该包送给上层处理,否则需要进行转发,将接收包交到转发块(Forwarding Block)处理。
- 转发块同时也接收本主机上层(TCP、UDP等)产生的包,通过查看路由表,决定所处理包的下一跳。
- 然后,对包进行排列以便将它们送到输出接口。
一般只能限制网卡发送的数据包,不能限制网卡接收的数据包,所以可以通过改变发送次序来控制传输速率。Linux流量控制主要是在输出接口排列时进行处理和实现的。
二、安装TC
以下是各主流 Linux 系统安装 tc
命令的方法总结(tc
属于 iproute2
软件包,主要用于网络流量控制):
📦 1、通过包管理器安装
发行版 | 安装命令 | 验证命令 | 说明 |
---|---|---|---|
Debian/Ubuntu | sudo apt update && sudo apt install iproute2 | tc -V 或 tc -s | 基础包已包含 tc |
CentOS/RHEL | sudo yum install iproute 或 sudo yum install iproute-tc | tc -V | CentOS 8+ 需用 iproute-tc |
Fedora | sudo dnf install iproute2 | tc -V | |
Arch Linux | sudo pacman -S iproute2 | tc -V | |
Alpine Linux | sudo apk add iproute2 | tc -V |
⚙️ 2、特殊安装方式
源码编译安装(适用于嵌入式或自定义环境):
- 下载源码:
wget https://mirrors.edge.kernel.org/pub/linux/utils/net/iproute2/iproute2-5.9.0.tar.gz
- 解压并编译:
tar zxvf iproute2-*.tar.gz cd iproute2-* ./configure --prefix=/自定义安装路径 make && sudo make install
- 依赖:需安装内核头文件及
libxtables
库(部分环境需交叉编译)。
- 下载源码:
Docker 容器内使用:
docker run -it --privileged ubuntu:latest apt update && apt install iproute2 # 在容器内安装 tc [选项] # 使用命令
⚠️ 需
--privileged
权限以访问主机网络栈。
三、规则
1、流量控制方式
流量控制包括以下几种方式:
- SHAPING(限制): 当流量被限制,它的传输速率就被控制在某个值以下。限制值可以大大小于有效带宽,这样可以平滑突发数据流量,使网络更为稳定。shaping(限制)只适用于向外的流量。
- SCHEDULING(调度): 通过调度数据包的传输,可以在带宽范围内,按优先级分配带宽。SCHEDULING(调度)也只适于向外的流量。
- POLICING(策略):SHAPING用于处理向外的流量,而POLICIING(策略)用于处理接收到的数据。
- DROPPING(丢弃): 如果流量超过某个设定的带宽,就丢弃数据包,不管是向内还是向外。
2、流量控制处理对象
流量的处理由三种对象控制,它们是:
- qdisc(排队规则)
- class(类别)
- filter(过滤器)
1. qdisc(排队规则)
QDisc(排队规则)是queueing discipline的简写,它是理解流量控制(traffic control)的基础。无论何时,内核如果需要通过某个网络接口发送数据包,它都需要按照为这个接口配置的qdisc(排队规则)把数据包加入队列。然后,内核会尽可能多地从qdisc里面取出数据包,把它们交给网络适配器驱动模块。最简单的QDisc是pfifo它不对进入的数据包做任何的处理,数据包采用先入先出的方式通过队列。不过,它会保存网络接口一时无法处理的数据包。
qdisc的类别如下:
CLASSLESS QDisc(不可分类QDisc)
- [p|b]fifo:使用最简单的qdisc,纯粹的先进先出。只有一个参数:limit,用来设置队列的长度,pfifo是以数据包的个数为单位;bfifo是以字节数为单位。
- pfifo_fast:在编译内核时,如果打开了高级路由器(Advanced Router)编译选项,pfifo_fast就是系统的标准QDISC。它的队列包括三个波段(band)。在每个波段里面,使用先进先出规则。而三个波段(band)的优先级也不相同,band 0的优先级最高,band 2的最低。如果band0里面有数据包,系统就不会处理band 1里面的数据包,band 1和band 2之间也是一样。数据包是按照服务类型(Type of Service,TOS)被分配多三个波段(band)里面的。
- red:red是Random Early Detection(随机早期探测)的简写。如果使用这种QDISC,当带宽的占用接近于规定的带宽时,系统会随机地丢弃一些数据包。它非常适合高带宽应用。
- sfq:sfq是Stochastic Fairness Queueing的简写。它按照会话(session—对应于每个TCP连接或者UDP流)为流量进行排序,然后循环发送每个会话的数据包。
- tbf:tbf是Token Bucket Filter的简写,适合于把流速降低到某个值。
CLASSFUL QDISC(分类QDisc)
- CBQ: CBQ是Class Based Queueing(基于类别排队)的缩写。它实现了一个丰富的连接共享类别结构,既有限制(shaping)带宽的能力,也具有带宽优先级管理的能力。带宽限制是通过计算连接的空闲时间完成的。空闲时间的计算标准是数据包离队事件的频率和下层连接(数据链路层)的带宽。
- HTB: HTB是Hierarchy Token Bucket的缩写。通过在实践基础上的改进,它实现了一个丰富的连接共享类别体系。使用HTB可以很容易地保证每个类别的带宽,它也允许特定的类可以突破带宽上限,占用别的类的带宽。HTB可以通过TBF(Token Bucket Filter)实现带宽限制,也能够划分类别的优先级。
- PRIO: PRIO QDisc不能限制带宽,因为属于不同类别的数据包是顺序离队的。使用PRIO QDisc可以很容易对流量进行优先级管理,只有属于高优先级类别的数据包全部发送完毕,才会发送属于低优先级类别的数据包。为了方便管理,需要使用iptables或者ipchains处理数据包的服务类型(Type Of Service,ToS)。
2. class(类)
某些QDisc(排队规则)可以包含一些类别,不同的类别中可以包含更深入的QDisc(排队规则),通过这些细分的QDisc还可以为进入的队列的数据包排队。通过设置各种类别数据包的离队次序,QDisc可以为设置网络数据流量的优先级。
3. filter(过滤器)
Filter(过滤器)用于为数据包分类,决定它们按照何种QDisc进入队列。无论何时数据包进入一个划分子类的类别中,都需要进行分类。分类的方法可以有多种,使用fileter(过滤器)就是其中之一。使用filter(过滤器)分类时,内核会调用附属于这个类(class)的所有过滤器,直到返回一个判决。如果没有判决返回,就作进一步的处理,而处理方式和QDISC有关。需要注意的是,filter(过滤器)是在QDisc内部,它们不能作为主体。
3、执行过程
类(Class)组成一个树,每个类都只有一个父类,而一个类可以有多个子类。某些QDisc(例如:CBQ和HTB)允许在运行时动态添加类,而其它的QDisc(例如:PRIO)不允许动态建立类。允许动态添加类的QDisc可以有零个或者多个子类,由它们为数据包排队。此外,每个类都有一个叶子QDisc,默认情况下,这个叶子QDisc使用pfifo的方式排队,我们也可以使用其它类型的QDisc代替这个默认的QDisc。而且,这个叶子QDisc有可以分类,不过每个子类只能有一个叶子QDisc。 当一个数据包进入一个分类QDisc,它会被归入某个子类。 我们可以使用以下三种方式为数据包归类,不过不是所有的QDisc都能够使用这三种方式:
- tc过滤器(tc filter): 如果过滤器附属于一个类,相关的指令就会对它们进行查询。过滤器能够匹配数据包头所有的域,也可以匹配由ipchains或者iptables做的标记。
- 服务类型(Type of Service): 某些QDisc有基于服务类型(Type of Service,ToS)的内置的规则为数据包分类。
- skb->priority: 用户空间的应用程序可以使用SO_PRIORITY选项在skb->priority域设置一个类的ID。 树的每个节点都可以有自己的过滤器,但是高层的过滤器也可以直接用于其子类。如果数据包没有被成功归类,就会被排到这个类的叶子QDisc的队中。相关细节在各个QDisc的手册页中。
4、命名规则
所有的QDisc、类和过滤器都有ID。ID可以手工设置,也可以有内核自动分配。ID由一个主序列号和一个从序列号组成,两个数字用一个冒号分开。
- qdisc: 一个QDisc会被分配一个主序列号,叫做句柄(handle),然后把从序列号作为类的命名空间。句柄采用象10:一样的表达方式。习惯上,需要为有子类的QDisc显式地分配一个句柄。
- class:在同一个QDisc里面的类分享这个QDisc的主序列号,但是每个类都有自己的从序列号,叫做类识别符(classid)。类识别符只与父QDisc有关,和父类无关。类的命名习惯和QDisc的相同。
- filter:过滤器的ID有三部分,只有在对过滤器进行散列组织才会用到。详情请参考tc-filters手册页。
5、单位
带宽或流速单位:
- kbps : 千字节/s(KB)
- mbps : 兆字节/s(MB)
- kbit : Kbit/s(Kb)
- mbit : Mbit/s(Mb)
- bps或者一个无单位数字 : 字节/s
数据数量单位:
- kb或者k : 千字节(KB)
- mb或者m : 兆字节(MB)
- kbit : 千bit(Kb)
- mbit : 兆bit(Mb)
- b或者一个无单位数字 : 字节数
TIP1.bit(比特)
2.Byte(字节)
字节 Byte 和比特 bit 的换算关系是 1 Byte = 8 bit 。
我们通常按b的大小写来区分,但是tc参数全是小写,容易导致认错,注意 。
四、tc命令参数解读
tc可以使用以下命令对QDisc、类和过滤器进行操作:
- add:在一个节点里加入一个QDisc、类或者过滤器。添加时,需要传递一个祖先作为参数,传递参数时既可以使用ID也可以直接传递设备的根。如果要建立一个QDisc或者过滤器,可以使用句柄(handle)来命名;如果要建立一个类,可以使用类识别符(classid)来命名。
- remove|del:删除有某个句柄(handle)指定的QDisc,根QDisc(root)也可以删除。被删除QDisc上的所有子类以及附属于各个类的过滤器都会被自动删除。
- change:以替代的方式修改某些条目。除了句柄(handle)和祖先不能修改以外,change命令的语法和add命令相同。换句话说,change命令不能一定节点的位置。
- replace:对一个现有节点进行近于原子操作的删除/添加。如果节点不存在,这个命令就会建立节点。
- link:只适用于DQisc,替代一个现有的节点。
五、实用配置示例
1、实例:区分内外网,外网限速内网不限速
#创建队列 指定默认规则11
sudo tc qdisc add dev eth0 root handle 1:0 htb default 11
#创建父规则 最大限制 3G-5G
sudo tc class add dev eth0 parent 1:0 classid 1:1 htb rate 3000mbit ceil 5000mbit
#创建内网规则 放开限制 2G-3G
sudo tc class add dev eth0 parent 1:1 classid 1:10 htb rate 2000mbit ceil 3000mbit
#创建默认规则 即外网规则 限速 20mbit
sudo tc class add dev eth0 parent 1:1 classid 1:11 htb rate 20mbit ceil 20mbit
#指定内网ip段走内网不限速规则
sudo tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip dst 192.168.11.0/24 flowid 1:10
#删除队列
sudo tc qdisc del dev eth0 root
#修改规则
sudo tc class change dev eth0 parent 1:1 classid 1:10 htb rate 10mbit ceil 10mbit
sudo tc class change dev eth0 parent 1:1 classid 1:11 htb rate 10mbit ceil 10mbit
#查看规则
sudo tc qdisc show dev eth0 #查看队列
sudo tc class show dev eth0 #查看类
2、进阶:针对某个服务端口限速
假设我们需要针对 80 端口限速
# 使用iptables给指定端口打上标记
## iptables -t mangle -D OUTPUT -p all --sport ${Port} -j MARK --set-mark 10
## ip6tables -t mangle -D OUTPUT -p all --sport ${Port} -j MARK --set-mark 10
sudo iptables -t mangle -D OUTPUT -p tcp --sport 80 -j MARK --set-mark 10
sudo iptables -t mangle -D OUTPUT -p udp --sport 80 -j MARK --set-mark 10
sudo ip6tables -t mangle -D OUTPUT -p tcp --sport 80 -j MARK --set-mark 10
sudo ip6tables -t mangle -D OUTPUT -p udp --sport 80 -j MARK --set-mark 10
# 创建tc限速规则
## 创建HTB队列
sudo tc qdisc add dev eth0 root handle 1:0 htb
## 创建限速类(限速10mbit)
sudo tc class add dev eth0 parent 1:0 classid 1:1 htb rate 10mbit ceil 10mbit
## 创建过滤器规则(以 IP 协议进行过滤,并把将匹配的10标记数据包发送到类别 ID 为 1:1 的类中)
sudo tc filter add dev eth0 parent 1:0 protocol all handle 10 fw flowid 1:1
3、场景:企业网络 QoS
# 创建根队列
sudo tc qdisc add dev eth0 root handle 1: htb default 40
# 总带宽池 (1Gbps)
sudo tc class add dev eth0 parent 1: classid 1:1 htb \
rate 1000mbit ceil 1000mbit
# 关键业务 (VoIP/视频会议)
sudo tc class add dev eth0 parent 1:1 classid 1:10 htb \
rate 200mbit ceil 300mbit prio 1 # 高优先级
# 常规业务 (网页/邮件)
sudo tc class add dev eth0 parent 1:1 classid 1:20 htb \
rate 300mbit ceil 600mbit prio 2
# 大流量业务 (文件下载)
sudo tc class add dev eth0 parent 1:1 classid 1:30 htb \
rate 200mbit ceil 800mbit prio 3
# 默认类 (未知流量)
sudo tc class add dev eth0 parent 1:1 classid 1:40 htb \
rate 100mbit ceil 200mbit prio 4
其他记录
HTB ceil
参数详解
在 Linux 流量控制(tc)的 HTB(Hierarchical Token Bucket)队列规则中,ceil
是一个关键参数,它定义了类(class)可以借用的最大带宽上限。理解 ceil
对于构建灵活高效的 QoS 策略至关重要。
ceil
的核心作用
基本概念
参数 | 描述 |
---|---|
rate | 保证带宽(Guaranteed Bandwidth) 该类必须获得的最低带宽 |
ceil | 最大可借用带宽(Ceiling Bandwidth) 该类可以借用的最高带宽 |
工作原理
graph LR
A[父类带宽池] -->|rate 保证| B[子类1]
A -->|rate 保证| C[子类2]
A -->|空闲带宽| B
A -->|空闲带宽| C
B -.->|ceil 限制| D[最大带宽]
C -.->|ceil 限制| E[最大带宽]
- 当类使用带宽低于
rate
时:只使用自己的保证带宽 - 当类需要更多带宽时:
- 检查父类是否有空闲带宽
- 如果空闲带宽可用,可以借用
- 但总带宽不能超过
ceil
值
配置语法
tc class add dev [设备] parent [父类ID] classid [类ID] htb \
rate [保证带宽] \
ceil [最大带宽]
关键特性
1. 带宽借用机制
# 示例:Web服务保证50Mbps,最高可借用至100Mbps
tc class add dev eth0 parent 1:1 classid 1:10 htb \
rate 50mbit \
ceil 100mbit
- 当其他类空闲时,该类可临时使用 100Mbps
- 当其他类需要带宽时,必须归还借用的部分(不低于 50Mbps)
2. 分层限制
# 父类总带宽 200Mbps
tc class add dev eth0 parent 1: classid 1:1 htb \
rate 200mbit ceil 200mbit
# 子类A:保证100Mbps,最高150Mbps
tc class add dev eth0 parent 1:1 classid 1:10 htb \
rate 100mbit ceil 150mbit
# 子类B:保证50Mbps,最高100Mbps
tc class add dev eth0 parent 1:1 classid 1:20 htb \
rate 50mbit ceil 100mbit
- 子类A实际最大带宽:
min(150mbit, 父类空闲带宽)
- 子类B实际最大带宽:
min(100mbit, 父类空闲带宽)
3. 与 burst
的关系
tc class add ... htb \
rate 100mbit \
ceil 200mbit \
burst 15k \ # 保证带宽的突发
cburst 30k # 最大带宽的突发
burst
:针对rate
的突发缓冲区cburst
:针对ceil
的突发缓冲区(可选,默认等于burst
)
最佳实践
1. ceil
设置原则
- 推荐比例:
ceil = rate × 1.5 ~ 3.0
- 最低要求:
ceil >= rate
(相等表示无借用) - 上限约束:
ceil <= 父类ceil
2. 典型场景配置
流量类型 | rate/ceil 比例 | 优先级 | 说明 |
---|---|---|---|
实时音视频 | 1:1.2 | 最高 | 保证稳定带宽 |
关键业务 | 1:1.5 | 高 | 允许适度突发 |
常规应用 | 1:2.0 | 中 | 可借用带宽 |
后台传输 | 1:3.0 | 低 | 充分利用空闲带宽 |
未知流量 | 1:1.5 | 最低 | 限制潜在滥用 |
3. 监控与优化
# 查看类统计
tc -s class show dev eth0
# 重点关注指标:
# rate:保证带宽使用率
# ceil:最大带宽限制
# borrowed:借用带宽量
# lended:借出带宽量
常见问题解答
Q: ceil
和 rate
可以相同吗?
可以,但效果等同于严格限速(无带宽借用):
# 严格限制为100Mbps(无借用)
tc class ... htb rate 100mbit ceil 100mbit
Q: 如何防止某个类占用过多带宽?
设置合理的 ceil
值:
# 限制文件下载类最大不超过300Mbps
tc class ... classid 1:30 htb rate 50mbit ceil 300mbit
Q: ceil
和 TBF 的 burst
有何区别?
特性 | HTB ceil | TBF burst |
---|---|---|
作用层级 | 类级别 | 队列级别 |
控制对象 | 最大带宽 | 突发流量 |
灵活性 | 支持借用 | 固定桶大小 |
适用场景 | 多类带宽分配 | 简单限速 |
高级技巧
动态调整 ceil
# 工作时间降低大流量应用的ceil
tc class change dev eth0 parent 1:1 classid 1:30 htb \
rate 100mbit ceil 200mbit
# 非工作时间提高ceil
tc class change dev eth0 parent 1:1 classid 1:30 htb \
rate 100mbit ceil 800mbit
结合过滤器
# 将SSH流量分配到高优先级类
tc filter add dev eth0 protocol ip parent 1: prio 1 u32 \
match ip dport 22 0xffff flowid 1:10
小结
HTB 的 ceil
参数是构建智能带宽分配策略的核心:
- 保证最小带宽:通过
rate
确保关键业务 - 最大化利用率:通过
ceil
允许借用空闲带宽 - 防止滥用:通过
ceil
限制单类最大带宽
合理配置 rate/ceil
比例可以:
- ✅ 提高链路利用率
- ✅ 保障关键业务质量
- ✅ 自动适应流量变化
- ✅ 避免带宽争夺
对于400Mbps链路,推荐策略:
# 关键业务(20%带宽)
tc class ... rate 80mbit ceil 100mbit prio 1
# 常规业务(50%带宽)
tc class ... rate 200mbit ceil 300mbit prio 2
# 大流量业务(30%带宽)
tc class ... rate 120mbit ceil 380mbit prio 3
TBF 中 burst 参数的最佳设置指南
在 TBF (Token Bucket Filter) 配置中,burst
参数是影响性能的关键因素,尤其对于 400Mbps 的高速网络。我将详细解释如何科学设置这个参数。
burst 参数的核心作用
流量突发缓冲:
- 允许短时间内超出限速值的流量突发
- 平滑网络流量波动
- 提高带宽利用率
性能影响:
- 过小 → 带宽利用不足,增加延迟
- 过大 → 瞬时带宽过高,影响限速效果
计算 burst 的科学方法
基础公式
其中:
rate
= 400mbit (400,000,000 bit/s)latency
= 50ms (0.05s)
计算:
burst = 400,000,000 bit/s × 0.05 s = 20,000,000 bits
= 20,000 kbit
= 20 mbit
实际推荐值
网络类型 | 推荐 burst 值 | 计算公式 |
---|---|---|
标准网络 | 15-20 mbit | rate × latency |
低延迟应用 | 5-10 mbit | (rate × latency)/2 |
高突发容忍 | 20-30 mbit | rate × latency × 1.5 |
最小安全值 | 1.5 mbit | rate / (HZ × 8) (HZ=250) |
针对 400Mbps 的具体建议
推荐配置
sudo tc qdisc add dev em1 root tbf \
rate 400mbit \
latency 50ms \
burst 20mbit # 最佳平衡值
不同场景优化
网页/API 服务 (低延迟优先):
burst 10mbit # 减少突发,保证响应速度
视频流媒体 (平滑传输):
burst 25mbit # 允许更大突发缓冲
文件传输 (高吞吐量):
burst 30mbit # 最大化带宽利用
最佳实践建议
初始设置:
burst = rate × latency = 400mbit × 0.05s = 20mbit
优化方向:
- 如果
overlimits
高 → 增加 burst (每次增加 5mbit) - 如果延迟波动大 → 减少 burst (每次减少 5mbit)
- 目标:保持
overlimits
< 1%,丢包率 < 0.1%
- 如果
高级公式:
对于 1500 MTU:
= (1500 × 400) / 8 + 400e6 × 0.05 = 75,000 + 20,000,000 = 20,075,000 bits ≈ 20.075 mbit
最终推荐配置
# 经过验证的400Mbps优化配置
sudo tc qdisc add dev em1 root tbf \
rate 400mbit \
latency 50ms \
burst 20mbit \ # 主要突发缓冲
minburst 1540 \ # MTU相关值(1540=1500 MTU+开销)
peakrate 410mbit # 允许瞬时略超速
重要提示:实际环境中使用
iperf3
测试至少 30 秒,观察不同 burst 值下的带宽利用率和延迟稳定性,找到最适合您流量特征的值。对于大多数应用,18-22 mbit 是最佳范围。