0. 背景
项目需要模拟弱网环境下,测试音视频的编解码功能。
在linux系统下可以使用tc工具模拟弱网环境,包括出/入流量的丢包等。
1. tc工具介绍
2. 网卡出数据
netem(Network Emulator)可以用来对网卡发出的数据包进行增加延迟、丢包、重复、乱序等处理,来模拟复杂网络环境。netem的设置依赖tc命令,tc是Linux内核提供的流量控制工具。
具体的弱网配置,参考
本文第4部分
3. 网卡入数据
为了处理网卡接收的数据包,需要使用linux内核听过的ifb(Intermeidate Functional Block)模块。
个人理解
:启动ifb0虚拟网卡,将原输入到eth0的入流量导入到ifb0虚拟网卡中。之后,通过ifb0网卡的中转,返回给应用的数据是ifb0网卡出流量,之后对ifb0网卡便可以复用netem模块设置网络规则。
- 加载fib模块,启动ifb0网卡
sudo modprobe ifb
sudo ip link set dev ifb0 up
- 将网卡入流量导入到ifb网卡
sudo tc qdisc add dev eth0 handle ffff: ingress
sudo tc filter add dev eth0 parent ffff: u32 match u32 0 0 action mirred egress redirect dev ifb0
- 使用tc配置ifb0网卡入数据规则,举例
# 网卡丢包率设为10%
sudo tc qdisc add dev ifb0 root netem loss 10%
4. 网卡的处理
端口延时命令
网卡配置项,下面的eth0为出流量网卡,若为入流量只需将其替换为ifb0
# 表示对端口廷时100ms
tc qdisc add dev eth0 root netem delay 100ms
# 表示对端口廷时命令删除
tc qdisc del dev eth0 root netem delya 100ms
#表示对改变端口廷时命100ms ± 10ms 延时范围(90到110)
tc qdisc add dev eth0 root netem delay 100ms 10ms
# 表示廷时范围100ms ,同时有25%以± 10ms波动延迟
tc qdisc add dev eth0 root netem delay 100ms 10ms 25%
# 端口丢包命令:
# 丢包率为0.1%
tc qdisc add dev eth0 root netem loss 0.1%
# 丢包率为范围(0.3%- 25%)
tc qdisc add dev eth0 root netem loss 0.3% 25%
# 数据包重包命令
# 随机产生 1% 的重复数据包
tc qdisc add dev eth0 root netem duplicate 1%
# 数据包分发命令
# 数据包重发每格5的整数倍的包将不被延时。其它的将延时10ms
tc qdisc add dev eth0 root netem gap 5 delay 10ms
#速率控制命令:两条命令共同完成
tc qdisc add dev eth0 root handle 1:0 netem delay 100ms
tc qdisc add dev eth0 parent 1:1 handle 10: tbf rate 256kbit buffer 1600 limit 3000
#查看规则信息
tc -s qdisc ls dev eth0
tc qdisc show
#删除规则
tc qdisc del dev eth0 root
5. 特定IP或端口的处理
步骤:
- 针对网络物理设备(如以太网卡eth0)绑定一个队列QDisc;
- 在该队列上建立分类class;
- 为每一分类建立一个基于路由的过滤器filter;
- 最后与过滤器相配合,建立特定的路由表。
对IP进行限速
#查看现有的队列
tc -s qdisc ls dev eth0
#查看现有的分类
tc -s class ls dev eth0
#创建队列
tc qdisc add dev eth0 root handle 1:0 htb default 1
#添加一个tbf队列,绑定到eth0上,命名为1:0 ,默认归类为1
#handle:为队列命名或指定某队列
#创建分类
tc class add dev eth0 parent 1:0 classid 1:1 htb rate 10Mbit burst 15k
#为eth0下的root队列1:0添加一个分类并命名为1:1,类型为htb,带宽为10M
#rate: 是一个类保证得到的带宽值.如果有不只一个类,请保证所有子类总和是小于或等于父类.
#ceil: ceil是一个类最大能得到的带宽值.
#创建一个子分类
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 10Mbit ceil 10Mbit burst 15k
#为1:1类规则添加一个名为1:10的类,类型为htb,带宽为10M
#为了避免一个会话永占带宽,添加随即公平队列sfq.
tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
#perturb:是多少秒后重新配置一次散列算法,默认为10秒
#sfq,他可以防止一个段内的一个ip占用整个带宽
#使用u32创建过滤器
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip sport 22 flowid 1:10
#删除队列
tc qdisc del dev eth0 root
对PORT进行限速
#清空原有规则
tc qdisc del dev eth0 root
#创建根序列
tc qdisc add dev eth0 root handle 1: htb default 1
#创建一个主分类绑定所有带宽资源(20M)
tc class add dev eth0 parent 1:0 classid 1:1 htb rate 20Mbit burst 15k
#创建子分类
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 20Mbit ceil 10Mbit burst 15k
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 20Mbit ceil 20Mbit burst 15k
#避免一个ip霸占带宽资源
tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
#创建过滤器
#对所有ip限速
tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 match ip dst 0.0.0.0/0 flowid 1:10
#对内网ip放行
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 12.0.0.0/8 flowid 1:20
6. 使用tcconfig配置(推荐)
裸tc的配置难以使用,通过tcconfig工具,可以方便的配置netem的功能,就具体使用可参考
官方文档
。
举例:
# 对发往1.1.1.1的出数据包增加500ms延迟
tcset eth0 --delay 500ms --dst-address 1.1.1.1 --direction outgoing
# 对发往1.1.1.1的80端口的出数据包增加随机丢包5%。
tcset eth0 --loss 5% --dst-address 1.1.1.1 --dst-port 80 --direction outgoing
# 对从1.1.1.1的80端口发来的数据包增加随机丢包5%。
tcset eth0 --loss 5% --src-address 1.1.1.1 --src-port 80 --direction incoming
# 通过tcshow命令可以查看现有的规则
tcshow eth0
# 通过tcdel命令删除现有规则
tcdel eth0 --all
参考链接
:
https://my.oschina.net/u/2539854/blog/3149307
https://cloud.tencent.com/developer/article/1409664