tc 是 Linux 系统中的一个命令,用于网络流量控制。它允许系统管理员管理和配置网络接口上的数据流量,提供带宽管理、流量整形、优先级控制等功能。tc 是 Traffic Control 的缩写,通常与 Linux 内核的流量控制子系统结合使用。
一、tc 的基本组成部分
1. qdisc(Queueing Discipline):
队列调度器,管理数据包的排队和调度。主要有两种类型:
- Classless qdisc(无类队列调度器):如 pfifo、bfifo、sfq 等,不支持分类,直接调度数据包。
- Classful qdisc(有类队列调度器):如 htb、cbq 等,支持分类,可以包含多个类(class)。
2. class(类):
定义在有类队列调度器(Classful qdisc)中的分类单元,用于对流量进行细粒度的控制和管理。每个类可以有自己的带宽限制和调度策略。
3. filter(过滤器):
用于将数据包分类到不同的类中。根据数据包的属性(如 IP 地址、端口号等)进行匹配和分类。
二、参数说明
Object
字段 | 说明 |
---|---|
qdisc |
用于管理和配置队列规则(Queueing Disciplines,简称 qdisc )。队列规则定义了如何处理和转发网络接口上的数据包。 |
class |
与 qdisc 配合使用,用于定义不同的流量分类。每个 class 可以有自己的队列规则 |
filter |
用于分类数据包,将数据包分配到不同的 class 中。过滤器基于数据包的各种属性(如源IP、目的端口等)进行工作 |
action |
一种操作,它定义了当匹配到特定的流量(通常由 filter 指定)时应执行的动作。比如修改数据包、重定向流量或者执行某些特定的任务。 |
常用参数
字段 | 说明 |
---|---|
show |
显示当前的流量控制配置。 |
add |
添加一个新的流量控制规则。 |
change |
修改现有的流量控制规则。 |
replace |
替换现有的流量控制规则。 |
delete | del |
删除指定的流量控制规则。 |
dev |
后跟网络接口名称,指定要操作的网络接口。 |
root |
指定操作应用于网络接口的根。 |
parent |
指定操作的父队列或类别。 |
protocol |
指定过滤器应用于哪种网络协议的数据包,如 ip。 |
pref |
指定过滤器的优先级。 |
u32 |
一种常用的过滤器类型,可以根据数据包的内容进行非常灵活的匹配。 |
match |
定义过滤条件,如 IP 地址、端口号等。 |
flowid |
指定匹配的数据包应该被分配到的 class 的 ID。 |
prio |
过滤器指定优先级,数值较小的过滤器优先级更高 |
handle |
句柄,用户关联 class 或 filter
|
rate |
最小带宽 |
ceil |
最大带宽 |
burst |
突发流量 |
latency |
延迟 |
队列规则
规则 | 说明 |
---|---|
pfifo_fast |
默认的队列规则类型,基于先进先出(FIFO)策略,但有三个带宽优先级。 设计用于快速处理,适用于大多数普通场景。 |
bfifo | pfifo |
简单的字节(bfifo )或包(pfifo )先进先出队列。可以用来限制队列的大小,不同之处在于限制是基于包的数量( pfifo )还是总字节大小(bfifo )。 |
tbf |
令牌桶过滤器(Token Bucket Filter,tbf ),用于限制数据流的速率,实现流量整形。通过配置速率、突发数据量和延迟,可以精确控制网络流量。 |
htb |
层次令牌桶(Hierarchical Token Bucket,htb ),比 tbf 更复杂和灵活,支持创建一个有层次结构的令牌桶。允许对不同类型的流量进行分类和带宽分配,非常适用于复杂的带宽管理需求。 |
sfq |
随机公平队列(Stochastic Fair Queueing,sfq ),旨在提供公平的带宽分配给所有流量,减少拥塞和避免单个流量占用过多带宽。通过随机化处理,尝试平等地分配带宽给各个数据包。 |
fq_codel | sfq_codel |
这些是针对缓冲区膨胀(Bufferbloat)问题的先进队列管理算法。 codel(Controlled Delay)旨在减少网络延迟, fq_codel 结合了公平队列和 codel 算法。 |
netem) |
网络模拟器(Network Emulator,用于模拟网络条件,如延迟、丢包、乱序等。 适用于测试网络应用的性能,模拟不同的网络环境。 |
cbq |
基于分类的队列(Class-Based Queueing),允许基于复杂规则将流量分配到不同的类别中,每个类别可以有自己的队列规则。 是一种较早的实现带宽管理的方法,逐渐被htb等更现代的策略所取代。 |
匹配器
规则 | 说明 |
---|---|
u32 |
用途:u32 是一个通用匹配器,可以基于数据包的头部信息进行非常灵活的匹配。它允许用户定义复杂的匹配规则,如 IP 地址、端口号等。特点: u32 匹配器非常强大,但构造匹配规则相对复杂。 |
basic |
用途:basic 匹配器提供了一种简化的方式来匹配数据包的基本属性,如协议类型或特定的数据包字段。特点:比 u32 更容易使用,但不如 u32 灵活。 |
fw |
用途:fw 匹配器允许使用 iptables 的标记(mark)功能来分类流量。你可以在 iptables 规则中设置标记,然后 tc 使用这些标记来分类数据包。特点:依赖于 iptables 设置,使得流量控制规则与防火墙规则紧密集成。 |
flower |
用途:flower 匹配器是一个较新的匹配器,设计用于更直观地匹配数据包的各种属性,如以太网类型、IP 地址、VLAN 标签等。特点:提供了一种直观、易于理解的方式来定义匹配规则,特别适合于复杂的匹配条件。 |
bpf |
用途:bpf 匹配器允许使用 BPF(Berkeley Packet Filter)程序来分类数据包。BPF 是一种强大的数据包过滤框架,允许执行自定义的数据包处理逻辑。特点:极其强大和灵活,可以实现几乎任何类型的数据包匹配和处理逻辑,但需要对 BPF 编程有深入了解。 |
三、示例
添加 HTB 队列调度器和类
HTB(Hierarchical Token Bucket)是一个常用的有类队列调度器,允许分层管理和分配带宽。
# 添加 HTB 根队列调度器
tc qdisc add dev eth0 root handle 1: htb default 10
# 添加根类,保证带宽为 10mbit,最大带宽为 10mbit
tc class add dev eth0 parent 1: classid 1:1 htb rate 10mbit ceil 10mbit
# 添加子类1,保证带宽为 5mbit,最大带宽为 10mbit
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5mbit ceil 10mbit
# 添加子类2,保证带宽为 3mbit,最大带宽为 10mbit
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 3mbit ceil 10mbit
# 为子类1添加 SFQ 队列调度器
tc qdisc add dev eth0 parent 1:10 handle 10: sfq
# 为子类2添加 SFQ 队列调度器
tc qdisc add dev eth0 parent 1:20 handle 20: sfq
# 添加过滤器,将流量分类到子类1
tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip src 192.168.1.0/24 flowid 1:10
# 添加过滤器,将流量分类到子类2
tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip src 192.168.2.0/24 flowid 1:20
解释
1. 添加 HTB 根队列调度器:
tc qdisc add dev eth0 root handle 1: htb default 10
- root:在设备 eth0 上添加一个根 qdisc。
- handle 1: htb:指定队列调度器类型为 HTB,并将其句柄设置为 1:。
- default 10:默认类 ID 为 10,表示未明确分类的流量将使用这个类。
2. 添加 HTB 类:
tc class add dev eth0 parent 1: classid 1:1 htb rate 10mbit ceil 10mbit
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5mbit ceil 10mbit
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 3mbit ceil 10mbit
- parent 1::在根 qdisc(句柄 1:)下添加类。
- classid 1:1、1:10、1:20:设置类的 ID。
- htb:指定类的类型为 HTB。
- rate 和 ceil:设置保证带宽和最大带宽。
3. 为子类添加队列调度器:
tc qdisc add dev eth0 parent 1:10 handle 10: sfq
tc qdisc add dev eth0 parent 1:20 handle 20: sfq
- parent 1:10、1:20:在类 1:10 和 1:20 下添加子 qdisc。
- handle 10: sfq、20: sfq:指定队列调度器类型为 SFQ,并将其句柄设置为 10: 和 20:。
4. 添加过滤器:
tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip src 192.168.1.0/24 flowid 1:10
tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip src 192.168.2.0/24 flowid 1:20
- protocol ip:指定过滤器应用于 IP 协议。
- parent 1::将过滤器应用于句柄 1: 的根 qdisc。
- prio 1:设置过滤器的优先级为 1。
- u32 match ip src:使用 u32 过滤器匹配源 IP 地址。
- flowid 1:10、1:20:将匹配的流量导向类 1:10 和 1:20。
四、返回内容说明
1. tc class show
显示了指定网络接口(在此例中为 vnet0)上的流量控制分类(class)规则。这些规则定义了如何根据不同的流量类别对网络流量进行管理和调度
# tc class show dev vnet0
class cbq 1: root rate 10Gbit (bounded,isolated) prio no-transmit
class cbq 1:445 parent 1: rate 100Mbit (bounded) prio 1
说明:
-
class cbq 1: root rate 10Gbit (bounded,isolated) prio no-transmit
class cbq
:表示使用的是 CBQ(Class-Based Queuing)排队策略。
CBQ 是一种早期的流量控制算法,它允许基于不同的类别对流量进行细粒度的管理。
1:
:这是类别的唯一标识符,通常表示为主类别ID: 次类别 ID
。在这里,只有主类别ID,表示这是一个顶级类别。
root
:表示这个类别是根类别,是所有其他类别的父类别。
rate 10Gbit
:定义了这个类别的最大传输速率为10Gbps。
(bounded,isolated)
:bounded
表示这个类别的带宽被限制在指定的速率内;
isolated
表示这个类别与其他类别隔离,不会与其他流量共享额外的带宽。
prio no-transmit
:表示这个类别没有指定优先级(no-transmit
),这意味着它不用于正常的数据传输。 -
class cbq 1:445 parent 1: rate 100Mbit (bounded) prio 1
1:445
:这是当前类别的唯一标识符,其中1:
是主类别ID,445
是次类别ID。
parent 1:
:表示这个类别的父类别是 ID 为1:
的类别,即上面描述的根类别。
rate 100Mbit
:定义了这个类别的最大传输速率为 100Mbps。
(bounded)
:表示这个类别的带宽被限制在指定的速率内。
prio 1
:指定了这个类别的优先级为1
,优先级数字较小表示较高的处理优先级。
2. tc filter show
显示了指定网络接口(在此例中为 vnet0)上配置的流量过滤规则。流量过滤器用于识别特定的数据包,并根据匹配的规则将它们分配到不同的流量类别(class)中进行处理
# tc filter show dev vnet0
filter parent 1: protocol ip pref 49152 u32
filter parent 1: protocol ip pref 49152 u32 fh 800: ht divisor 1
filter parent 1: protocol ip pref 49152 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:445
match 00000000/00000000 at 16
说明:
-
filter parent 1: protocol ip pref 49152 u32
filter parent 1:
:表示这个过滤器应用于 ID为1:
的父类(通常是根队列规则或类别)。
protocol ip
:指定这个过滤器仅适用于 IP 协议的数据包。
pref 49152
:表示这个过滤器的优先级为 49152。在处理数据包时,较低的 pref 值表示较高的处理优先级。
u32
:指这个过滤器使用的是u32
选择器,u32
是一种灵活的过滤器,能够基于数据包中的任意 32 位字段进行匹配。
-
filter parent 1: protocol ip pref 49152 u32 fh 800: ht divisor 1
fh 800:
:fh
(filter handle)是过滤器的唯一标识符,800:
是这个过滤器的句柄。
ht divisor 1
:ht
(hash table)表示过滤器使用的哈希表,divisor 1
指定了哈希表大小的除数,用于确定哈希表的桶(bucket)数量。 -
filter parent 1: protocol ip pref 49152 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:445
order 2048
:指定了在同一优先级下过滤器的处理顺序。
key ht 800 bkt 0
:指明了过滤器所用的哈希表键值和桶号。
flowid 1:445
:如果匹配成功,匹配到的流量将被分配到 ID为1:445
的流量类别中处理。
match 00000000/00000000 at 16
:指定了过滤器的匹配规则。
这里表示过滤器匹配数据包的第 16 字节处的值与 00000000 进行比较,掩码为 00000000,实际上这是一个不会成功匹配任何数据包的示例规则(因为掩码为 0 )。
网友评论