文章目录

  • 1 前言
  • 2 相关概念
  • 3 使用TC
  • 4 创建HTB队列
  • 5 为根队列创建相应的类别
  • 6 为各个类别设置过滤器
  • 7 复杂的实例

Linux 下 TC 命令原理及详解<一>
Linux 下 TC 命令原理及详解<二>
Linux 下 TC 命令原理及详解<三>
Linux 下 TC 命令原理及详解<四>
Linux 下 TC 命令原理及详解<五>

该系统文章由 Linux tc QOS 详解 这篇文章整理而得,目前还未对内容和脚本进行检验和测试,后续将会进行一些测试和完善。

1 前言

众所周知,在互联网诞生之初都是各个高校和科研机构相互通讯,并没有网络流量控制方面的考虑和设计,IP协议的原则是尽可能好地为所有数据流服务,不同的数据流之间是平等的。

然而多年的实践表明,这种原则并不是最理想的,有些数据流应该得到特别的照顾,比如,远程登录的交互数据流应该比数据下载有更高的优先级。

针对不同的数据流采取不同的策略,这种可能性是存在的。并且,随着研究的发展和深入,人们已经提出了各种不同的管理模式。IETF已经发布了几个标准, 如综合服务(Integrated Services)、区分服务(Diferentiated Services)等。

其实,Linux内核从2.2开始,就已经实现了相关的流量控制功能。

本文将介绍Linux中有关流量控制的相关概念,用于流量控制的工具TC的使用方法,并给出几个有代表性实例。

2 相关概念

由此可以看出,报文分组从输入网卡(入口)接收进来,经过路由的查找,以确定是发给本机的,还是需要转发的。如果是发给本机的,就直接向上递交给上层的协议,比如TCP,如果是转发的,则会从输出网卡(出口)发出。

网络流量的控制通常发生在输出网卡处。虽然在路由器的入口处也可以进行流量控制,Linux也具有相关的功能,但一般说来,由于我们无法控制自己网络之外的设备,入口处的流量控制相对较难。本文将集中介绍出口处的流量控制。

流量控制的一个基本概念是队列(Qdisc),每个网卡都与一个队列(Qdisc)相联系,每当内核需要将报文分组从网卡发送出去,都会首先将该报文分组添加到该网卡所配置的队列中,由该队列决定报文分组的发送顺序。因此可以说,所有的流量控制都发生在队列中,详细流程图见图1。

图1 报文在Linux内部流程图

有些队列的功能是非常简单的,它们对报文分组实行先来先走的策略。有些队列则功能复杂,会将不同的报文分组进行排队、分类,并根据不同的原则,以不同的顺序发送队列中的报文分组。为实现这样的功能,这些复杂的队列需要使用不同的过滤器(Filter)来把报文分组分成不同的类别(Class)。这里把这些复杂的队列称为可分类(ClassfuI)的队列。

通常, 要实现功能强大的流量控制,可分类的队列是必不可少的。因此,类别(class)和过滤器(Filter)也是流量控制的另外两个重要的基本概念。图2所示的是一个可分类队列的例子。

图2 多类别队列

由图2可以看出,类别(CIass)和过滤器(Filter)都是队列的内部结构,并且可分类的队列可以包含多个类别,同时,一个类别又可以进一步包含有子队列,或者子类别。所有进入该类别的报文分组可以依据不同的原则放入不同的子队列或子类别中,以此类推。而过滤器(Filter)是队列用来对数据报文进行分类的工具,它决定一个数据报文将被分配到哪个类别中。

3 使用TC

在Linux中,流量控制都是通过TC这个工具来完成的。通常,要对网卡进行流量控制的配置,需要进行如下的步骤:

  • 为网卡配置一个队列;
  • 在该队列上建立分类;
  • 根据需要建立子队列和子分类;
  • 为每个分类建立过滤器。

在Linux中,可以配置很多类型的队列,比如CBQ、HTB等,其中CBQ 比较复杂,不容易理解,HTB(HierarchicaIToken Bucket)是一个可分类的队列,与其他复杂的队列类型相比,HTB具有功能强大、配置简单及容易上手等优点。在TC 中, 使用”major:minor”这样的句柄来标识队列和类别,其中major和minor都是数字。

对于队列来说,minor总是为0,即 "major:0" 这样的形式,也可以简写为 "major:" 比如,队列1:0可以简写为1:。需要注意的是,major在一个网卡的所有队列中必须是惟一的。对于类别来说,其major必须和它的父类别或父队列的major相同,而minor在一个队列内部则必须是惟一的(因为类别肯定是包含在某个队列中的)。举个例子,如果队列2:包含两个类别,则这两个类别的句柄必须是2:x这样的形式,并且它们的x不能相同,比如2:1和2:2。

下面,将以HTB队列为主,结合需求来讲述TC的使用。假设eth0出口有100Mbit/s的带宽,分配给WWW 、E-mail和Telnet三种数据流量,其中分配给WWW的带宽为40Mbit/s,分配给Email的带宽为40Mbit/s,分配给Telnet的带宽为20Mbit/s。

需要注意的是, 在TC 中使用下列的缩写表示相应的带宽:

  • Kbps:kiIobytes per second,即 “千字节每秒”
  • Mbps:megabytes per second,即 “兆字节每秒 ”
  • Kbit:kilobits per second,即 “千比特每秒”
  • Mbit:megabits per second,即 “兆比特每秒”

4 创建HTB队列

有关队列的TC命令的一般形式为:

# tc qdisc [add|change|replace|link] dev DEV [parent qdisk-id|root][handle qdisc-id] qdisc[qdisc specific parameters]

首先,需要为网卡eth0配置一个HTB队列,使用下列命令:

# tc qdisc add dev eth0 root handle 1: htb default 11

各项的含义:

  • add 表示要添加
  • dev eth0 表示要操作的网卡为eth0
  • root 表示为网卡eth0添加的是一个根队列
  • handle 1: 表示队列的句柄为1:
  • htb 表示要添加的队列为HTB队列
  • default 11 是htb特有的队列参数,意思是所有未分类的流量都将分配给类别1:11

5 为根队列创建相应的类别

有关类别的TC 命令的一般形式为:

# tc class [add|change|replace] dev DEV parent qdisc-id [classid class-id] qdisc [qdisc specific parameters]

可以利用下面这三个命令为根队列1创建三个类别,分别是1:11、1:12和1:13,它们分别占用40、40和20mbit的带宽。

# tc class add dev eth0 parent 1: classid 1:11 htb rate 40mbit ceil 40mbit
# tc class add dev eth0 parent 1: classid 1:12 htb rate 40mbit ceil 40mbit
# tc class add dev eth0 parent 1: classid 1:13 htb rate 20mbit ceil 20mbit

各项的含义:

  • parent 1: 表示类别的父亲为根队列1:
  • classid 1:11 表示创建一个标识为1:11的类别
  • rate 40mbit 表示系统将为该类别确保带宽40mbit
  • ceil 40mbit 表示该类别的最高可占用带宽为40mbit

6 为各个类别设置过滤器

有关过滤器的TC 命令的一般形式为:

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

由于需要将WWW、E-mail、Telnet三种流量分配到三个类别,即上述1:11、1:12和1:13,因此,需要创建三个过滤器,如下面的三个命令:

# tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 80 0xffff flowid 1:11
# tc filter add dev eth0 prtocol ip parent 1:0 prio 1 u32 match ip dport 25 0xffff flowid 1:12
# tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 23 oxffff flowid 1:13

各项的含义:

  • protocol ip 表示该过滤器应该检查报文分组的协议字段
  • prio 1 表示它们对报文处理的优先级是相同的,对于不同优先级的过滤器,系统将按照从小到大的优先级顺序来执行过滤器,对于相同的优先级,系统将按照命令的先后顺序执行
  • 这几个过滤器还用到了u32选择器(命令中u32后面的部分)来匹配不同的数据流。以第一个命令为例,判断的是dport字段,如果该字段与Oxffff进行与操作的结果是80,则 flowid 1:11 表示将把该数据流分配给类别1:11

更加详细的有关TC的用法可以参考TC 的手册页。

7 复杂的实例

在上面的例子中,三种数据流(www、Email、Telnet)之间是互相排斥的。当某个数据流的流量没有达到配额时,其剩余的带宽并不能被其他两个数据流所借用。在这里将涉及如何使不同的数据流可以共享一定的带宽。

首先需要用到HTB的一个特性,即对于一个类别中的所有子类别,它们将共享该父类别所拥有的带宽,同时,又可以使得各个子类别申请的各自带宽得到保证。这也就是说,当某个数据流的实际使用带宽没有达到其配额时,其剩余的带宽可以借给其他的数据流。而在借出的过程中,如果本数据流的数据量增大,则借出的带宽部分将收回,以保证本数据流的带宽配额。

下面考虑这样的需求,同样是三个数据流WWW、E-mail和Telnet,其中的Telnet独立分配20Mbit/s的带宽。另一方面,WWW 和SMTP各自分配40Mbit/s。同时,它们又是共享的关系,即它们可以互相借用带宽。如图3所示:

图3

需要的TC命令如下:

# tc qdisc add dev eth0 root handle 1: htb default 21# tc class add dev eth0 partent 1: classid 1:1 htb rate 20mbit ceil 20mbit# tc class add dev eth0 parent 1: classid 1:2 htb rate 80mbit ceil 80mbit# tc class add dev eth0 parent 1: classid 1:21 htb rate 40mbit ceil 20mbit# tc class add dev eth0 parent 1:2 classid 1:22 htb rate 40mbit ceil 80mbit# tc filter add dev eth0 protocol parent 10 prio 1 u32 match ip dport 80 0xffff flowid 1:21# tc filter add dev eth0 protocol parent 1:0 prio 1 u32 match ip dport 25 0xffff flowid 1:22# tc filter add dev eth0 protocol parent 1:0 prio 1 u32 match ip dport 23 0xffff flowid 1:1

这里为根队列1创建两个根类别,即1:1和1:2,其中1:1对应Telnet数据流,1:2对应80Mbit的数据流。然后,在1:2中,创建两个子类别1:21和1:22,分别对应WWW和E-mail数据流。由于类别1:21和1:22是类别1:2的子类别,因此他们可以共享分配的80Mbit带宽。同时,又确保当需要时,自己的带宽至少有40Mbit。

从这个例子可以看出,利用HTB中类别和子类别的包含关系,可以构建更加复杂的多层次类别树,从而实现的更加灵活的带宽共享和独占模式,达到企业级的带宽管理目的。

Linux 下 TC 命令原理及详解<一>相关推荐

  1. Linux 下 TC 命令原理及详解

    众所周知,在互联网诞生之初都是各个高校和科研机构相互通讯,并没有网络流量控制方面的考虑和设计,IP协议的原则是尽可能好地为所有数据流服务,不同的数据流之间是平等的.然而多年的实践表明,这种原则并不是最 ...

  2. Linux 下 TC 命令原理及详解<四>

    tc 由 Alexey N. Kuznetsov 编写,从 Linux 2.2 版开始并入 Linux 内核. Linux 从 kernel 2.1.105 开始支持 QoS,不过,需要重新编译内核. ...

  3. Linux下fdisk命令操作磁盘详解--添加、删除、转换分区

    linux下fdisk命令操作磁盘详解--添加.删除.转换分区等 fdisk 操作硬盘的命令格式如下: [root@localhost beinan]# fdisk 设备 比如我们通过 fdisk - ...

  4. linux命令引用,Linux下nl命令的用法详解

    Linux中nl命令和cat命令很像,不过nl命令会打上行号,属于比较不常用的命令,下面随小编一起来了解下这个鲜为人知的nl命令吧. nl命令在linux系统中用来计算文件中行号.nl 可以将输出的文 ...

  5. Linux下SSH命令使用方法详解

    1.查看SSH客户端版本 有的时候需要确认一下SSH客户端及其相应的版本号.使用ssh -V命令可以得到版本号.需要注意的是,Linux一般自带的是OpenSSH: 下面的例子即表明该系统正在使用Op ...

  6. Linux 下 top 命令的使用详解

    前言: top 指令用于查看当前CPU负载, 内存占用. 或让其一直打印到固定文件内, 用于以后查看 版本: 本次 top 的版本为version 3.3.10, 系统版本为centos 7.4 使用 ...

  7. linux下grep命令用法,全面详解linux下grep命令的用法

    学linux系统,grep这个命令是必须要掌握的.grep命令是用来查找文件或标准输出中匹配的行,它的强大之处在于它支持正则表达式.日常工作中,grep绝对是用的最多的命令之一. 注:本文只介绍gre ...

  8. linux part用法,Linux下partprobe命令的使用详解

    linux上,在安装系统之后,可否创建分区并且在不重新启动机器的情况下系统能够识别这些分区? 解决方法: 你可以使用一个叫做partprobe的工具.它包含在parted的rpm软件包中.在Red H ...

  9. Linux下find命令的使用详解

    1,什么是find? 从英文字面意思上就是:查找,查询的意思,不错,这就是Linux系统功能强大的文件查找命令find 2,find命令的具体使用方法 命令格式:find [options] [查找路 ...

最新文章

  1. Chart.js-雷达图分析(参数分析+例图)
  2. python精通-11周精通python计划(完结)-网易云课堂
  3. 常用的相似性度量(距离总结)
  4. php mysql 内存溢出_关于MySQL的整型数据的内存溢出问题的应对方法_MySQL
  5. choiceformat_ChoiceFormat:数字范围格式
  6. oc 画一个圆弧_UG建模一个蜗杆的方法,纯手工建模无插件
  7. 对于Python函数与方法,你可能存在些误解
  8. 看门狗超时前在内核打印信息
  9. filter的作用 一
  10. 求定积分 c++实现
  11. 网站优化 14条--雅虎十四条优化原则
  12. 基恩士KEYENCE激光打标机控制器维修ML-9110详解
  13. 【测试】史上最详细的测试用例设计方法讲解
  14. C/C++和Lua混合编程
  15. 修改UE4的缓存路径
  16. 数据赋能,助力新零售数字化突围
  17. Driller源码阅读笔记(一)
  18. csp试题2:小明种苹果(绪)
  19. String类菜鸟级教程(字符串常量池及不可变,StringBuffer 和 StringBuilder)
  20. centos 怎么退出init 3_CentOS 7.3:LAMP 动静分离部署

热门文章

  1. HTML5制作一个笑脸
  2. 信息安全 SEED Lab10 Packet Sniffing and Spoofing Lab
  3. 针对linux系统中/usr/src/kernels中找不到内核源码的问题
  4. 督办管理系统——让企业工作落实到位
  5. java.lang.IllegalStateException: Cannot get a text value from a numeric cell
  6. CUDA软件架构—网格(Grid)、线程块(Block)和线程(Thread)的组织关系以及线程索引的计算公式
  7. 《用户体验要素》笔记
  8. H3C AP状态指示灯
  9. 从php角度分析预防xss和Sql注入
  10. STM32定时器输入捕获,脉宽测量知识点