linux下使用tc控制和模拟网络流量

2023-12-13 15:57:52

1?模拟延迟传输简介

netem 与 tc: netem 是 Linux 2.6 及以上内核版本提供的一个网络模拟功能模块。该功能模块可以用来在性能良好的局域网中,模拟出复杂的互联网传输性能,诸如低带宽、传输延迟、丢包等等情况。使用 Linux 2.6 (或以上) 版本内核的很多发行版 Linux 都开启了该内核功能,比如 Fedora、Ubuntu、Redhat、OpenSuse、CentOS、Debian 等等。 tc 是Linux 系统中的一个工具,全名为 traffic control(流量控制)。tc 可以用来控制 netem 的工作模式,也就是说,如果想使用 netem ,需要至少两个条件,一个是内核中的 netem 功能被包含,另一个是要有 tc 。

需要注意的是:本文介绍的流控只能控制发包动作,不能控制收包动作,同时,它直接对物理接口生效,如果控制了物理的 eth0,那么逻辑网卡(比如 eth0:1)也会受到影响,反之,如果您在逻辑网卡上做控制,该控制可能是无效的。(注:虚拟机中的多个网卡可以在虚拟机中视为多个物理网卡)。

2. 模拟网络抖动

# tc qdisc add dev eth0 root netem delay 100ms

该命令将?eth0?网卡的传输设置为延迟?100?毫秒发送。

更真实的情况下,延迟值不会这么精确,会有一定的波动,我们可以用下面的情况来模拟出

带有波动性的延迟值:

# tc qdisc add dev eth0 root netem delay 100ms 10ms

该命令将?eth0?网卡的传输设置为延迟?100ms ± 10ms?(90 ~ 110 ms?之间的任意值)发送。

还可以更进一步加强这种波动的随机性:

# tc qdisc add dev eth0 root netem delay 100ms 10ms 30%

该命令将?eth0?网卡的传输设置为?100ms?,同时,大约有?30%?的包会延迟?± 10ms?发送。示例:现在?ping?一下?216?机器:

可以看出数据明显的波动性。

# tc qdisc add dev eth0 root netem loss 1%

该命令将?eth0?网卡的传输设置为随机丢掉?1%?的数据包。示例:在?216?上执行

#tc qdisc add dev eth0 root netem loss 10%

显示?16?个包只有?13?个收到了。也可以设置丢包的成功率:

# tc qdisc add dev eth0 root netem loss 1% 30%

该命令将?eth0?网卡的传输设置为随机丢掉?1%?的数据包,成功率为?30%?。

4.删除网卡上面的相关配置:将之前命令中的?add?改为?del?即可删除配置:

# tc qdisc del dev eth0 XXXXXXXXXXX(自己加的配置)该命令将 删除?eth0?网卡的相关传输配置

至此,我们已经可以通过?TC?在测试环境中模拟一定的网络延时和丢包的情况。下面是关于tc?更多的应用和介绍

5?模拟包重复:
# tc qdisc add dev eth0 root netem duplicate 1%

该命令将?eth0?网卡的传输设置为随机产生?1%?的重复数据包 。6?模拟数据包损坏:

# tc qdisc add dev eth0 root netem corrupt 0.2%

该命令将?eth0?网卡的传输设置为随机产生?0.2%?的损坏的数据包 。?(内核版本需在?2.6.16?以上)

7?模拟数据包乱序:
# tc qdisc change dev eth0 root netem delay 10ms reorder 25% 50%

该命令将?eth0?网卡的传输设置为:有?25%?的数据包(50%相关)会被立即发送,其他的延迟10?秒。

新版本中,如下命令也会在一定程度上打乱发包的次序:# tc qdisc add dev eth0 root netem delay 100ms 10ms

8?查看已经配置的网络条件:# tc qdisc show dev eth0

该命令将?查看并显示?eth0?网卡的相关传输配置

3.原理简介

参考:?流量控制 · GitBook

TC?是一个流量控制的工具,下面转了一篇关于?TC?流量控制的文章。TC?介绍?

在?linux?中,TC?有二种控制方法?CBQ?和?HTB.HTB?是设计用来替换?CBQ?的。它是一个层次式的过滤框架.

TC?包括三个基本的构成块:

队列规定?qdisc(queueing discipline?)、类(class)和分类器(Classifiers)

TC?中的队列(queueing discipline):
用来实现控制网络的收发速度.通过队列,linux?可以将网络数据包缓存起来,然后根据用户的

设置,在尽量不中断连接(如?TCP)的前提下来平滑网络流量.需要注意的是,linux?对接收队列的控制不够好,所以我们一般只用发送队列,即“控发不控收”.它封装了其他两个主要?TC?组件(类和分类器)。内核如果需要通过某个网络接口发送数据包,它都需要按照为这个接口配置的?qdisc(排队规则)把数据包加入队列。然后,内核会?尽可能多地从?qdisc?里面取出数据包,把它们交给网络适配器驱动模块。

最简单的?QDisc?是?pfifo?它不对进入的数据包做任何的处理,数据包采用先入先出的方式通过队列。不过,它会保存网络接口一时无法处理的数据包。
队列规则包括?FIFO(先进先出),RED(随机早期探测),SFQ(随机公平队列)和令牌桶(Token Bucket),类基队列(CBQ),CBQ?是一种超级队列,即它能够包含其它队列(甚至其它?CBQ)。

TC?中的?Class?类
class?用来表示控制策略.很显然,很多时候,我们很可能要对不同的?IP?实行不同的流量控制策略,这时候我们就得用不同的?class?来表示不同的控制策略了.

TC?中的?Filter?规则
filter?用来将用户划入到具体的控制策略中(即不同的?class?中).比如,现在,我们想对?xxa,xxb两个?IP?实行不同的控制策略(A,B),这时,我们可用?filter?将?xxa?划入到控制策略?A,将?xxb?划入到控制策略?B,filter?划分的标志位可用?u32?打标功能或?IPtables?的?set-mark (大多使用iptables?来做标记)功能来实现。
目前,TC?可以使用的过滤器有:fwmark?分类器,u32?分类器,基于路由的分类器和?RSVP分类器(分别用于?IPV6、IPV4)等;其中,fwmark?分类器允许我们使用?Linux netfilter?代码选择流量,而?u32?分类器允许我们选择基于?ANY?头的流量?.需要注意的是,filter (过滤器)是在?QDisc?内部,它们不能作为主体。

TC?的应用流程
数据包->iptables(在通过?iptables?时,iptables?根据不同的?ip?来设置不同的?mark)->TC(class)-

>TC(queue)

4. 应用举例

假设?eth0?位是服务器的外网网络接口。开始之前,先要清除?eth0?所有队列规则

tc qdisc del dev eth0 root?2> /dev/null?> /dev/null1)?定义最顶层(根)队列规则,并指定?default?类别编号

tc qdisc add dev eth0 root handle?1:?htb default?2

2)?定义第一层的?1:1?类别?(速度)本来是要多定义第二层叶类别,但目前来看,这个应用中就可以了.

tc class add dev eth0 parent 1:1 classid 1:2 htb rate 98mbit ceil 100mbit prio 2 
tc class add dev eth0 parent 1:1 classid 1:3 htb rate 1mbit ceil 2mbit prio 2

注:以上就是我们控制输出服务器的速度,一个为?98M,一个为?2M.
rate:?是一个类保证得到的带宽值.如果有不只一个类,请保证所有子类总和是小于或等于父类.prio:用来指示借用带宽时的竞争力,prio?越小,优先级越高,竞争力越强.
ceil: ceil?是一个类最大能得到的带宽值.

同时为了不使一个会话永占带宽,添加随即公平队列?sfq.
tc qdisc add dev eth0 parent?1:2?handle?2:?sfq perturb?10?tc qdisc

add dev eth0 parent 1:3 handle 3: sfq perturb 10

3)?设定过滤器
过滤器可以使用本身的?u32?也可以使用?iptables?来打上标记
指定在?root?类?1:0?中,对?192..168.0.2?的过滤,使用?1:2?的规则,来给他?98M?的速度,写法就如下

tc filter add dev eth0 protocol ip parent 1:0 u32 match ip src 192.168.0.2 flowid 1:2 
tc filter add dev eth0 protocol ip parent 1:0 u32 match ip src 192.168.0.1 flowid 1:3

如果是所有?ip?写法就如
tc filter add dev eth0 protocol ip parent?1:?prio?50?u32 match ip

dst 0.0.0.0/0?flowid?1:10使用?Iptables?来配合过滤器

还可以使用这个方法,但需要借助下面的?iptables?的命令来做标记了

tc filter add dev eth0 parent 1: protocol ip prio 1 handle 2 fw flowid 1:2 
tc filter add dev eth0 parent 1: protocol ip prio 1 handle 2 fw flowid 1:3

iptables?只要打上记号就行了

iptables -t mangle -A POSTROUTING -d 192.168.0.2 -j MARK --set-mark 10 iptables -t mangle -A POSTROUTING -d 192.168.0.3 -j MARK --set-mark 20

TC?对最对高速度的控制
Rate ceiling?速率限度
参数?ceil?指定了一个类可以用的最大带宽,?用来限制类可以借用多少带宽.缺省的?ceil?是和速率一样
这个特性对于?ISP?是很有用的,?因为他们一般限制被服务的用户的总量即使其他用户没有请求服务.(ISPS?很想用户付更多的钱得到更好的服务) ,注根类是不允许被借用的,?所以没有指定?ceil

注: ceil?的数值应该至少和它所在的类的速率一样高,?也就是说?ceil?应该至少和它的任何一个子类一样高

Burst?突发
网络硬件只能在一个时间发送一个包这仅仅取决于一个硬件的速率.?链路共享软件可以利用这个能力动态产生多个连接运行在不同的速度.?所以速率和?ceil?不是一个即时度量只是一个在一个时间里发送包的平均值.?实际的情况是怎样使一个流量很小的类在某个时间类以最大的速率提供给其他类. burst?和?cburst?参数控制多少数据可以以硬件最大的速度不费力的发送给需要的其他类.
如果?cburst?小于一个理论上的数据包他形成的突发不会超过?ceil?速率,?同样的方法?TBF?的最高速率也是这样.
你可能会问,?为什么需要?bursts .?因为它可以很容易的提高向应速度在一个很拥挤的链路上.比如?WWW?流量是突发的.?你访问主页.?突发的获得并阅读.?在空闲的时间?burst?将再"charge"一次.
注: burst?和?cburst?至少要和其子类的值一样大.

TC?命令格式:

加入

tc qdisc [ add | change | replace | link ] dev DEV [ parent qdisc-id | root ] [ handle qdisc-id ] qdisc[ qdisc specific parameters ]
tc class [ add | change | replace ] dev DEV parent qdisc-id [ classid class-id ] qdisc [ qdisc specificparameters ]

tc filter [ add | change | replace ] dev DEV [ parent qdisc-id | root ] protocol protocol prio priorityfiltertype [ filtertype specific parameters ] flowid flow-id

查看

tc [-s | -d ] qdisc show [ dev DEV ]
tc [-s | -d ] class show dev DEV tc filter show dev DEV

查看?TC?的状态
tc -s -d qdisc show dev eth0tc -s -d class show dev eth0

删除tc规则
tc qdisc del dev eth0 root

实例
使用?TC?下载限制单个?IP?进行速度控制

tc qdisc add dev eth0 root handle 1: htb r2q 1 
tc class add dev eth0 parent 1: classid 1:1 htb rate 30mbit ceil 60mbit 
tc  filter add dev eth0 parent 1: protocol ip prio 16 u32 match ip dst 192.168.1.2  flowid 1:1

就可以限制?192.168.1.2?的下载速度为?30Mbit?最高可以?60Mbit ,其中?r2q,是指没有?default?的root,使整个网络的带宽没有限制

使用?TC?对整段?IP?进行速度控制
tc qdisc add dev eth0 root handle?1:?htb r2q?1?tc class add dev

eth0 parent 1: classid 1:1 htb rate 50mbit ceil 1000mbit 
tc filter add dev eth0 parent 1: protocol ip prio 16 u32 match ip dst 192.168.111.0/24 flowid 1:1

就可以限制?192.168.111.0?到?255?的带宽为?3000k?了,实际下载速度为?200k?左右。这种情况下,这个网段所有机器共享这?200k?的带宽。
还可以加入一个?sfq(随机公平队列)

tc qdisc add dev eth0 root handle 1: htb r2q 1 
tc class add dev eth0 parent 1: classid 1:1 htb rate 3000kbit burst 10k 
tc qdisc add dev eth0 parent 1:1 handle 10: sfq perturb 10 
tc filter add dev eth0 parent 1: protocol ip prio 16 u32 match ip dst 192.168.111.168 flowid 1:1

sfq,他可以防止一个段内的一个?ip?占用整个带宽。使用?TC?控制服务器对外的速度为?10M

更多的例子,请看:?TC(Traffic Control)命令—linux自带高级流控

5.验证工具

[root@centos-linux sunsky]# ping -i.1 -c5 10.211.55.11

PING 10.211.55.11 (10.211.55.11) 56(84) bytes of data.

64 bytes from 10.211.55.11: icmp_seq=1 ttl=64 time=0.075 ms

64 bytes from 10.211.55.11: icmp_seq=2 ttl=64 time=0.135 ms

64 bytes from 10.211.55.11: icmp_seq=3 ttl=64 time=0.069 ms

64 bytes from 10.211.55.11: icmp_seq=4 ttl=64 time=0.071 ms

64 bytes from 10.211.55.11: icmp_seq=5 ttl=64 time=0.169 ms

 

--- 10.211.55.11 ping statistics ---

5 packets transmitted, 5 received, 0% packet loss, time 446ms

rtt min/avg/max/mdev = 0.069/0.103/0.169/0.042 ms

[root@centos-linux sunsky]# iperf -s  -p 1000

------------------------------------------------------------

Server listening on TCP port 1000

TCP window size:  128 KByte (default)

------------------------------------------------------------

[  4] local 10.211.55.11 port 1000 connected with 10.211.55.11 port 58816

[ ID] Interval       Transfer     Bandwidth

[  4]  0.0-10.0 sec  28.6 GBytes  24.5 Gbits/sec


[root@centos-linux sunsky]# iperf    -c 10.211.55.11 -p  1000 -l 10M

------------------------------------------------------------

Client connecting to 10.211.55.11, TCP port 1000

TCP window size: 2.76 MByte (default)

------------------------------------------------------------

[  3] local 10.211.55.11 port 58834 connected with 10.211.55.11 port 1000

[ ID] Interval       Transfer     Bandwidth

[  3]  0.0-10.0 sec  26.6 GBytes  22.8 Gbits/sec

参考:

https://netbeez.net/blog/how-to-use-the-linux-traffic-control/

http://codeshold.me/2017/01/tc_detail_inro.html

文章来源:https://blog.csdn.net/usoa/article/details/134846278
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。