什么是TC
TC(Traffic Control)是Linux内核提供的流量控制工具,它可以对网络接口上的数据包进行队列、调度、限流、延迟等各种操作。TC通过队列规定(Queueing Discipline,简称qdisc)来实现对网络流量的精细控制。
TC主要功能包括:
- 带宽控制
- 延迟模拟
- 丢包模拟
- 包重排
- 流量整形
基本概念
QDisc(队列规定)
QDisc是TC的核心概念,它定义了数据包在网络接口上的排队和发送规则。Linux内核支持多种类型的qdisc:
- pfifo_fast:默认的qdisc,简单的FIFO队列
- netem:网络仿真qdisc,用于模拟各种网络条件
- tbf:令牌桶过滤器,用于限制带宽
- htb:层次化令牌桶,支持复杂的带宽分配
- cbq:基于类的队列,用于复杂的流量控制
- prio:优先级队列
Handle和Parent
每个qdisc都有一个handle(句柄),格式为major:minor
:
- root:根qdisc,handle通常是
1:0
- parent:指定父qdisc的handle
常用命令格式
1# 添加qdisc
2tc qdisc add dev <interface> <position> <qdisc-type> [parameters]
3
4# 删除qdisc
5tc qdisc del dev <interface> <position>
6
7# 查看qdisc
8tc qdisc show dev <interface>
9
10返回:
11qdisc mq 0: root
12qdisc fq_codel 0: parent :2 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
13qdisc fq_codel 0: parent :1 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
14
15# 替换qdisc
16tc qdisc replace dev <interface> <position> <qdisc-type> [parameters]
参数说明:
<interface>
:网络接口名,如eth0、enp0s3等<position>
:位置,通常是root(根队列)<qdisc-type>
:队列类型,如netem、tbf等
网络延迟模拟
固定延迟
1# 添加2ms的固定延迟
2tc qdisc add dev eth0 root netem delay 2ms
3
4# 查看当前配置
5tc qdisc show dev eth0
变动延迟
1# 添加100ms±10ms的变动延迟(正态分布)
2tc qdisc add dev eth0 root netem delay 100ms 10ms
3
4# 添加100ms±10ms的变动延迟,25%相关性
5tc qdisc add dev eth0 root netem delay 100ms 10ms 25%
延迟分布
1# 使用uniform分布
2tc qdisc add dev eth0 root netem delay 100ms 20ms distribution uniform
3
4# 使用normal分布(默认)
5tc qdisc add dev eth0 root netem delay 100ms 20ms distribution normal
6
7# 使用pareto分布
8tc qdisc add dev eth0 root netem delay 100ms 20ms distribution pareto
丢包模拟
随机丢包
1# 1%的随机丢包率
2tc qdisc add dev eth0 root netem loss 1%
3
4# 0.1%的随机丢包率
5tc qdisc add dev eth0 root netem loss 0.1%
6
7# 5%丢包,25%相关性
8tc qdisc add dev eth0 root netem loss 5% 25%
连续丢包
1# Gilbert模型:p=丢包概率,r=恢复概率,1-h=好状态时丢包概率,1-k=坏状态时不丢包概率
2tc qdisc add dev eth0 root netem loss gemodel 1% 10% 70% 0.1%
包重排模拟
1# 25%的包会被延迟,延迟时间为10ms,相关性50%
2tc qdisc add dev eth0 root netem delay 10ms reorder 25% 50%
3
4# 1%的包立即发送(跳过队列)
5tc qdisc add dev eth0 root netem gap 5 delay 10ms
包重复
1# 1%的包会被重复发送
2tc qdisc add dev eth0 root netem duplicate 1%
包损坏
1# 0.1%的包会被损坏(随机位翻转)
2tc qdisc add dev eth0 root netem corrupt 0.1%
带宽限制
使用TBF(Token Bucket Filter)
1# 限制带宽为1Mbit/s,突发为32KB,延迟为400ms
2tc qdisc add dev eth0 root tbf rate 1mbit latency 400ms burst 32kbit
3
4# 限制带宽为200kbit/s
5tc qdisc add dev eth0 root tbf rate 200kbit latency 10ms burst 1600
使用HTB(Hierarchy Token Bucket)
1# 创建HTB根队列
2tc qdisc add dev eth0 root handle 1: htb default 30
3
4# 创建根类,总带宽6Mbit/s
5tc class add dev eth0 parent 1: classid 1:1 htb rate 6mbit burst 15k
6
7# 创建子类,保证带宽5Mbit/s,最大6Mbit/s
8tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5mbit burst 15k
9tc class add dev eth0 parent 1:1 classid 1:20 htb rate 1mbit ceil 6mbit burst 15k
10tc class add dev eth0 parent 1:1 classid 1:30 htb rate 1mbit ceil 6mbit burst 15k
复合条件模拟
延迟+丢包
1# 100ms延迟 + 1%丢包
2tc qdisc add dev eth0 root netem delay 100ms loss 1%
延迟+丢包+重排
1# 100ms延迟 + 1%丢包 + 10%重排
2tc qdisc add dev eth0 root netem delay 100ms loss 1% reorder 10%
延迟+带宽限制
1# 先添加netem进行延迟
2tc qdisc add dev eth0 root handle 1: netem delay 100ms
3
4# 在netem下添加tbf进行带宽限制
5tc qdisc add dev eth0 parent 1:1 handle 10: tbf rate 256kbit buffer 1600 limit 3000
针对特定流量的控制
使用filter进行分类
1# 创建HTB根队列
2tc qdisc add dev eth0 root handle 1: htb
3
4# 创建类
5tc class add dev eth0 parent 1: classid 1:1 htb rate 1mbit
6tc class add dev eth0 parent 1: classid 1:2 htb rate 1mbit
7
8# 添加过滤器:目标端口80的流量走1:1类
9tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
10 match ip dport 80 0xffff flowid 1:1
11
12# 添加过滤器:目标IP 192.168.1.100的流量走1:2类
13tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
14 match ip dst 192.168.1.100 flowid 1:2
针对特定IP限速
1# 创建HTB队列
2tc qdisc add dev eth0 root handle 1: htb
3
4# 创建默认类(无限制)
5tc class add dev eth0 parent 1: classid 1:1 htb rate 1000mbit
6
7# 创建限制类(1Mbit/s)
8tc class add dev eth0 parent 1: classid 1:2 htb rate 1mbit ceil 1mbit
9
10# 过滤特定IP的流量
11tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
12 match ip src 192.168.1.100 flowid 1:2
Docker环境下的TC使用
容器网络接口
1# 查看docker容器的网络接口
2docker exec <container_id> ip addr
3
4# 在宿主机上对容器的veth接口进行限制
5# 假设容器的veth接口是vethxxxx
6tc qdisc add dev vethxxxx root netem delay 100ms
容器内部使用TC
1# 需要特权模式运行容器
2docker run --privileged -it ubuntu:20.04 /bin/bash
3
4# 在容器内部使用tc
5tc qdisc add dev eth0 root netem delay 50ms loss 1%
查看和管理
查看当前qdisc状态
1# 查看所有接口的qdisc
2tc qdisc show
3
4# 查看特定接口
5tc qdisc show dev eth0
6
7# 查看详细统计信息
8tc -s qdisc show dev eth0
9
10# 查看类信息
11tc class show dev eth0
12
13# 查看过滤器
14tc filter show dev eth0
删除qdisc
1# 删除eth0上的根qdisc(会清除所有TC规则)
2tc qdisc del dev eth0 root
3
4# 删除特定handle的qdisc
5tc qdisc del dev eth0 handle 10:
替换qdisc配置
1# 替换现有配置
2tc qdisc replace dev eth0 root netem delay 200ms loss 2%
实际应用场景
网络测试
1# 模拟慢速网络环境测试应用性能
2tc qdisc add dev eth0 root netem delay 200ms loss 1%
3
4# 测试完成后清除规则
5tc qdisc del dev eth0 root
带宽管理
1# 为不同服务分配带宽
2tc qdisc add dev eth0 root handle 1: htb default 30
3
4# Web服务保证2Mbit/s
5tc class add dev eth0 parent 1: classid 1:10 htb rate 2mbit ceil 4mbit
6tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
7 match ip sport 80 0xffff flowid 1:10
8
9# 文件传输限制在1Mbit/s
10tc class add dev eth0 parent 1: classid 1:20 htb rate 1mbit ceil 1mbit
11tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
12 match ip sport 21 0xffff flowid 1:20
QoS配置
1# 优先级队列,3个级别
2tc qdisc add dev eth0 root handle 1: prio
3
4# 高优先级:VoIP流量
5tc filter add dev eth0 parent 1: protocol ip prio 1 u32 \
6 match ip dport 5060 0xffff flowid 1:1
7
8# 中优先级:HTTP流量
9tc filter add dev eth0 parent 1: protocol ip prio 2 u32 \
10 match ip dport 80 0xffff flowid 1:2
11
12# 低优先级:其他流量(默认)
13# flowid 1:3 是默认队列
高级用法
使用fq_codel
1# 使用Fair Queueing CoDel算法,减少缓冲膨胀
2tc qdisc add dev eth0 root fq_codel
使用cake
1# 使用CAKE(Common Applications Kept Enhanced)算法
2tc qdisc add dev eth0 root cake bandwidth 100mbit
基于mark的分类
1# 在iptables中给包打标记
2iptables -t mangle -A OUTPUT -p tcp --dport 80 -j MARK --set-mark 1
3iptables -t mangle -A OUTPUT -p tcp --dport 443 -j MARK --set-mark 2
4
5# 基于mark进行分类
6tc filter add dev eth0 parent 1: protocol ip prio 1 handle 1 fw flowid 1:1
7tc filter add dev eth0 parent 1: protocol ip prio 1 handle 2 fw flowid 1:2
故障排查
常见问题
-
qdisc添加失败
1# 检查内核模块是否加载 2lsmod | grep sch_netem 3 4# 手动加载模块 5modprobe sch_netem
-
配置不生效
1# 检查接口状态 2ip link show eth0 3 4# 查看详细错误信息 5tc -d qdisc show dev eth0
-
性能问题
1# 查看统计信息,检查dropped包数量 2tc -s qdisc show dev eth0 3 4# 检查系统负载 5top 6sar -n DEV 1
调试技巧
1# 开启详细输出
2tc -d qdisc add dev eth0 root netem delay 100ms
3
4# 查看内核消息
5dmesg | grep -i "tc\|qdisc"
6
7# 使用tcpdump验证效果
8tcpdump -i eth0 -n host <target_ip>
注意事项
- 权限要求:TC命令需要root权限或CAP_NET_ADMIN能力
- 性能影响:复杂的TC规则会消耗CPU资源,在高流量环境下需要注意
- 内核支持:某些高级功能需要特定的内核版本支持
- 网络接口状态:只能在UP状态的网络接口上应用TC规则
- 规则清理:系统重启后TC规则会丢失,需要在启动脚本中重新配置