流量控制 HOWTO

版本 1.0.2

Martin A. Brown

“2006 年 10 月”

修订历史
修订 1.0.22006-10-28修订者:MAB
添加 HFSC 的参考,更改作者电子邮件地址
修订 1.0.12003-11-17修订者:MAB
添加了 Leonardo Balliache 文档的链接
修订 1.02003-09-24修订者:MAB
经 TLDP 审核和批准
修订 0.72003-09-14修订者:MAB
增量修订,校对,准备提交 TLDP
修订 0.62003-09-09修订者:MAB
小幅编辑,Stef Coene 的更正
修订 0.52003-09-01修订者:MAB
HTB 章节基本完成,更多图表,LARTC 预发布
修订 0.42003-08-30修订者:MAB
添加了图表
修订 0.32003-08-29修订者:MAB
基本完成无类别、软件、规则、元素和组件章节
修订 0.22003-08-23修订者:MAB
概述、元素、组件和软件章节的主要工作
修订 0.12003-08-15修订者:MAB
初始修订(大纲完成)

流量控制包含一组机制和操作,通过这些机制和操作,数据包被排队以便在网络接口上进行传输/接收。这些操作包括入队、策略、分类、调度、整形和丢弃。本 HOWTO 介绍了 Linux 下流量控制的功能和实现概述。

© 2006, Martin A. Brown

根据 GNU 自由文档许可证 1.1 版或自由软件基金会发布的任何后续版本的条款,允许复制、分发和/或修改本文档;不包含不变部分,不包含封面文本,不包含封底文本。许可证副本位于 https://gnu.ac.cn/licenses/fdl.html


目录
1. Linux 流量控制简介
1.1. 目标受众和关于读者的假设
1.2. 约定
1.3. 推荐方法
1.4. 缺失内容、更正和反馈
2. 概念概述
2.1. 它是什么?
2.2. 为什么要使用它?
2.3. 优点
2.4. 缺点
2.5. 队列
2.6.
2.7. 令牌和桶
2.8. 数据包和帧
3. 流量控制的传统元素
3.1. 整形
3.2. 调度
3.3. 分类
3.4. 策略
3.5. 丢弃
3.6. 标记
4. Linux 流量控制的组件
4.1. qdisc
4.2. class
4.3. filter
4.4. 分类器
4.5. 策略器
4.6. drop
4.7. handle
5. 软件和工具
5.1. 内核要求
5.2. iproute2 工具 (tc)
5.3. tcng, 下一代流量控制
5.4. IMQ,中间队列设备
6. 无类别队列规则 (qdiscs)
6.1. FIFO,先进先出 (pfifobfifo)
6.2. pfifo_fast,默认 Linux qdisc
6.3. SFQ,随机公平队列
6.4. ESFQ,扩展随机公平队列
6.5. GRED,通用随机早期丢弃
6.6. TBF,令牌桶过滤器
7. 有类别队列规则 (qdiscs)
7.1. HTB,分层令牌桶
7.2. HFSC,分层公平服务曲线
7.3. PRIO,优先级调度器
7.4. CBQ,基于类的队列
8. 规则、指南和方法
8.1. Linux 流量控制的一般规则
8.2. 处理已知带宽的链路
8.3. 处理可变(或未知)带宽的链路
8.4. 基于流共享/分割带宽
8.5. 基于 IP 共享/分割带宽
9. 用于 QoS/流量控制的脚本
9.1. wondershaper
9.2. ADSL 带宽 HOWTO 脚本 (myshaper)
9.3. htb.init
9.4. tcng.init
9.5. cbq.init
10. 图表
10.1. 通用图表
11. 注释流量控制链接

1. Linux 流量控制简介

Linux 提供了一套非常丰富的工具,用于管理和操作数据包的传输。更大的 Linux 社区非常熟悉 Linux 下可用的数据包处理和防火墙工具(netfilter,以及之前的 ipchains),以及可以在操作系统上运行的数百种网络服务。社区内部很少有人,Linux 社区外部更少有人意识到流量控制子系统的巨大威力,该子系统在 2.2 和 2.4 内核下不断发展和成熟。

本 HOWTO 旨在介绍流量控制的概念传统元素(一般而言)Linux 流量控制实现的组件,并提供一些指南。本 HOWTO 代表了 LARTC HOWTO、各个项目的文档以及重要的是 LARTC 邮件列表 在一段时间研究的收集、合并和综合。

对于只想立即进行实验的急切灵魂,建议参考 使用 tcng 和 HTB 进行流量控制 HOWTOLARTC HOWTO 以获得即时满足。


1.1. 目标受众和关于读者的假设

本 HOWTO 的目标受众是希望了解流量控制领域并概述 Linux 下可用于实现流量控制的工具的网络管理员或精通技术的家庭用户。

我假设读者对 UNIX 概念和命令行感到舒适,并且对 IP 网络有基本的了解。希望实施流量控制的用户可能需要修补、编译和安装内核或软件包 [1] 的能力。但是,对于使用较新内核(2.4.20+,另请参见第 5.1 节)的用户,可能只需要安装和使用软件的能力。

广义上讲,本 HOWTO 是为有经验的用户编写的,可能是有 Linux 下流量控制经验的用户。我假设读者可能没有先前的流量控制经验。


1.2. 约定

本文档使用 DocBook (版本 4.2) 和 vim 编写。所有格式均由 xsltproc 基于 DocBook XSLLDP XSL 样式表应用。字体格式和显示约定与大多数印刷和电子分发的技术文档类似。


1.3. 推荐方法

我强烈建议渴望首次涉足流量控制领域的读者,在专注于 tcng 之前,仅需粗略熟悉 tc 命令行实用程序。tcng 软件包定义了一种完整的语言来描述流量控制结构。乍一看,这种语言可能令人生畏,但是掌握这些基础知识将迅速为用户提供比直接使用 tc 更广泛的能力来使用(和部署)流量控制配置。

在可能的情况下,我将尝试以抽象的方式描述 Linux 流量控制系统的行为,尽管在许多情况下,我需要提供定义这些结构的常见系统之一或另一个的语法。我可能不会同时提供 tcng 语言和 tc 命令行示例,因此明智的用户将对两者都有一些了解。


1.4. 缺失内容、更正和反馈

本 HOWTO 中仍缺少内容。特别是,以下项目将在稍后添加到本文档中。

  • GRED、WRR、PRIO 和 CBQ 的描述和图表。

  • 示例章节。

  • 详细介绍分类器的章节。

  • 讨论流量测量技术的章节。

  • 涵盖计量器的章节。

  • 关于 tcng 的更多详细信息。

我欢迎提出建议、更正和反馈,请发送至。所有错误和遗漏完全是我的责任。尽管我已尽一切努力验证本文档中内容的真实性,但我对根据本文档的影响而采取的行动不承担任何责任。


2. 概念概述

本节将介绍流量控制检查使用它的原因,确定一些优点缺点,并介绍流量控制中使用的关键概念。


2.1. 它是什么?

流量控制是指在路由器上接收和传输数据包的排队系统和机制的集合名称。这包括决定在接口输入端以什么速率接受哪些数据包(以及是否接受),以及确定在接口输出端以什么速率以什么顺序传输哪些数据包。

在绝大多数情况下,流量控制由一个队列组成,该队列收集进入的数据包,并在硬件(或底层设备)可以接受它们时尽快将其出队。这种队列是 FIFO。

NoteLinux 下的默认 qdisc 是 pfifo_fast,它比 FIFO 稍微复杂一些。

在各种软件中都有队列的示例。队列是组织待处理任务或数据的一种方式(另请参见第 2.5 节)。由于网络链路通常以串行方式传输数据,因此需要队列来管理出站数据包。

在桌面机器和共享同一互联网上行链路的高效 Web 服务器的情况下,可能会发生以下带宽争用。Web 服务器可能能够比数据通过链路传输的速度更快地填满路由器上的输出队列,此时路由器开始丢弃数据包(其缓冲区已满!)。现在,桌面机器(带有交互式应用程序用户)可能面临数据包丢失和高延迟。请注意,高延迟有时会导致用户尖叫!通过分离用于服务这两个不同类别的应用程序的内部队列,可以在这两个应用程序之间更好地共享网络资源。

流量控制是一组工具,允许用户对联网设备的这些队列和排队机制进行精细控制。使用这些工具重新排列流量和数据包的能力非常强大且可能很复杂,但不能替代足够的带宽。

术语服务质量 (QoS) 通常用作流量控制的同义词。


2.2. 为什么要使用它?

分组交换网络与电路交换网络在一个非常重要的方面有所不同。分组交换网络本身是无状态的。电路交换网络(例如电话网络)必须在网络内保持状态。IP 网络在设计上是无状态和分组交换网络;事实上,这种无状态性是 IP 的基本优势之一。

这种无状态性的弱点是缺乏对流量类型的区分。简而言之,流量控制允许管理员根据数据包的属性对数据包进行不同的排队。它甚至可以用来模拟电路交换网络的行为。这会将状态引入无状态网络。

有很多实际原因需要考虑流量控制,并且在许多情况下使用流量控制是有意义的。以下是一些可以使用这些工具解决或至少改善的常见问题示例。

下面的列表并非流量控制用户可用的所有类型解决方案的详尽列表,而是介绍了可以通过使用流量控制来最大化网络连接可用性的问题类型。

常见的流量控制解决方案

  • 将总带宽限制为已知速率;TBFHTB 带子类。

  • 限制特定用户、服务或客户端的带宽;HTB 类和分类filter。流量。

  • 在非对称链路上最大化 TCP 吞吐量;优先传输 ACK 数据包,wondershaper

  • 为特定应用程序或用户保留带宽;HTB 带子类和分类

  • 优先处理延迟敏感型流量;PRIOHTB 类内部。

  • 管理超额订阅带宽;HTB 带借用。

  • 允许公平分配未保留带宽;HTB 带借用。

  • 确保丢弃特定类型的流量;policer 连接到 filter,并带有 drop 操作。

还要记住,有时,购买更多带宽会更好。流量控制并不能解决所有问题!


2.3. 优点

如果使用得当,流量控制应导致更可预测的网络资源使用,并减少对这些资源的波动性争用。然后,网络将满足流量控制配置的目标。即使同时为更高优先级的交互式流量提供服务,也可以为批量下载流量分配合理的带宽。即使是低优先级数据传输(例如邮件)也可以分配带宽,而不会对其他类别的流量产生巨大影响。

从更大的角度来看,如果流量控制配置代表已传达给用户的策略,则用户(以及扩展的应用程序)知道对网络的期望。


2.4. 缺点

复杂性很容易成为使用流量控制的最显着缺点之一。有一些方法可以熟悉流量控制工具,从而缓解关于流量控制及其机制的学习曲线,但是识别流量控制配置错误可能是一个相当大的挑战。

适当地使用流量控制可以导致更公平地分配网络资源。它也可能以不适当的方式安装,从而导致对资源的进一步和更具分裂性的争用。

路由器上支持流量控制方案所需的计算资源需要能够处理维护流量控制结构增加的成本。幸运的是,这是一个很小的增量成本,但随着配置规模和复杂性的增长,它可能会变得更加重要。

对于个人使用,使用流量控制没有相关的培训成本,但是公司可能会发现购买更多带宽比使用流量控制更简单。培训员工并确保知识深度可能比投资更多带宽更昂贵。

尽管分组交换网络上的流量控制涵盖了更大的概念领域,但您可以将流量控制视为为分组交换网络提供[部分]电路交换网络状态的一种方式。


2.5. 队列

队列构成了所有流量控制的背景,并且是调度的基本概念。队列是包含有限数量的等待操作或服务的项目的位置(或缓冲区)。在网络中,队列是数据包(我们的单位)等待硬件(服务)传输的位置。在最简单的模型中,数据包以先到先服务的方式传输 [2]。在计算机网络(以及更广泛的计算机科学)学科中,这种队列被称为 FIFO。

在没有任何其他机制的情况下,队列不提供任何流量控制的保证。队列中只有两个有趣的动作。任何进入队列的内容都会排入队列。从队列中删除项目就是将该项目出队。

当队列与其他可以延迟数据包、重新排列、丢弃和优先处理多个队列中的数据包的机制结合使用时,队列会变得更加有趣。队列还可以使用子队列,这使得调度操作中的行为变得复杂。

从更高层软件的角度来看,数据包只是简单地排队以进行传输,并且排队的数据包的传输方式和顺序对于更高层而言是无关紧要的。因此,对于更高层而言,整个流量控制系统可能看起来像单个队列 [3]。只有通过检查该层的内部结构,流量控制结构才会暴露和可用。


2.6. 流

流是两个主机之间不同的连接或对话。两个主机之间的任何唯一数据包集都可以视为流。在 TCP 下,具有源 IP 和端口以及目标 IP 和端口的连接概念代表一个流。UDP 流也可以类似地定义。

流量控制机制经常将流量分离为流的类别,这些类别可以聚合并作为聚合流传输(考虑 DiffServ)。备用机制可能会尝试根据各个流平等地划分带宽。

当尝试在一组竞争流之间平均分配带宽时,流变得很重要,尤其是在某些应用程序故意构建大量流时。


2.7. 令牌和桶

整形 机制的两个关键基础是令牌和桶的相互关联的概念。

为了控制出队速率,实现可以计算每个项目出队时出队的数据包或字节数,尽管这需要复杂地使用计时器和测量来准确限制。一种广泛用于流量控制的方法,不是计算当前使用量和时间,而是以期望的速率生成令牌,并且仅当令牌可用时才将数据包或字节出队。

考虑一个游乐园游乐设施的类比,队列中有人在等待体验游乐设施。让我们想象一条轨道,手推车在固定轨道上行驶。手推车以固定的速率到达队列的头部。为了享受游乐设施,每个人都必须等待可用的手推车。手推车类似于令牌,人类似于数据包。同样,这种机制是速率限制或整形 机制。在特定时期内,只有一定数量的人可以体验游乐设施。

为了扩展这个类比,想象一下游乐园游乐设施的空行,以及大量手推车停在轨道上,准备载人。如果大量的人一起进入队列,那么由于手推车可用并等待,他们中的许多人(可能全部)都可以体验游乐设施。可用手推车的数量是一个类似于桶的概念。一个桶包含多个令牌,并且可以使用桶中的所有令牌,而无需考虑时间的推移。

为了完成类比,游乐园游乐设施上的手推车(我们的令牌)以固定的速率到达,并且仅保持可用,直到桶的大小。因此,桶根据速率填充令牌,如果未使用令牌,则桶可以填满。如果使用了令牌,则桶将不会填满。桶是支持突发流量(例如 HTTP)的关键概念。

TBF qdisc 是整形器的经典示例(关于 TBF 的部分包含一个图表,可以帮助可视化令牌和桶的概念)。TBF 生成速率令牌,并且仅当令牌可用时才传输数据包。令牌是一个通用的整形概念。

如果队列不需要立即使用令牌,则可以收集令牌直到需要它们为止。无限期地收集令牌将否定整形的任何好处,因此收集令牌直到达到一定数量的令牌。现在,队列有令牌可用于大量需要出队的数据包或字节。这些无形的令牌存储在一个无形的桶中,并且可以存储的令牌数量取决于桶的大小。

这也意味着在任何时刻都可能有一个装满令牌的桶可用。非常可预测的常规流量可以通过小桶处理。对于突发性更强的流量,可能需要更大的桶,除非所需的目标之一是减少的突发性。

总而言之,令牌以速率生成,并且最多可以收集一个桶值的令牌。这允许处理突发流量,同时平滑和整形传输的流量。

令牌和桶的概念密切相关,并在 TBF无类别 qdisc 之一)和 HTB有类别 qdisc 之一)中使用。在 tcng 语言中,使用双色和三色计量器无疑是令牌和桶的概念。


2.8. 数据包和帧

跨网络发送的数据术语根据用户正在检查的层而变化。本文档将相当粗鲁(且不正确地)忽略数据包和帧之间的技术区别,尽管此处概述了它们。

单词帧通常用于描述要转发给下一个接收者的第 2 层(数据链路)数据单元。以太网接口、PPP 接口和 T1 接口都将其第 2 层数据单元命名为帧。帧实际上是执行流量控制的单元。

另一方面,数据包是更高层的概念,代表第 3 层(网络)单元。术语数据包在本文档中是首选,尽管它略有不准确。


3. 流量控制的传统元素


3.1. 整形

整形器延迟数据包以满足期望的速率。

整形是一种机制,通过该机制,数据包在输出队列中传输之前被延迟以满足期望的输出速率。这是寻求带宽控制解决方案的用户最常见的愿望之一。延迟数据包作为流量控制解决方案的一部分的行为使每个整形机制都成为非工作保持机制,大致意思是:“需要工作才能延迟数据包。”

反过来看,非工作保持排队机制正在执行整形功能。工作保持排队机制(参见 PRIO)将无法延迟数据包。

整形器尝试限制或定量分配流量,以满足但不超过配置的速率(通常以每秒数据包数或每秒比特/字节数衡量)。作为副作用,整形器可以平滑突发流量 [4]。带宽整形的优点之一是能够控制数据包的延迟。整形到速率的底层机制通常是令牌和桶机制。另请参见 第 2.7 节,了解有关令牌和桶的更多详细信息。


3.2. 调度

调度器排列和/或重新排列数据包以进行输出。

调度是一种机制,通过该机制,在特定队列的输入和输出之间排列(或重新排列)数据包。最常见的调度器是 FIFO(先进先出)调度器。从更大的角度来看,输出队列上的任何一组流量控制机制都可以视为调度器,因为数据包被排列用于输出。

其他通用调度机制尝试补偿各种网络状况。公平排队算法(参见 SFQ)尝试防止任何单个客户端或流主导网络使用。轮询算法(参见 WRR)为每个流或客户端提供出队数据包的机会。其他复杂的调度算法尝试防止骨干网过载(参见 GRED)或改进其他调度机制(参见 ESFQ)。


3.3. 分类

分类器将流量分类或分离到队列中。

分类是一种机制,通过该机制,数据包被分离以进行不同的处理,可能是不同的输出队列。在接受、路由和传输数据包的过程中,联网设备可以以多种不同的方式对数据包进行分类。分类可以包括标记数据包,这通常发生在单个管理控制下的网络边界上,或者分类可以单独发生在每个跃点上。

Linux 模型(参见第 4.3 节)允许数据包在流量控制结构中跨一系列分类器级联,并与策略器结合分类(另请参见第 4.5 节)。


3.4. 策略

策略器测量和限制特定队列中的流量。

策略作为流量控制的一个要素,只是一种可以限制流量的机制。策略最常用于网络边界,以确保对等方消耗的带宽不超过其分配的带宽。策略器将接受达到一定速率的流量,然后对超过此速率的流量执行操作。一个相当严厉的解决方案是丢弃流量,尽管流量可以重新分类而不是被丢弃。

策略器是一个关于流量进入队列速率的是/否问题。如果数据包即将以低于给定速率进入队列,则采取一个操作(允许入队)。如果数据包即将以高于给定速率进入队列,则采取另一个操作。尽管策略器在内部使用令牌桶机制,但它不具有像整形机制那样延迟数据包的能力。


3.5. 丢弃

丢弃会丢弃整个数据包、流或分类。

丢弃数据包是一种丢弃数据包的机制。


3.6. 标记

标记是一种更改数据包的机制。

Note这不是fwmarkiptables 目标MARKipchains--mark用于修改数据包元数据,而不是数据包本身。

流量控制标记机制在数据包本身上安装 DSCP,然后由管理域内的其他路由器使用和尊重(通常用于 DiffServ)。


4. Linux 流量控制的组件

表 1. 流量控制元素和 Linux 组件之间的相关性

传统元素Linux 组件
整形class 提供整形功能。
调度qdisc 是一个调度器。调度器可以很简单,例如 FIFO,也可以很复杂,包含类和其他 qdisc,例如 HTB。
分类filter 对象通过 classifier 对象的作用来执行分类。严格来说,Linux 分类器不能独立于过滤器存在。
策略policer 仅作为 filter 的一部分存在于 Linux 流量控制实现中。
丢弃drop 流量,需要一个 filter,其中包含一个 policer,该策略器使用 “drop” 作为操作。
标记dsmark qdisc 用于标记。

4.1. qdisc

简而言之,qdisc 是一个调度器(第 3.2 节)。每个输出接口都需要某种调度器,默认调度器是 FIFO。Linux 下可用的其他 qdisc 将根据该调度器的规则重新排列进入调度器队列的数据包。

qdisc 是构建所有 Linux 流量控制的主要构建块,也称为排队规则。

有类别 qdisc 可以包含 classes,并提供一个句柄,用于附加 filters。不禁止在没有子类的情况下使用有类别 qdisc,但这通常会消耗周期和其他系统资源而没有任何好处。

无类别 qdisc 不能包含类,也不能将过滤器附加到无类别 qdisc。由于无类别 qdisc 不包含任何类型的子项,因此分类没有任何效用。这意味着无法将过滤器附加到无类别 qdisc。

术语混淆的一个来源是术语的用法rootqdisc 和ingressqdisc。这些实际上不是排队规则,而是可以将流量控制结构附加到出口(出站流量)和入口(入站流量)的位置。

每个接口都包含两者。主要且更常见的是出口 qdisc,称为rootqdisc。它可以包含任何排队规则 (qdiscs),并具有潜在的 classes 和类结构。绝大多数文档都适用于rootqdisc 及其子项。在接口上传输的流量会遍历出口或rootqdisc。

对于接口上接受的流量,ingressqdisc 会被遍历。由于其效用有限,它不允许创建子 class(类),仅作为可以附加 filter(过滤器)的对象而存在。实际上,ingressqdisc 仅仅是一个方便的对象,可以在其上附加 policer(策略器),以限制网络接口上接受的流量。

简而言之,您可以使用出口 qdisc 做更多的事情,因为它包含一个真正的 qdisc 和流量控制系统的全部功能。入口ingressqdisc 只能支持一个策略器。本文档的其余部分将关注附加到出口rootqdisc 的流量控制结构,除非另有说明。


4.2. class(类)

类仅存在于有类别的 qdisc(例如,例如HTBCBQ)中。类非常灵活,并且总是可以包含多个子类或单个子 qdisc [5]。不禁止一个类本身包含一个有类别的 qdisc,这极大地促进了复杂的流量控制场景。

任何类也可以附加任意数量的 filter(过滤器),这允许选择子类或使用过滤器来重新分类或丢弃进入特定类的流量。

叶子类是 qdisc 中的终端类。它包含一个 qdisc(默认 FIFO)并且永远不会包含子类。任何包含子类的类都是内部类(或根类),而不是叶子类。


4.3. filter(过滤器)

过滤器是 Linux 流量控制系统中最复杂的组件。过滤器提供了一种方便的机制,用于将流量控制的几个关键要素粘合在一起。过滤器最简单和最明显的角色是对数据包进行分类(参见 第 3.3 节)。Linux 过滤器允许用户使用多个不同的过滤器或单个过滤器将数据包分类到输出队列中。

  • 过滤器必须包含一个 classifier(分类器)短语。

  • 过滤器可能包含一个 policer(策略器)短语。

过滤器可以附加到有类别的 qdiscclass(类)上,但是排队的数据包总是首先进入根 qdisc。在遍历附加到根 qdisc 的过滤器之后,数据包可能会被定向到任何子类(它们可以有自己的过滤器),在那里数据包可能会经历进一步的分类。


4.4. classifier(分类器)

可以使用 tc 操作的过滤器对象可以使用几种不同的分类机制,其中最常见的是u32分类器。u32分类器允许用户根据数据包的属性选择数据包。

分类器是可以用作 filter(过滤器)一部分的工具,用于识别数据包或数据包的元数据的特征。Linux 分类器对象直接类似于流量控制 分类 的基本操作和基本机制。


4.5. policer(策略器)

这种基本机制仅在 Linux 流量控制中用作 filter(过滤器)的一部分。策略器调用高于指定速率的一个动作和低于指定速率的另一个动作。巧妙地使用策略器可以模拟三色计量器。另请参阅 第 10 节

尽管 策略整形 都是限制带宽使用的流量控制的基本要素,但策略器永远不会延迟流量。它只能根据指定的标准执行操作。另请参阅 示例 5


4.6. drop(丢弃)

这种基本的流量控制机制仅在 Linux 流量控制中用作 policer(策略器)的一部分。附加到任何 filter(过滤器)的任何策略器都可以具有 drop(丢弃)动作。

Note在 Linux 流量控制系统中,可以显式丢弃数据包的唯一位置是策略器。策略器可以限制以特定速率排队的数据包,或者可以配置为丢弃与特定模式匹配的所有流量 [6]

但是,在流量控制系统中,数据包可能会作为副作用被丢弃。例如,如果使用的调度器使用此方法来控制流,如 GRED 所做的那样,则数据包将被丢弃。

此外,整形器或调度器如果耗尽其分配的缓冲区空间,则可能不得不在特别突发或过载期间丢弃数据包。


4.7. handle(句柄)

每个 class(类)和有类别的 qdisc(另请参阅 第 7 节)都需要流量控制结构内的唯一标识符。此唯一标识符称为句柄,并具有两个组成部分,一个主编号和一个次编号。这些数字可以由用户根据以下规则任意分配 [7]

类和 qdisc 的句柄编号

major(主编号)

此参数对内核完全没有意义。用户可以使用任意编号方案,但是流量控制结构中具有相同父对象的所有对象必须共享一个major(主编号)句柄编号。传统编号方案从直接附加到出口rootqdisc。

minor(次编号)

如果次编号minor(次编号)为 0,则此参数明确地将对象标识为 qdisc。任何其他值都将对象标识为类。共享父对象的所有类必须具有唯一的minor(次编号)次编号。

特殊的句柄 ffff:0 保留给入口ingressqdisc。

句柄用作classid(类 ID)flowid(流 ID)tc filter(过滤器)语句中的目标。这些句柄是对象的用户级应用程序可用的外部标识符。内核维护每个对象的内部标识符。


5. 软件和工具


5.1. 内核要求

许多发行版提供的内核都具有对流量控制(服务质量)的模块化或单内核支持。自定义内核可能尚未提供对所需功能的支持(模块化与否)。如果不是,这是一个非常简短的所需内核选项列表。

建议几乎没有或没有内核编译经验的用户参考 Kernel HOWTO(内核 HOWTO)。经验丰富的内核编译人员在阅读更多关于流量控制和规划之后,应该能够确定以下哪些选项适用于所需的配置。

示例 1. 内核编译选项 [8]

#
# QoS and/or fair queueing
#
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_CSZ=m
CONFIG_NET_SCH_PRIO=m
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_QOS=y
CONFIG_NET_ESTIMATOR=y
CONFIG_NET_CLS=y
CONFIG_NET_CLS_TCINDEX=m
CONFIG_NET_CLS_ROUTE4=m
CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_U32=m
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
CONFIG_NET_CLS_POLICE=y
      

使用上述选项集编译的内核将为本文档中讨论的几乎所有内容提供模块化支持。用户可能需要在使用给定功能之前 modprobe 模块。再次强调,建议感到困惑的用户参考 Kernel HOWTO(内核 HOWTO),因为本文档无法充分解决关于 Linux 内核使用的问题。


5.2. iproute2 工具 (tc)

iproute2 是一套命令行实用程序,用于操作机器上 IP 网络配置的内核结构。有关这些工具的技术文档,请参阅 iproute2 文档,有关更具解释性的讨论,请参阅 linux-ip.net 的文档。在 iproute2 包中的工具中,二进制文件 tc 是唯一用于流量控制的工具。本 HOWTO 将忽略该套件中的其他工具。

由于它与内核交互以指导流量控制结构的创建、删除和修改,因此 tc 二进制文件需要编译时支持您希望使用的所有 qdisc。特别是,上游 iproute2 包尚不支持 HTB qdisc。有关更多信息,请参阅 第 7.1 节

tc 工具执行支持流量控制所需的内核结构的所有配置。由于其用途广泛,命令语法(充其量)可以被描述为神秘的。tc 实用程序将其第一个非选项参数作为三个 Linux 流量控制组件之一,qdiscclass(类)或 filter(过滤器)。

示例 2. tc 命令用法

[root@leander]# tc
Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }
where  OBJECT := { qdisc | class | filter }
       OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] }
      

每个对象接受进一步和不同的选项,并且将在下面不完整地描述和记录。以下示例中的提示旨在介绍 tc 命令行语法的变幻莫测。有关更多示例,请查阅 LARTC HOWTO。为了更好地理解,请查阅内核和 iproute2 代码。

示例 3. tc qdisc

[root@leander]# tc qdisc add    \ (1)
>                  dev eth0     \ (2)
>                  root         \ (3)
>                  handle 1:0   \ (4)
>                  htb            (5)
      
(1)
添加排队规则。动词也可以是del(删除).
(2)
指定我们要将新排队规则附加到的设备。
(3)
这对 tc 意味着 “出口”。单词root必须使用,但是。另一个功能有限的 qdisc,入口ingressqdisc 可以附加到同一设备。
(4)
handle(句柄)是用户指定的数字,形式为major(主编号):minor(次编号)。任何排队规则句柄的次编号必须始终为零 (0)。qdisc 句柄的可接受简写语法是 “1:”,其中如果未指定,则次编号假定为零 (0)。
(5)
这是要附加的排队规则,在本示例中为 HTB。排队规则特定的参数将紧随其后。在此示例中,我们没有添加任何 qdisc 特定的参数。

以上是将排队规则添加到设备的最简单 tc 实用程序用法。这是一个使用 tc 向现有父类添加类的示例。

示例 4. tc class(类)

[root@leander]# tc class add    \ (1)
>                  dev eth0     \ (2)
>                  parent 1:1   \ (3)
>                  classid 1:6  \ (4)
>                  htb          \ (5)
>                  rate 256kbit \ (6)
>                  ceil 512kbit   (7)
      
(1)
添加一个类。动词也可以是del(删除).
(2)
指定我们要将新类附加到的设备。
(3)
指定我们要将新类附加到的父 handle(句柄)。
(4)
这是一个唯一 handle(句柄)(major(主编号):minor(次编号))标识此类的句柄。次编号必须是任何非零 (0) 数字。
(5)
有类别的 qdisc 都要求任何子类都必须与父类类型相同。因此,HTB qdisc 将包含 HTB 类。
(6)(7)
这是一个类特定的参数。有关这些参数的更多详细信息,请查阅 第 7.1 节

示例 5. tc filter(过滤器)

[root@leander]# tc filter add               \ (1)
>                  dev eth0                 \ (2)
>                  parent 1:0               \ (3)
>                  protocol ip              \ (4)
>                  prio 5                   \ (5)
>                  u32                      \ (6)
>                  match ip port 22 0xffff  \ (7)
>                  match ip tos 0x10 0xff   \ (8)
>                  flowid 1:6               \ (9)
>                  police                   \ (10)
>                  rate 32000bps            \ (11)
>                  burst 10240              \ (12)
>                  mpu 0                    \ (13)
>                  action drop/continue       (14)
      
(1)
添加一个过滤器。动词也可以是del(删除).
(2)
指定我们要将新过滤器附加到的设备。
(3)
指定我们要将新过滤器附加到的父句柄。
(4)
此参数是必需的。它的用途应该是显而易见的,尽管我不太了解。
(5)
prio(优先级)参数允许给定的过滤器优先于另一个过滤器。pref(优先)是同义词。
(6)
这是一个 classifier(分类器),并且是每个 tc filter(过滤器)命令中的必需短语。
(7)(8)
这些是分类器的参数。在这种情况下,具有服务类型标志(指示交互式使用)并且匹配端口 22 的数据包将由此语句选择。
(9)
flowid(流 ID)指定目标类(或 qdisc)的 handle(句柄),匹配的过滤器应将选择的数据包发送到该目标类(或 qdisc)。
(10)
这是 policer(策略器),并且是每个 tc filter(过滤器)命令中的可选短语。
(11)
策略器将在此速率之上执行一个动作,并在另一个速率之下执行另一个动作(参见 action(动作)参数)。
(12)
burst(突发)HTB 中的突发完全类似(burst(突发)是一个 令牌桶 概念)。burst(突发)最小策略单元。要计算所有流量,请使用
(13)
mpu(最小数据包单元)为零 (0)。action(动作)
(14)
指示如果根据策略器的属性应该做什么。第一个词指定如果超过策略器应该采取的动作。第二个词指定否则应该采取的动作。速率如上所示,tc 命令行实用程序具有神秘而复杂的语法,即使对于如此处示例所示的简单操作也是如此。读者不应感到惊讶的是,存在一种更简单的方法来配置 Linux 流量控制。请参阅下一节,第 5.3 节

5.3. tcng,下一代流量控制


FIXME;赞扬 tcng。另请参阅 使用 tcng 和 HTB 的流量控制 HOWTOtcng 文档

下一代流量控制(以下简称 tcng)提供了 Linux 下流量控制的所有功能,但头痛程度只有百分之二十。

5.4. IMQ,中间队列设备


FIXME;必须讨论 IMQ。另请参阅 Patrick McHardy 关于 IMQ 的网站。

6. 无类别排队规则 (qdisc)


这些排队规则中的每一个都可以用作接口上的主 qdisc,或者可以用作 有类别 qdisc 的叶子类内部。这些是在 Linux 下使用的基本调度器。请注意,默认调度器是 pfifo_fast

6.1. FIFO,先进先出 (


pfifobfifo这不是 Linux 接口上的默认 qdisc。请务必参阅 第 6.2 节,了解有关默认 qdisc()

Notepfifo_fast)的完整详细信息。FIFO 算法构成了所有 Linux 网络接口上的默认 qdisc (pfifo_fast) 的基础。它不执行数据包的整形或重新排列。它只是在接收和排队数据包后尽快传输数据包。这也是所有新创建的类中使用的 qdisc,直到另一个 qdisc 或类替换 FIFO。

然而,真正的 FIFO qdisc 必须具有大小限制(缓冲区大小),以防止在无法像接收数据包一样快速地出队数据包的情况下溢出。Linux 实现了两种基本的 FIFO qdisc,一种基于字节,另一种基于数据包。无论使用哪种类型的 FIFO,队列的大小都由参数

limit(限制)定义。对于,单位被理解为数据包,而对于bfifo,单位被理解为字节。这不是 Linux 接口上的默认 qdisc。请务必参阅 第 6.2 节,了解有关默认 qdisc(示例 6. 指定数据包或字节 FIFO 的

限制定义。对于6.2. pfifo_fast

[root@leander]# cat bfifo.tcc
/*
 * make a FIFO on eth0 with 10kbyte queue size
 *
 */

dev eth0 {
    egress {
        fifo (limit 10kB );
    }
}
[root@leander]# tcc < bfifo.tcc
# ================================ Device eth0 ================================

tc qdisc add dev eth0 handle 1:0 root dsmark indices 1 default_index 0
tc qdisc add dev eth0 handle 2:0 parent 1:0 bfifo limit 10240
[root@leander]# cat pfifo.tcc
/*
 * make a FIFO on eth0 with 30 packet queue size
 *
 */

dev eth0 {
    egress {
        fifo (limit 30p );
    }
}
[root@leander]# tcc < pfifo.tcc
# ================================ Device eth0 ================================

tc qdisc add dev eth0 handle 1:0 root dsmark indices 1 default_index 0
tc qdisc add dev eth0 handle 2:0 parent 1:0 pfifo limit 30
      

6.2. )的完整详细信息。qdisc 是 Linux 下所有接口的默认 qdisc。基于传统的 FIFO qdisc,此 qdisc 还提供了一些优先级。它提供了三个不同的频带(单独的 FIFO)用于分离流量。最高优先级流量(交互式流)被放置在频带 0 中,并且始终首先被服务。类似地,频带 1 总是在频带 2 出队之前清空挂起的数据包。

)的完整详细信息。关于 pfifo_fast

qdisc,最终用户没有什么可配置的。有关 pfifo_fast)的完整详细信息。的准确详细信息priomap(优先级映射)和 ToS 位的使用,请参阅 LARTC HOWTO 的 pfifo-fast 章节


6.3. SFQ,随机公平队列

SFQ qdisc 尝试在任意数量的 之间公平地分配向网络传输数据的机会。它通过使用哈希函数将流量分离到单独的(内部维护的)FIFO 中来实现这一点,这些 FIFO 以轮询方式出队。由于哈希函数的选择有可能表现出不公平性,因此会定期更改此函数。扰动(参数perturb(扰动))设置此周期性。

示例 7. 创建 SFQ

[root@leander]# cat sfq.tcc
/*
 * make an SFQ on eth0 with a 10 second perturbation
 *
 */

dev eth0 {
    egress {
        sfq( perturb 10s );
    }
}
[root@leander]# tcc < sfq.tcc
# ================================ Device eth0 ================================

tc qdisc add dev eth0 handle 1:0 root dsmark indices 1 default_index 0
tc qdisc add dev eth0 handle 2:0 parent 1:0 sfq perturb 10
      

不幸的是,一些聪明的软件(例如 Kazaa 和 eMule 等)通过打开尽可能多的 TCP 会话()来消除这种公平排队的益处。在许多网络中,对于行为良好的用户,SFQ 可以充分地将网络资源分配给竞争流,但是当令人讨厌的应用程序侵入网络时,可能需要采取其他措施。

另请参阅 第 6.4 节,了解具有更多暴露参数供用户操作的 SFQ qdisc。


6.4. ESFQ,扩展随机公平队列

从概念上讲,此 qdisc 与 SFQ 没有什么不同,尽管它允许用户控制比其更简单的同类产品更多的参数。构思此 qdisc 是为了克服上述 SFQ 的缺点。通过允许用户控制哪个哈希算法用于分配对网络带宽的访问,用户可以实现更公平的实际带宽分配。

示例 8. ESFQ 用法

Usage: ... esfq [ perturb SECS ] [ quantum BYTES ] [ depth FLOWS ]
        [ divisor HASHBITS ] [ limit PKTS ] [ hash HASHTYPE]

Where:
HASHTYPE := { classic | src | dst }
      

FIXME;此处需要实践经验和/或证明。


6.5. GRED,通用随机早期丢弃

FIXME;我从未使用过这个。需要实践经验或证明。

理论声明 RED 算法在骨干网或核心网络上很有用,但在最终用户附近不太有用。请参阅关于 的章节,以查看关于 TCP 渴求性的一般讨论。


6.6. TBF,令牌桶过滤器

此 qdisc 构建于 令牌令牌桶 之上。它只是整形在接口上传输的流量。为了限制从特定接口出队数据包的速度,TBF qdisc 是完美的解决方案。它只是将传输的流量减慢到指定的速率。

只有在有足够的令牌可用时才传输数据包。否则,数据包将被延迟。以这种方式延迟数据包将在数据包的往返时间中引入人为延迟。

示例 9. 创建 256kbit/s TBF

[root@leander]# cat tbf.tcc
/*
 * make a 256kbit/s TBF on eth0
 *
 */

dev eth0 {
    egress {
        tbf( rate 256 kbps, burst 20 kB, limit 20 kB, mtu 1514 B );
    }
}
[root@leander]# tcc < tbf.tcc
# ================================ Device eth0 ================================

tc qdisc add dev eth0 handle 1:0 root dsmark indices 1 default_index 0
tc qdisc add dev eth0 handle 2:0 parent 1:0 tbf burst 20480 limit 20480 mtu 1514 rate 32000bps
      


7. 有类别排队规则 (qdisc)

Linux 流量控制的灵活性和控制可以通过有类别 qdisc 的作用来释放。请记住,有类别排队规则可以附加过滤器,允许将数据包定向到特定的类和子队列。

有几个常用术语来描述直接附加到出口rootqdisc 和终端类的类。附加到出口rootqdisc 的类称为根类,更通用地称为内部类。特定排队规则中的任何终端类都称为叶子类,类似于类的树结构。除了使用比喻性语言将结构描绘成树之外,家庭关系语言也很常见。


7.1. HTB,分层令牌桶

HTB 使用令牌和令牌桶的概念,以及基于类的系统和 filter(过滤器),以实现对流量的复杂和精细控制。凭借复杂的 借用模型,HTB 可以执行各种复杂的流量控制技术。立即使用 HTB 的最简单方法之一是 整形

通过理解 令牌令牌桶,或者通过掌握 TBF 的功能,HTB 应该仅仅是逻辑上的一步。此排队规则允许用户定义所使用的令牌和令牌桶的特征,并允许用户以任意方式嵌套这些令牌桶。当与 分类 方案结合使用时,可以以非常精细的方式控制流量。

以下是使用 tc 工具在命令行上 HTB 语法的示例输出。尽管 tcng 的语法本身就是一种语言,但 HTB 的规则是相同的。

示例 10. tc HTB 用法

Usage: ... qdisc add ... htb [default N] [r2q N]
 default  minor id of class to which unclassified packets are sent {0}
 r2q      DRR quantums are computed as rate in Bps/r2q {10}
 debug    string of 16 numbers each 0-3 {0}

... class add ... htb rate R1 burst B1 [prio P] [slot S] [pslot PS]
                      [ceil R2] [cburst B2] [mtu MTU] [quantum Q]
 rate     rate allocated to this class (class can still borrow)
 burst    max bytes burst which can be accumulated during idle period {computed}
 ceil     definite upper class rate (no borrows) {rate}
 cburst   burst but for ceil {computed}
 mtu      max packet size we create rate map for {1600}
 prio     priority of leaf; lower are served first {0}
 quantum  how much bytes to serve from leaf at once {use r2q}

TC HTB version 3.3
      


7.1.1. 软件要求

与几乎所有其他讨论的软件不同,HTB 是一种较新的排队规则,您的发行版可能没有使用 HTB 所需的所有工具和功能。内核必须支持 HTB;内核版本 2.4.20 及更高版本在库存发行版中支持它,尽管较早的内核版本需要打补丁。要启用对 HTB 的用户级支持,请参阅 HTB,获取 iproute2 补丁以用于 tc


7.1.2. 整形

HTB 最常见的应用之一包括将传输的流量整形到特定速率。

所有整形都发生在叶子类中。整形不会发生在内部类或根类中,因为它们的存在只是为了建议 借用模型 应如何分配可用令牌。


7.1.3. 借用

HTB qdisc 的一个基本部分是借用机制。子类在超过 rate(速率)后从其父类借用令牌。子类将继续尝试借用,直到达到 ceil(上限),此时它将开始对数据包进行排队以进行传输,直到有更多令牌/ctokens 可用。由于只有两种主要类型的类可以使用 HTB 创建,因此下表和图表标识了各种可能的状态以及借用机制的行为。

表 2. HTB 类状态和可能采取的动作

类类型类状态HTB 内部状态采取的动作
leaf(叶子类)< 速率HTB_CAN_SEND(HTB_可以发送)叶子类将出队排队的字节,直到可用令牌(不超过突发数据包)
leaf(叶子类)> 速率, < ceil(上限)HTB_MAY_BORROW(HTB_可以借用)叶子类将尝试从父类借用令牌/ctokens。如果令牌可用,它们将以quantum(量子)增量借出,叶子类将出队最多cburst(上限突发)字节
leaf(叶子类)> ceil(上限)HTB_CANT_SEND(HTB_不能发送)不会出队任何数据包。这将导致数据包延迟,并将增加延迟以满足所需的速率。
inner, root(内部类,根类)< 速率HTB_CAN_SEND(HTB_可以发送)内部类将向子类借出令牌。
inner, root(内部类,根类)> 速率, < ceil(上限)HTB_MAY_BORROW(HTB_可以借用)内部类将尝试从父类借用令牌/ctokens,并以quantum(量子)增量借给竞争的子类,每个请求一次。
inner, root(内部类,根类)> ceil(上限)HTB_CANT_SEND(HTB_不能发送)内部类不会尝试从其父类借用,也不会向子类借出令牌/ctokens。

此图表标识了借用令牌的流动以及令牌如何向父类收费的方式。为了使借用模型工作,每个类都必须准确计算自身及其所有子类使用的令牌数量。因此,子类或叶子类中使用的任何令牌都将向每个父类收费,直到到达根类。

任何希望借用令牌的子类都将向其父类请求令牌,如果其父类也超过其速率,则将请求从其父类借用,直到找到令牌或到达根类为止。因此,令牌的借用流向叶子类,而令牌使用的收费流向根类。

请注意,在此图中,有几个 HTB 根类。这些根类中的每一个都可以模拟虚拟电路。


7.1.4. HTB 类参数

default(默认)

每个 HTB qdisc 对象的可选参数,默认default(默认)为 0,这会导致任何未分类的流量以硬件速度出队,完全绕过附加到出口rootqdisc。

速率

的任何类。用于设置限制传输流量的最小期望速度。这可以被视为承诺信息速率 (CIR) 的等效项,或给定叶子类的保证带宽。

ceil(上限)

ceil(上限)

burst(突发)

用于设置限制传输流量的最大期望速度。借用模型应说明如何使用此参数。这可以被视为 “突发带宽” 的等效项。burst(突发)burst(突发)

cburst(上限突发)

这是 rate(速率)令牌桶的大小(参见 令牌和令牌桶)。HTB 将出队cburst(上限突发)字节,然后等待更多令牌的到达。

quantum(量子)

cburst(上限突发)quantum(量子)这是 ceil(上限)令牌桶的大小(参见 令牌和令牌桶)。HTB 将出队

字节,然后等待更多 ctokens 的到达。

quantum(量子)字节,然后等待更多 ctokens 的到达。这是 HTB 用于控制借用的关键参数。通常,正确的

量子由 HTB 计算,而不是由用户指定。调整此参数会对争用下的借用和整形产生巨大影响,因为它既用于在超过 rate(速率)(但低于 ceil(上限))的子类之间拆分流量,也用于从这些相同类传输数据包。

prio(优先级)


r2q

同样,通常为用户计算,

  • 是 HTB 的提示,以帮助确定特定类的最佳 quantum(量子)。

  • mtu(最大传输单元)速率7.1.5. 规则ceil(上限)以下是一些使用 HTB 的一般指南,这些指南来自 http://docum.org/LARTC 邮件列表。这些规则只是给初学者的建议,旨在最大限度地发挥 HTB 的优势,直到更好地理解 HTB 的实际应用。速率使用 HTB 进行整形仅发生在叶子类中。另请参阅 第 7.1.2 节速率由于 HTB 不在叶子类以外的任何类中进行整形,因此叶子类的速率ceil(上限) - 速率之和不应超过父类的上限

    。理想情况下,子类的速率

  • quantum(量子)之和应与父类的速率速率匹配,从而允许父类在子类之间分配剩余带宽(上限ceil(上限).

  • quantum(量子))。quantum(量子)使用 HTB 的这个关键概念值得重复。只有叶子类实际整形数据包;数据包仅在这些叶子类中延迟。内部类(一直到根类)的存在是为了定义借用/借出如何发生(另请参阅 第 7.1.3 节)。

  • 上限quantum(量子)仅在类超过速率quantum(量子)但低于上限

  • 时使用。mtu(最大传输单元)应设置为 MTU 或更高。即使量子

  • 太小,HTB 至少会在每个服务机会出队单个数据包。在这种情况下,它将无法准确计算实际消耗的带宽 [9]


父类以量子

HFSC 类别的排队规则 (qdisc) 平衡了对延迟敏感的流量和对吞吐量敏感的流量。在拥塞或积压状态下,HFSC 排队机制会在需要时根据服务曲线定义交织延迟敏感型流量。阅读德语版的 Linux 实现 HFSC Scheduling mit Linux,或阅读英语翻译版 HFSC Scheduling with Linux。原始研究文章 用于链路共享、实时和优先级分级的分层公平服务曲线算法 也仍然可用。

本节将在稍后完成。


7.3. PRIO,优先级调度器

PRIO 类别的排队规则 (qdisc) 基于一个非常简单的原则工作。当它准备出队一个数据包时,首先检查第一个类别是否有数据包。如果有数据包,则将其出队。如果没有数据包,则检查下一个类别,直到排队机制没有更多类别要检查为止。

本节将在稍后完成。


7.4. CBQ,基于类别的排队

CBQ 是流量控制系统的经典实现(也称为老牌实现)。本节将在稍后完成。


8. 规则、指南和方法


8.1. Linux 流量控制的一般规则

有一些通用的规则可以简化对 Linux 流量控制的研究。Linux 下的流量控制结构是相同的,无论初始配置是使用 tcng 还是 tc 完成的。

  • 任何执行整形功能的路由器都应该是链路上的瓶颈,并且应该以略低于最大可用链路带宽的速度进行整形。这可以防止在其他路由器中形成队列,从而最大限度地控制数据包延迟/延缓到整形设备。

  • 设备只能对其传输的流量进行整形 [10]。由于流量已经在输入接口上接收,因此无法对其进行整形。解决此问题的传统方案是入口策略器。

  • 每个接口都必须有一个 qdisc。当没有其他排队规则 (qdisc) 显式附加到接口时,将使用默认的排队规则 (qdisc)(pfifo_fast 排队规则 (qdisc))。

  • 添加到没有子类接口的 类别排队规则 (classful qdiscs) 之一通常只会消耗 CPU 而没有任何好处。

  • 任何新创建的类都包含一个 FIFO。此排队规则 (qdisc) 可以显式地替换为任何其他排队规则 (qdisc)。如果子类附加到此类,则 FIFO 排队规则 (qdisc) 将被隐式删除。

  • 直接附加到root排队规则 (qdisc) 的类可以用于模拟虚拟电路。

  • 过滤器 (filter) 可以附加到类或 类别排队规则 (classful qdiscs) 之一。


8.2. 处理具有已知带宽的链路

HTB 是在具有已知带宽的链路上使用的理想 qdisc,因为最内层(根层)类可以设置为给定链路上可用的最大带宽。流可以进一步细分为子类,从而允许为特定类别的流量保证带宽,或者允许优先处理特定类型的流量。


8.3. 处理具有可变(或未知)带宽的链路

理论上,PRIO 调度器是可变带宽链路的理想匹配,因为它是一个工作守恒型 qdisc(这意味着它不提供 整形)。对于具有未知或波动带宽的链路,PRIO 调度器只是优先出队最高优先级频带中的任何可用数据包,然后降至较低优先级的队列。


8.4. 基于流共享/拆分带宽

在网络带宽的多种竞争类型中,这是一般情况下最容易解决的竞争类型之一。通过使用 SFQ 排队规则 (qdisc),特定队列中的流量可以分为多个流,每个流将在该队列中获得公平的服务(在该队列内部)。行为良好的应用程序(和用户)会发现使用 SFQ 和 ESFQ 足以满足大多数共享需求。

这些公平排队算法的致命弱点是行为不端的用户或应用程序,它们同时打开许多连接(例如,eMule、eDonkey、Kazaa)。通过创建大量单独的流,应用程序可以主导公平排队算法中的时隙。重申一下,公平排队算法不知道单个应用程序正在生成大部分流,并且无法惩罚用户。需要其他方法。


8.5. 基于 IP 共享/拆分带宽

对于许多管理员来说,这是在用户之间分配带宽的理想方法。不幸的是,没有简单的解决方案,并且随着共享网络链路的机器数量的增加,它变得越来越复杂。

要在N个 IP 地址之间公平地分配带宽,必须有N个类。


9. 用于 QoS/流量控制的脚本


9.1. wondershaper

更多内容即将推出,请参阅 wondershaper


9.2. ADSL 带宽 HOWTO 脚本 (myshaper)

更多内容即将推出,请参阅 myshaper


9.3. htb.init

更多内容即将推出,请参阅 htb.init


9.4. tcng.init

更多内容即将推出,请参阅 tcng.init


9.5. cbq.init

更多内容即将推出,请参阅 cbq.init


10. 图表


10.1. 通用图表

下面是类别排队规则 (classful queuing discipline) 组件之间关系的一般图表(图中为 HTB)。该图表的更大版本 可用

示例 11. HTB tcng 配置示例

/*
 *
 *  possible mock up of diagram shown at
 *  http://linux-ip.net/traffic-control/htb-class.png
 *
 */

$m_web = trTCM (
                 cir 512  kbps,  /* commited information rate */
                 cbs 10   kB,    /* burst for CIR */
                 pir 1024 kbps,  /* peak information rate */
                 pbs 10   kB     /* burst for PIR */
               ) ;

dev eth0 {
    egress {

        class ( <$web> )  if tcp_dport == PORT_HTTP &&  __trTCM_green( $m_web );
        class ( <$bulk> ) if tcp_dport == PORT_HTTP && __trTCM_yellow( $m_web );
        drop              if                              __trTCM_red( $m_web );
        class ( <$bulk> ) if tcp_dport == PORT_SSH ;

        htb () {  /* root qdisc */

            class ( rate 1544kbps, ceil 1544kbps ) {  /* root class */

                $web  = class ( rate 512kbps, ceil  512kbps ) { sfq ; } ;
                $bulk = class ( rate 512kbps, ceil 1544kbps ) { sfq ; } ;

            }
        }
    }
}
      


11. 注释的流量控制链接

本节列出了一些关于流量控制和 Linux 流量控制软件的文档链接。每个链接都将列出一个关于该站点内容的简要描述。

注释

[1]

有关特定流量控制机制、内核或命令行实用程序的使用或安装的更多详细信息,请参阅 第 5 节

[2]

这种排队模型长期以来一直被文明国家用于公平分配稀缺的食物或物资。据说威廉·福克纳曾走到队伍前面去领取他的那份冰,这证明并非所有人都喜欢 FIFO 模型,并为我们提供了一个考虑优先级排队的模型。

[3]

类似地,整个流量控制系统对于将数据包排队到该层的更高层而言,表现为一个队列或调度器。

[4]

这种平滑效果并非总是理想的,因此 HTB 参数具有 burst 和 cburst。

[5]

类别排队规则 (classful qdisc) 只能具有其类型的子类。例如,HTB 排队规则 (qdisc) 只能将 HTB 类作为子类。CBQ 排队规则 (qdisc) 不能将 HTB 类作为子类。

[6]

在这种情况下,您将拥有一个 过滤器 (filter),它使用 分类器 (classifier) 来选择您希望丢弃的数据包。然后,您将使用 策略器 (policer),并使用如下所示的丢弃操作 police rate 1bps burst 1 action drop/drop

[7]

我不知道这些数字的范围和基数。我认为它们是 u32 十六进制,但需要确认这一点。

[8]

本示例中列出的选项取自 2.4.20 内核源代码树。确切的选项可能因内核版本而略有不同,具体取决于补丁和新的调度器和分类器。

[9]

在这种情况下,HTB 将错误地报告带宽使用情况。它将计算quantum(量子)而不是实际出队数据包大小所使用的带宽。这可能会很快歪曲结果。

[10]

实际上,中间排队设备 (IMQ) 模拟了一个输出设备,流量控制结构可以附加到该设备上。这种巧妙的解决方案允许网络设备以与出口流量相同的方式整形入口流量。尽管与规则存在明显的矛盾,但 IMQ 对内核而言显示为一个设备。因此,并没有违反规则,而是对该规则进行了狡猾的重新解释。