Linux流量控制TC中的HTB队列创建与过滤

众所周知,在互联网诞生之初都是各个高校和科研机构相互通讯,并没有Linux流量控制方面的考虑和设计,IP协议的原则是尽可能好地为所有数据流服务,不同的数据流之间是平等的。然而多年的实践表明,这种原则并不是最理想的,有些数据流应该得到特别的照顾, 比如,远程登录的交互数据流应该比数据下载有更高的优先级。

针对不同的数据流采取不同的策略,这种可能性是存在的。并且,随着研究的发展和深入, 人们已经提出了各种不同的管理模式。IETF已经发布了几个标准, 如综合服务(Integrated Services)、区分服务(Diferentiated Services)等。其实,Linux内核从2 2开始,就已经实现了相关的流量控制功能。本文将介绍Linux中有关流量控制的相关概念, 用于Linux流量控制的工具TC的使用方法,并给出几个有代表性实例。

一、相关概念

由此可以看出, 报文分组从输入网卡(入口)接收进来,经过路由的查找, 以确定是发给本机的,还是需要转发的。如果是发给本机的,就直接向上递交给上层的协议,比如TCP,如果是转发的, 则会从输出网卡(出口)发出。网络流量控制通常发生在输出网卡处。虽然在路由器的入口处也可以进行流量控制,Linux也具有相关的功能, 但一般说来, 由于我们无法控制自己网络之外的设备, 入口处的Linux流量控制相对较难。本文将集中介绍出口处的流量控制。流量控制的一个基本概念是队列(Qdisc),每个网卡都与一个队列(Qdisc)相联系, 每当内核需要将报文分组从网卡发送出去, 都会首先将该报文分组添加到该网卡所配置的队列中, 由该队列决定报文分组的发送顺序。因此可以说,所有的Linux流量控制都发生在队列中,详细流程图见图1。

图1报文在Linux内部流程图

有些队列的功能是非常简单的, 它们对报文分组实行先来先走的策略。有些队列则功能复杂,会将不同的报文分组进行排队、分类,并根据不同的原则, 以不同的顺序发送队列中的报文分组。为实现这样的功能,这些复杂的队列需要使用不同的过滤器(Filter)来把报文分组分成不同的类别(Class)。这里把这些复杂的队列称为可分类(ClassfuI)的队列。通常, 要实现功能强大的Linux流量控制, 可分类的队列是必不可少的。因此,类别(class)和过滤器(Filter)也是流量控制的另外两个重要的基本概念。图2所示的是一个可分类队列的例子。

图2多类别队列

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

二、使用TC

在Linux中,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, 即"兆比特每秒 。

三、创建HTB队列

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


  1. #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。

四、为根队列创建相应的类别

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


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

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

#tc class add dev eth0 parent 1: classid 1:1 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: cllassid 1:13 htb rate 20mbit ceil 20mbit

命令中,"parent 1:"表示类别的父亲为根队列1:。"classid1:11"表示创建一个标识为1:11的类别,"rate 40mbit"表示系统

将为该类别确保带宽40mbit,"ceil 40mbit",表示该类别的最高可占用带宽为40mbit。

五、为各个类别设置过滤器

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


  1. #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"表示该过滤器应该检查报文分组的协议字段。"pr[o 1" 表示它们对报文处理的优先级是相同的,对于不同优先级的过滤器, 系统将按照从小到大的优先级。

顺序来执行过滤器, 对于相同的优先级,系统将按照命令的先后顺序执行。这几个过滤器还用到了u32选择器(命令中u32后面的部分)来匹配不同的数据流。以第一个命令为例,判断的是dport字段,如果该字段与Oxffff进行与操作的结果是8O,则"flowid 1:11" 表示将把该数据流分配给类别1:1 1。更加详细的有关TC的用法可以参考TC 的手册页。

六、复杂的实例

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

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

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

图三

需要的TC命令如下:


  1. #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中类别和子类别的包含关系,可以构建更加复杂的多层次类别树,从而实现的更加灵活的带宽共享和独占模式,达到企业级的带宽管理目的。

时间: 2024-10-12 11:12:09

Linux流量控制TC中的HTB队列创建与过滤的相关文章

linux下TC+HTB流量控制

C规则涉及到 队列(QUEUE) 分类器(CLASS) 过滤器(FILTER),filter划分的标志位可用U32或iptables的set-mark来实现 ) 一般是"控发"不控收 linux下有两块网卡,一个eth1是外网,另一块eth0是内网.在eth0上做HTB.(注 意:filter划分标志位可用u32打标功能或iptables的set-mark功能,如果用iptables来打标记的话,下行速LV在eth0处 控制,但打标应在进入eth0之前进行,所以,"-i et

Linux 下TC 以及netem队列的使用

一:综述: linux系统中的流量控制器(TC)主要是在输出端口处建立一个队列进行流量控制. TC是一个可以根据数据包的任何一个部分的特征对其进行分类的工具,并且可以为各类数据提供不同带宽,从而控制他们的传输速度.TC是iproute2的一部分,集成在2.2.及以上版本的内核中,还可以与linux内核里的各种架构(如Netfilter netem)协同工作. 二:TC的组件 TC主要由队列规定(qdisc),类(class)和过滤器(filter)这3个组件组成,绘图中一般用圆形表示队列规定,用

关于Linux操作系统中的queue_depth(队列深度)

Linux中的queue_depth(队列深度),可以用lsscsi查看. 不过今天在我的vm 虚拟机环境中(无外界存储),是没有lsscsi命令. 不过,从网上,搜到了如下的信息: $ lsscsi -l [0:0:1:0]    disk    FUJITSU  MAM3184MP        0105  /dev/sda state=running queue_depth=16 scsi_level=4 type=0 device_blocked=0 timeout=30 先记录下来.

在 Linux 中如何自动批量创建用户

作为一名 Linux 系统管理员,你有时必须向系统添加新的用户帐户.为此,经常使用 adduser 命令.当涉及到多个用户的创建时,adduser 命令可能会变得相当无聊和耗时.这篇短文旨在为 Linux 系统管理员提供一种简单而无人值守的方式来批量创建用户.newusers 命令将帮助你通过从预填文件中获取信息来创建多个用户. 要求 访问 Linux 计算机的特权. 约定 #- 给定命令需要以 root 用户权限运行或者使用sudo命令 $- 给定命令以常规权限用户运行 如何进行 创建一个包含

Linux系统中如何一次创建和删除多个文件/文件夹

Linux系统中如何一次创建和删除多个文件/文件夹 1.创建/删除多个文件 //连续创建5个文件,文件名为file1.file2...file5 [[email protected] ~]# touch file{1..5} [[email protected] ~]# ls anaconda-ks.cfg Downloads file3 hello install.log Pictures test Desktop file1 file4 hello.c install.log.syslog

Linux下TC使用说明 & 使用备注 ZZ

一.TC原理介绍 Linux操作系统中的流量控制器TC(Traffic Control)用于Linux内核的流量控制,主要是通过在输出端口处建立一个队列来实现流量控制. Linux流量控制的基本原理如下图所示. 接收包从输入接口(Input Interface)进来后,经过流量限制(Ingress Policing)丢弃不符合规定的数据包,由输入多路分配器(Input De-Multiplexing)进行判断选择:如果接收包的目的是本主机,那么将该包送给上层处理:否则需要进行转发,将接收包交到转

Linux下TC使用说明

Linux下TC使用说明 一.TC原理介绍 Linux操作系统中的流量控制器TC(Traffic Control)用于Linux内核的流量控制,主要是通过在输出端口处建立一个队列来实现流量控制. Linux流量控制的基本原理如下图所示. 接收包从输入接口(Input Interface)进来后,经过流量限制(Ingress Policing)丢弃不符合规定的数据包,由输入多路分配器(Input De-Multiplexing)进行判断选择:如果接收包的目的是本主机,那么将该包送给上层处理:否则需

嵌入式 Linux进程间通信(七)——消息队列

嵌入式 Linux进程间通信(七)--消息队列 一.消息队列 消息队列用于同一台机器上的进程间通信,是一个在系统内核中用来保存消息的队列,在系统内核中是以消息链表的形式出现.消息链表中节点的结构用msg声明.消息队列是一种从一个进程向另一个进程发送数据块的方法. 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.消息队列可以避免命名管道的同步和阻塞问题,但是每个数据块都有一个最大长度的限制. 1.msgget函数 #include <sys/types.h> #in

Linux进程间通信(1)——消息队列

下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管道 一.什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.  每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题.但是消息队列 与命名管道一样,每个数据块都有一个最大长度的限制. Linux用宏MSGMAX和MSGMNB来限制一条消