Linux TC 流量控制介绍
前段时间在做一些测试的时候接触到了Linux tc,因为需要对数据包添加延迟,用到了tc中的netem。添加简单的延迟非常简单,像这样一条命令就搞定了:$ tc qdisc add dev eth0 root netem delay 1s
,你甚至不需要完全理解命令中参数的含义。但是当你想做一些更加特殊的限制的时候,(比如只对某个特定的ip端口添加延迟、或者只对入站的流量添加延迟),事情就变得有些棘手了,简单的百度貌似已经满足不了要求了。你不得不了解TC中的一些基本概念,以及tc[2]命令中相关参数的含义。
本文正是带你了解这些TC中的基本概念,并通过一个实际例子,将这些概念与tc命令联系起来。
本博客已迁移至CatBro's Blog,那是我自己搭建的个人博客,欢迎关注。本文链接
示例命令
考虑到这是一个科普向的介绍,这里只举了一个最简单的例子,但是基本上包含了重要的概念。本文的期望是,让读者在阅读后可以完全理解下面的例子,并且知道如何根据自身的需求编写自己的命令。
sudo tc qdisc add dev eth0 root handle 1: prio bands 4
sudo tc qdisc add dev eth0 parent 1:4 handle 40: netem loss 10% delay 40ms
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 4 u32 match ip dst 192.168.190.7 match ip dport 36000 0xffff flowid 1:4
TC基本概念
QDISCS
全称是queueing discipline,我们姑且称其为排队规则吧。它是协议栈和网络接口之间的一个缓冲层。你可以在qdisc上对数据包做一些你想做的操作,比如分类、整形、调度等。
qdisc分为无类(classless)qdisc和有类(classful)qdisc。无类qdisc不再内部细分类,有类qdisc可进一步包含多个分类,每个class上可以进一步包含子qdisc,子qdisc也可以是有类qdisc,这样就形成了树状的分层结构。
CLASSES
有类qdisc可以有多个子类(class),有些qdisc预定义了子类(如prio),有些则需要用户添加类。一个类上又可以附加其他类。最末端没有子类的类称为叶子类,它上面附加了一个qdisc。当创建一个class的时候,默认会附加一个fifo qdisc,它只是一个简单的队列,不对数据包进行任何的操作。当在这个类上增加子类的时候,这个默认的qdisc被移除。你可以将这个默认的fifo qdisc替换成其他任意你想用的qdisc。
FILTERS
过滤器,用于有类qdisc中,决定将包入队到哪个类中。每当一个包到达有子类的类时,就需要进行分类。其中一种分类的方法就是使用过滤器(另外两个是ToS和skb->priority)。所有附加到类上的过滤器会被依次调用,直到其中一个返回裁决。一个filter包含了一些条件,当一个包到达该节点时,会根据包的特征判断是否匹配。
以上3个是TC中最基本的3个概念,任何复杂的流量控制都是通过这个三元组递归实现的。
层级结构
每个接口有一个egress 'root qdisc',默认是pfifo_fast。每个qdisc和class都分配一个句柄handle,句柄用于在后续的配置语句中进行引用。除了egress qdisc,一个接口也可以有一个ingress qdisc,负责管制入站的流量。但是ingress qdisc相比classful qdisc其可能性是非常有限。(所以才有所谓的控发不控收,对入站流量进行控制通常需要借助ifb[6]或者imq)。
这些qdisc的handles有两个部分组成,一个major数和一个minor数:<major>:<minor>
。习惯上将root qdisc命名为1:
,等价于1:0
。一个qdisc的minor数总是0。
子类需要跟它们的parent有相同的major数。major数在一个egress或ingress内必须是唯一的,minor数在一个qdisc和它的class中必须是唯一的。
一个典型的层级结构如下:
1: root qdisc
|
1:1 child class
/ | \
/ | \
/ | \
/ | \
1:10 1:11 1:12 child classes
| | |
| 11: | leaf class
| |
10: 12: qdisc
/ \ / \
10:1 10:2 12:1 12:2 leaf classes
内核只跟root qdisc进行通信,每当包需要入队或者出队的时候,都需要从root节点开始,最终到达叶子节点,从而决定入队到哪里,或者从哪里出队。
比如当一个包入队时,它可能会经过如下路径:
1: -> 1:1 -> 1:12 -> 12: -> 12:2
当然也可能直接走如下路径:
1: -> 12:2
这种情况,就是root qdisc上的过滤器决定把包直接送到12:2
。
{% label warning@注意:%}入队和出队时虽然节点的拓扑图是一样的,但是每个节点表示的含义却有所不同[4]。入队时是根据过滤器和包的特征决定走哪条路径,而出队时则取决于qdisc本身的调度算法,比如FIFO、优先级队列、SFQ的顺序调度等。
过滤器
前面已经提到了过滤器用于将包分类到子类,那么具体是如何对包进行分类的呢?tc支持很多类型的分类器,它们根据数据包相关的不同信息来作出决策。其中最常用的就是u32分类器,它根据数据包中的字段做出决策(例如源IP地址等)。还有比如fw分类器,根据防火墙如何标记数据包来做出决策,你可以使用iptables标记目标数据包,然后通过fw分类器进行过滤。另外还有诸如route分类器、cgroup分类器、bpf分类器等,篇幅原因不再赘述。下面仅介绍最常见的u32分类器。
公共参数
分类器一般接收以下几个公共的参数:
protocol
分类器接受的协议,通常你只接受IP流量。必须。
parent
分类器附加到哪个handle上。这个handle必须是一个已经存在的类。必须。
prio|perf
分类器的优先级。数字越小的越先进行匹配尝试。
handle
这个handle对于不同的过滤器表示不同的含义。
u32分类器[3]
u32过滤器最简单的格式是设置一组选择器对包进行匹配,匹配的包分到特定的子类中,或者执行一个action。u32分类器提供了多种不同的选择器,可以大致分成特殊选择器和通用选择器两类。
特殊选择器
常用的有ip选择器和tcp选择器。特殊选择器简化了一些常用字段的设置,可以匹配包头中的各种字段,比如:
tc filter add dev eth0 protocol ip parent 1:0 prio 10 u32 \
match ip src 192.168.8.0/24 flowid 1:4
上例匹配ip源地址在192.168.8.0/24子网的包。
tc filter add dev eth0 protocol ip parent 1:0 prio 10 u32 \
match ip protocol 0x6 0xff \
match tcp dport 53 0xffff \
flowid 1:2
上例匹配TCP协议(0x6)、且目的端口为53的包。
通用选择器
特殊选择器总是可以改写成对应的通用选择器,通用选择器可以匹配 IP(或上层)头中的几乎任何位,不过相比特殊选择器较难编写和阅读。其语法如下:
match [ u32 | u16 | u8 ] PATTERN MASK at [OFFSET | nexthdr+OFFSET]
其中u32|u16|u8指定pattern的长度,分别为4个字节、2个字节、1个字节。PATTERN表示匹配的包的pattern,MASK告诉过滤器匹配哪些位,at表示从包的指定偏移处开始匹配。
来看一个例子:
tc filter add dev eth0 protocol ip parent 1:0 pref 10 u32 \
match u32 00100000 00ff0000 at 0 flowid 1:10
选择器会匹配IP头第二个字节为0x10的包,at 0
表示从头开始匹配,mask为00ff0000
所以只匹配第二个字节,pattern为00100000
即第二个字节为0x10。
再来看另一个例子:
tc filter add dev eth0 protocol ip parent 1:0 pref 10 u32 \
match u32 00000016 0000ffff at nexthdr+0 flowid 1:10
nexthdr
选项表示封装在IP包里的下一个头,即上层协议的头。at nexthdr+0
表示从下一个头第一个字节开始匹配。因为mask为0000ffff
,所以匹配发生在头的第三和第四个字节。在TCP和UDP协议中这两个字节是包的目的端口。数字是由大段格式给出的,所以pattern 00000016
转换成十进制是22。即该选择器会匹配目的端口为22的包。
示例解析
好了,现在我们可以回过头来看最初的那个示例了,看看这些命令到底是什么意思。
sudo tc qdisc add dev eth0 root handle 1: prio bands 4
sudo tc qdisc add dev eth0 parent 1:4 handle 40: netem loss 10% delay 40ms
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 4 u32 match ip dst 192.168.190.7 match ip dport 36000 0xffff flowid 1:4
我们一行行来看,第一行在设备eth0上添加了一个root qdisc,句柄为1:,qdisc类型为prio,bands数为4。
prio是一个有类的qdisc。它的作用跟默认的qdisc pfifo_fast类似。pfifo_fast有三个所谓的band,不同band的流量具有不同的优先级。每个band内,则应用FIFO规则。
prio qdisc,默认会创建3个子类,包含纯FIFO qdisc,默认根据ToS位进行分类。你可以使用过滤器来对流量进行分类,你也可以在子类上附加其他qdisc替换默认的FIFO。
接下来看第二个命令,parent 1:4
表示在子类1:4上,handle 40:
表示句柄为40:,netem
表示添加一个netem qdisc,loss 10% delay 40ms
则是netem的参数,表示丢包10%、延迟40ms。netem[5]是一个用于提供网络仿真功能的无类qdisc,可以模拟延迟、丢包、包重复、包失序等各种情况。
第三个命令则是添加了一个过滤器,parent 1:0
表示在根节点上添加该过滤器,prio 4
是过滤器的优先级,如果有很多过滤器会根据优先级的值按顺序进行尝试。u32
表示使用u32分类器。match ip dst 192.168.190.7
表示匹配ip地址为192.168.190.7的包,match ip dport 36000 0xffff
表示匹配目的端口为36000的包,多个选择器之间是“与”的关系,flowid 1:4
表示将匹配的包分类到1:4
子类中。
所以最终的效果是,发往192.168.190.7且目的端口为36000的包,会分类到1:4子类,添加40ms的延迟,且有10%的丢包率。其他包则还是默认的行为,即根据ToS字段分类到1:1、1:2或1:3子类中,然后根据优先级依次发送。
画出该例子的分层结构图,大致如下:
1: root qdisc (prio)
/ | \ \
/ | \ \
/ | \ \
1:1 1:2 1:3 1:4 classes
| | | |
40: qdiscs
pfifo pfifo pfifo netem
band 0 1 2 3
后记
本文只介绍了tc的基本概念和简单用法。prio qdisc只对包做了一个分类,并没有进行整形。实际上,你也可以使用更复杂的带整形的qdisc,比如CBQ、HTB等,也可以增加更多的层级。你还可以在叶子节点上添加SFQ qdisc以实现会话级的带宽公平性。相信理解了TC的这些基本概念,再根据自身需求使用其他qdisc也不是什么难事了。
参考资料
Linux TC 流量控制介绍的更多相关文章
- linux tc流量控制
tc流量控制 项目背景 vintage3.0接口lookupforupdage增加一个策略,当带宽流量tx或rx超过40%,75%随机返回304:超过60%,此接口均返回304 为了对测试机器进行流量 ...
- Linux TC流量控制HOWTO中文版
<本文摘自Linux的高级路由和流量控制HOWTO中文版 第9章节>网人郭工进行再次编译: 利用队列,我们可以控制数据发送的方式.记住我们只能对发送数据进行控制(或称为整形).其实,我们无 ...
- Linux内核策略介绍
Linux内核策略介绍学习笔记 主要内容 硬件 策略 CPU 进程调度.系统调用.中断 内存 内存管理 外存 文件IO 网络 协议栈 其他 时间管理 进程调度 内核的运行时间 系统启动.中断发 ...
- Linux实战教学笔记07:Linux系统目录结构介绍
第七节 Linux系统目录结构介绍 标签(空格分隔):Linux实战教学笔记 第1章 前言 windows目录结构 C:\windows D:\Program Files E:\你懂的\精品 F:\你 ...
- Linux的简单介绍和常用命令的介绍
Linux的简单介绍和常用命令的介绍 本说明以Ubuntu系统为例 Ubuntu系统的安装自行百度,或者参考http://www.cnblogs.com/CoderJYF/p/6091068.html ...
- Linux性能工具介绍
l Linux性能工具介绍 p CPU高 p 磁盘I/O p 网络 p 内存 p 应用程序跟踪 l 操作系统与应用程序的关系比喻为“唇亡齿寒”一点不为过 l 应用程序的性能问题/功能问 ...
- Linux core 文件介绍
Linux core 文件介绍 http://www.cnblogs.com/dongzhiquan/archive/2012/01/20/2328355.html 1. core文件的简单介绍在一个 ...
- Linux 启动参数介绍
Linux 启动参数介绍 取自2.6.18 kernel Documentation/i386/boot.txt 文件中介绍 vga= 这里的不是一个整数(在C语言表示法中,应是十进制,八进制或者十六 ...
- Linux系统启动过程介绍
Linux系统启动过程介绍 学习操作系统有必要了解一下系统的启动过程,这样在面对各种系统故障的时候能快速定位解决问题,下面以Centos来分析linux系统的启动过程. 1.BIOS自检:当开机的时候 ...
随机推荐
- 大白话讲解IOC和AOP
IOC和AOP 什么是IOC IoC(Inversion of control)控制反转,它是一种思想,而Spring Framework实现了这一思想.Ioc也称为依赖注入(DI). IOC控制反转 ...
- 在VMware上安装Linux虚拟机
1.新建虚拟机 2.选择典型安装 3.点击稍后安装操作系统 4.选择类型和版本 5.选择一个英文路径 6. 7.调整硬件 8. 9. 10.选择第一项 11.选择中文 12.选择最小安装 13. 14 ...
- C++ 反汇编:关于函数调用约定
函数是任何一门高级语言中必须要存在的,使用函数式编程可以让程序可读性更高,充分发挥了模块化设计思想的精髓,今天我将带大家一起来探索函数的实现机理,探索编译器到底是如何对函数这个关键字进行实现的,并使用 ...
- suse 12 编译部署 Nginx
文章目录 编译前准备 创建nginx用户 下载nginx源码包 安装编译环境依赖 编译nginx 配置nginx为systemctl管理 Linux:~ # cat /etc/os-release N ...
- 上架打包错误:error itms-90086
这是一个很纠结的错误 大家第一反应肯定是 赶紧去看看 位数是否设置 然后发现没有问题 就开始懵逼了 (比如我) 然而无意看到了一个人写的简书 这个人在 Overflow 找到了一个答案 比如你选择 ...
- web安全之备份
1:打开界面,一头雾水.根据题目提示"备份是个好习惯"可以想到,这应该是一个代码泄露问题.常见的网页主页index.php.那么备份文件一般是.bak文件类型.尝试下载该文件 in ...
- IP网络主动测评系统——IT运维人员的好帮手
一.前 言 随着计算机网络的普及和快速发展,互联网已经融入到人们的衣食住行等方方面 面,如工作.购物.音视频聊天.视频会议.朋友圈.抖音.在线网游.网络电影 电视等.毫不夸张地说,现如今大部分人的绝大 ...
- bi报表是什么意思,有什么优势?
BI也叫商业智能系统,BI报表也就是将企业中现有数据进行整合并提供出的报表,商业智能描述了一系列的概念和方法,通过应用基于事实的支持系统来辅助商业决策的制定. 商业智能技术提供使企业迅速分析数据的技 ...
- 谁说EXCEL不能处理大数据?那是你用错了工具
我是一名数据分析师,每天需要和各种各样的数据和表格打交道,是一名名副其实的"表哥",不仅需要制作和更新公司里的日报.周报和月报,有时候也要为公司的会议准备各种数据材料.由于公司的业 ...
- Linux Docker虚拟机入门实战讲解
什么是Docker? Docker是基于Go语言实现的云开源项目,诞生于2013年初,最初发起者是dotCloud公司.Docker自开源后受到广泛的关注和讨论,目 前已有多个相关项目,逐渐形成了围绕 ...