概述
TC和QoS
- 1 流量控制(Traffic Control)
- 1.1 TC工作原理
- 1.2 TC的三个组成
- 1.2.1 Qdisc-无类队列和有类队列
- 1.2.2 过滤器
- 1.2.3 类别
- 1.3 基本命令
- 1.3.1 TBF操作实例
- 1.3.2 CBQ操作实例
- 1.3.3 HTB操作实例
- 1.3.4 监视
- 1.3.5 维护
- 2 服务质量(Quality of Service)
- 2.1 概念
- 2.2 服务模型
- 2.2.1 Best-Effort服务模型
- 2.2.2 IntServ服务模型
- 2.2.3 Differ服务模型
- 2.3 技术背景
1 流量控制(Traffic Control)
最简单的流量控制往往是通过采集速率,在超过指定速率后丢弃数据包,但这种方案并不能将流量控制在指定速率,还会导致传输质量的较大损失。Linux内核内置了一个TC(流量控制)框架,主要实现流量限速、流量整形和策略应用(策略包括丢弃、NAT等)。在输出端口处建立一个队列,基于目的IP地址或目的子网的网络号,将需要延迟发送的数据包缓冲在队列中,并在合适的时间发送出去。因此,TC主要有三个要素:
- Qdisc(Queue discipline)队列规定
- filter 过滤器
- class 类别
1.1 TC工作原理
数据包在经过网卡后,按需求经过过滤器后被存入不同叶子队列中。
Linux在实现TC的时候,对队列进行了抽象,基本维护了两个回调函数指针,分别是入队(enqueue)操作和出队(dequeue)操作。对于叶子节点队列,进行数据包的入队和出队;对于非叶子节点的队列来说,并没有真正的数据包排入或排出,而是递归调用其它抽象队列的相应入队和出队操作。
1.2 TC的三个组成
1.2.1 Qdisc-无类队列和有类队列
无类队列(CLASSLESS QDISC):对进入网络设备(网卡)的数据流不加以区分,统一对待的队列规定。
有类队列(CLASSFUL QDISC):对进入网络设备(网卡)的数据包根据不同的需求,以分类的方式区别对待的队列规定。有类队列包括CBQ(Class Based Queueing,基于类别队列)、HTB(Hierarchy Token Bucket,分层令牌桶队列)和PRIO(优先级队列):
- CBQ:实现了一个丰富的连接共享类别结构,既有限制带宽的能力,也具有带宽优先级别管理的能力。
- HTB:实现了一个丰富的连接共享类别结构,可以很容易地保证每个类别的带宽,虽然它也允许特定的类可以突破带宽上限,占用别的类的带宽。HTB可以通过TBF(Token Bucket Filter)实现带宽限制,也能够划分类别的优先级。
- PRIO:很容易管理流量的优先级,但限制不能限制带宽,因为属于不同类别的数据包是顺序离队的。只有属于高优先级类别的数据包全部发送完毕,才会发送属于低优先级类别的数据包。
CBQ与HTB相比,HTB更佳。基于令牌桶算法能够在限制数据的平均传输速率的同时,还允许某种程度的突发传输。
令牌桶算法:
#include <iostream>
#include <atomic>
#include <ctime>
#include <time.h>
class TokenBucket {
typedef enum color{
GREEN,
RED
}COLOR;
private :
int m_cir; // 添加令牌的速率
int m_cbs; // 桶的容量
std::atomic<int64_t> m_clsLastUpdateTime; // 上次桶内令牌数更新时间
std::atomic<int64_t> m_clsCurTokenNum; // 当前桶内令牌数
// 毫秒级时间,不够用可以自己重写
int64_t _get_cur_time() {
return clock();
}
public:
TokenBucket(int cir, int cbs) {
m_cir = cir;
m_cbs = cbs;
m_clsLastUpdateTime = _get_cur_time();
}
~TokenBucket() {}
/************************
数据包处理函数
参数:token, 数据包大小
返回值:RED, 惩罚处理
GREED, 放行
************************/
COLOR packetProcess(int token) {
int64_t nowTime;
int64_t timeInterval;
int64_t updateTokenNum;
int64_t curTokenNum = m_clsCurTokenNum.load();
if (token <= curTokenNum) {
m_clsCurTokenNum.fetch_sub(token);
return GREEN;
}
nowTime = _get_cur_time();
timeInterval = nowTime - m_clsLastUpdateTime.load();
updateTokenNum = timeInterval * m_cir + curTokenNum;
if (updateTokenNum < token) {
return RED;
}
else {
updateTokenBucket(nowTime, updateTokenNum);
}
m_clsCurTokenNum.fetch_sub(token);
return GREEN;
}
/************************
更新令牌桶内的时间以及数量
参数:time, 更新时间
num, 数量
返回值:void
************************/
void updateTokenBucket(int64_t time, int64_t num) {
m_clsLastUpdateTime.store(time);
m_clsCurTokenNum.store(num);
}
};
代码来源:令牌桶算法原理及实现
1.2.2 过滤器
过滤器(filter)是用于对数据包进行分类的工具。
- u32过滤器:源/目的IP地址,源/目的端口,协议类型,服务类型(TOS)
sudo tc filter add dev ens33 parent 1:0 protocol ip prio 1 u32 match ip src 192.168.79.131 flowid 1:1 #源IP地址
sudo tc filter add dev ens33 parent 1:0 protocol ip prio 1 u32 match ip dst 192.168.79.131 flowid 1:1 #目的地址
sudo tc filter add dev ens33 parent 1:0 protocol ip prio 1 u32 match ip sport 80 0xffff flowid 1:1 #源端口
sudo tc filter add dev ens33 parent 1:0 protocol ip prio 1 u32 match ip dport 80 0xffff flowid 1:1 #目的端口
sudo tc filter add dev ens33 parent 1:0 protocol ip prio 1 u32 match ip protocol 1 0xffff flowid 1:1 #根据/etc/protocols来决定协议号
sudo tc filter add dev ens33 parent 1:0 protocol ip prio 1 u32 match ip tos 0x10 0xff flowid 1:1 #选择交互和最小延迟的数据流,匹配大量传输
- 根据iptables的标记fwmark进行过滤
sudo iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6
sudo tc filter add dev ens33 protocol ip parent 1:0 prio 1 handle 6 fw flowid 1:1
- 根据路由,具体可见下一节中的操作实例。
1.2.3 类别
类(class)组成一个树,每个类都只有一个父类,而一个类可以有多个子类。
1.3 基本命令
1.3.1 TBF操作实例
sudo tc qdisc add dev ens33 handle 1: root tbf rate 100Mbit burst 100Kbit limit 200Mbit
Size: 168.9M Time: 14.19s Speed: 11.35MB/s
1.3.2 CBQ操作实例
虚拟机 | IP地址 |
---|---|
18.04(Server) | 192.168.79.131 |
16.04 | 192.168.79.129 |
16.04_1 | 192.168.79.132 |
- 针对网络物理设备(网卡ens33)绑定队列,针对一个网卡只需要建立一个队列:
tc qdisc add dev ens33 root handle 1: cbq bandwidth 10Mbit avpkt 1000 cell 8 mpu 64
将一个cbq队列绑定到网络物理设备ens33上,其编号为1:0;网络物理设备eth0的实际带宽为10Mbit,包的平均大小为1000字节;包间隔发送单元的大小为8字节,最小传输包大小为64字节。
- 针对一个队列需建立一个根分类,对于分类,按其分类的编号顺序起作用,编号小的优先;一但符合某个分类匹配规则,通过该分类发送数据包,则其后的分类不在起作用:
tc class add dev ens33 parent 1:0 classid 1:1 cbq bandidth 10Mbit rate 10Mbit maxburst 20 allot 1514 prio 8 avpkt 1000 cell 8 weight 1Mbit
该队列的最大可用带宽为10Mbit,实际分配的带宽为10Mbit,可接收冲突的发送最长包数目为20字节;最大传输单元加MAC头的大小为1514字节,优先级别为8,包的平均大小为1000字节,包间隔发送单元的大小为8字节,相当于实际带宽的加权速率为1Mbit。
- 在根分类里建立子分类1:2:
tc class add dev ens33 parent 1:1 classid 1:2 cbq bandwidth 10Mbit rate 8Mbit maxburst 20 allot 1514 prio 2 avpkt 1000 cell 8 split 1:0 bounded
该队列的最大可用带宽为10Mbit,实际分配的带宽为8Mbit,可接收冲突的发送最长包数目为20字节;最大传输单元加MAC头的大小为1514字节,优先级别为2,包的平均大小为1000字节,包间隔发送单元的大小为8字节,相当于实际带宽的加权速率为800Kbit,分类的分离点为1:0,且不可借用未使用带宽。
在根分类里建立子分类1:3:
tc class add dev ens33 parent 1:1 classid 1:3 cbq bandwidth 10Mbit rate 2Mbit maxburst 20 allot 1514 prio 1 avpkt 1000 cell 8 split 1:0
该队列的最大可用带宽为10Mbit,实际分配的带宽为2Mbit,可接收冲突的发送最长包数目为20字节;最大传输单元加MAC头的大小为1514字节,优先级别为1,包的平均大小为1000字节,包间隔发送单元的大小为8字节,相当于实际带宽的加权速率为200Kbit,分类的分离点为1:0。
- 为每一次分类建立一个过滤器,并为每一个分类建立一个路由映射:
tc filter add dev eth0 parent 1:0 protocol ip prio 100 route to 2 flowid 1:2
tc filter add dev eth0 parent 1:0 protocol ip prio 100 route to 3 flowid 1:3
- 与过滤器相配合,建立特定的路由表:
ip route add 192.168.79.129 dev eth0 via 192.168.79.131 realm 2
发往主机192.168.79.129的数据包通过分类2转发(分类2的速率8Mbit)。
ip route add 192.168.79.132 dev eth0 via 192.168.79.131 realm 3
发往主机192.168.79.132的数据包通过分类3转发(分类3的速率1Mbit)。
- 通过由两个FTP客户机分别从服务器下载同一个168.9M的文件,通过改变参数得到以下限速结果:
Situation | Name | Time | Speed |
---|---|---|---|
未设置TC | 16.04 | 0.86s | 187MB/s |
未设置TC | 16.04_1 | 0.61s | 263MB/s |
8Mbit bounded | 16.04 | 164s | 1004KB/s |
5Mbit bounded | 16.04 | 270s | 610KB/s |
8Mbit | 16.04 | 0.98s | 164MB/s |
2Mbit | 16.04_1 | 1.14s | 141MB/s |
8Mbit = 8192Kbit/s = 1024 KB/s
5Mbit = 640KB/s
1.3.3 HTB操作实例
步骤大致如上一节,不赘述。
sudo tc qdisc add dev ens33 root handle 1: htb
sudo tc class add dev ens33 parent 1: classid 1:1 htb rate 10Mbit ceil 10Mbit
sudo tc class add dev ens33 parent 1:1 classid 1:2 htb rate 8Mbit ceil 8Mbit
sudo tc class add dev ens33 parent 1:1 classid 1:2 htb rate 2Mbit ceil 10Mbit
sudo tc filter add dev ens33 protocol ip parent 1:0 prio 1 u32 match ip dst 192.168.79.129 flowid 1:2
sudo tc filter add dev ens33 protocol ip parent 1:0 prio 1 u32 match ip dst 192.168.79.132 flowid 1:3
同样由两个FTP客户机分别从服务器下载同一个168.9M的文件,通过改变参数得到以下限速结果:
Situation | Name | Time | Speed |
---|---|---|---|
未设置TC | 16.04 | 0.86s | 187MB/s |
未设置TC | 16.04_1 | 0.61s | 263MB/s |
rate 8 ceil 8 | 16.04 | 176s | 933KB/s |
rate 2 ceil 10 | 16.04_1 | 141s | 1.14MB/s |
rate 2 ceil 2 | 16.04_1 | 706s | 233KB/s |
2Mbit = 256KB/s
10Mbit = 1.25MB/s
1.3.4 监视
主要包括对队列、分类、过滤器和路由状况进行监视。
对队列、分类和过滤器的监视:
tc (-s) qdisc/class/filter ls dev eth0
对路由情况的监视:
ip route
1.3.5 维护
主要包括对队列、分类、过滤器和路由的增添、修改和删除。
增添动作一般依照 队列 -> 分类 -> 过滤器 -> 路由 的顺序进行;修改动作则没有什么要求;删除则依照路由 -> 过滤器 -> 分类 -> 队列 的顺序进行。
2 服务质量(Quality of Service)
2.1 概念
QoS现指解决网络延迟和阻塞等问题的一种技术,用于区分流量,保证高优先级带宽的要求与网络质量。QoS技术本身不会增加网络带宽,而是在有限的带宽资源下,如何平衡地为各种业务分配带宽,针对不同需求,为业务提供端到端的服务质量保证。实现QoS的一个最基本的方法就是分类和标记。
一个QoS策略包含一个或多个限速规则,一个限速规则包含一个或多个流分类规则。QoS通过流分类划分流量,并根据配置的限速规则的优先级保证高优先级限速下的带宽。
影响网络服务质量的因素,也就成为QoS的度量指标,包括带宽、时延和抖动。
2.2 服务模型
2.2.1 Best-Effort服务模型
Best-Effort是最简单也是最早出现的QoS服务模型。在这种模型中,网络中的设备上除了保证网络之间路由可达之外,不需要部署额外的功能。应用程序可以在任何时候发出任意数量的报文,而且不需要通知网络。网络只是尽最大的可能性来发送报文,但对时延、可靠性等性能不提供任何保证。
在理想状态下,如果有足够的带宽,Best-Effort是最简单的服务模式。而实际上,这种“简单“带来一定的限制。因此,Best-Effort适用于对时延、可靠性等性能要求不高的业务,如FTP、E-Mail等。
2.2.2 IntServ服务模型
InterServ模型下,网络需要为某个业务预留一条专用通道。这种资源预留的状态称为“软状态”。为了保证这条通道不被占用,RSVP会定期发送大量协议报文进行探测。通过RSVP,各网元可以判断是否有足够的资源可以预留。只有所有的网元都预留了足够的资源,专用通道方可建立。
2.2.3 Differ服务模型
DiffServ服务模型,也叫差分服务模型,意思就是提供有差别的服务。DiffServ模型中,网络中的流量可以根据多种条件被分成多个类,或者标记不同的优先级。当网络出现拥塞时,不同的类会享受不同的优先处理,从而实现差分服务。同一类的业务在网络中会被聚合起来统一发送,保证相同的延迟、抖动、丢包率等QoS指标。
报文分类是基础,是有区别地实施服务的前提,流量监管、流量整形和接口限速主要用于预防拥塞,拥塞管理和拥塞避免是用来解决拥塞。
2.3 技术背景
QoS Workflow:
当数据包进入设备后,它依次经过标记、计量、管制、重分类、队列、整形以及优先级调度。
分类:将数据分为不同类别,不会修改原来的数据包;
标记:将数据设置为不同的优先级,会修改原来的数据包;
计量:通过漏桶算法或令牌桶算法实现,计量后的数据包会根据不同的整形类别分别保存在缓冲区中,待满足对应的要求后再发送;
管制:丢弃超出带宽的数据包;
整形:将超出带宽的数据包缓存在内存中,限制流出某一网络的某一连接的流量与突发,使这类报文以比较均匀的速度向外发送;
队列:当网络发生拥塞后,数据还是要被传递的,依照什么样的方式来传数据,就需要队列的指导。
最后
以上就是典雅鲜花为你收集整理的Linux下的流量控制(TC)和服务质量(QoS)1 流量控制(Traffic Control)2 服务质量(Quality of Service)的全部内容,希望文章能够帮你解决Linux下的流量控制(TC)和服务质量(QoS)1 流量控制(Traffic Control)2 服务质量(Quality of Service)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复