我读过原文SIGCOMM '97 PostScript 论文关于 HFSC,这非常技术性,但我理解基本概念。您可以指定凸或凹服务曲线,而不是给出线性服务曲线(与几乎所有其他调度算法一样),从而可以将带宽和延迟分离。但是,即使本文提到正在使用的调度算法类型(实时和链路共享),它总是只提到每个调度类的一条曲线(通过指定此曲线来完成分离,因此只需要一条曲线)。
现在 HFSC 已经为 BSD(OpenBSD、FreeBSD 等)实现了,使用ALTQ 调度框架并且它已经使用 Linux 实现TC调度框架(iproute2 的一部分)。两种实现都增加了两条额外的服务曲线,分别是不是在原始论文中!实时服务曲线和上限服务曲线。再次提醒,请注意原始论文提到了两种调度算法(实时和链接共享),但在该论文中,这两种算法都使用一条服务曲线。从来没有像您目前在 BSD 和 Linux 中看到的那样,这两种算法都有两条独立的服务曲线。
更糟糕的是,有些版本的 ALTQ 似乎为 HSFC 添加了额外的队列优先级(原始论文中也没有优先级这样的东西)。我发现几个 BSD HowTo 提到了这个优先级设置(即使最新版 ALTQ 的手册页不知道 HSFC 有这样的参数,所以官方甚至认为它不存在)。
这一切都使得 HFSC 调度比原始论文中描述的算法更加复杂,互联网上有大量教程,它们经常相互矛盾,一个声称与另一个相反。这可能是没有人真正了解 HFSC 调度如何真正工作的主要原因。在我提问之前,我们需要某种示例设置。我将使用一个非常简单的示例设置,如下图所示:
替代文本 http://f.imagehost.org/0177/hfsc-test-setup.png
由于教程之间相互矛盾,因此我无法回答以下一些问题:
我到底需要实时曲线干什么?假设 A1、A2、B1、B2 都是 128 kbit/s 链路共享(两者都没有实时曲线),那么如果根有 512 kbit/s 可供分配(当然 A 和 B 都是 256 kbit/s),那么它们中的每一个都会获得 128 kbit/s,对吗?为什么我还要给 A1 和 B1 一个 128 kbit/s 的实时曲线?这有什么用?给这两个更高的优先级?根据原始论文,我可以使用曲线,这毕竟是 HFSC 的意义所在。通过为这两个类别赋予 [256kbit/s 20ms 128kbit/s] 曲线,这两个类别的优先级自动比 A2 和 B2 高出两倍(平均仍然只有 128 kbit/s)
实时带宽是否计入链路共享带宽?例如,如果 A1 和 B1 都只有 64kbit/s 实时带宽和 64kbit/s 链路共享带宽,这是否意味着一旦通过实时方式为他们提供 64kbit/s,他们的链路共享要求也会得到满足(他们可能会获得额外的带宽,但让我们暂时忽略这一点)或者这是否意味着他们通过链路共享获得了另外 64 kbit/s?那么每个类的带宽“要求”是否都是实时加链路共享?或者,如果链路共享曲线高于实时曲线(当前链路共享要求等于指定的链路共享要求减去已提供给此类的实时带宽),则类的要求是否高于实时曲线?
上限曲线是否也适用于实时,只适用于链接共享,还是两者兼而有之?有些教程说一种方式,有些则说另一种方式。有些甚至声称上限是实时带宽 + 链接共享带宽的最大值?真相是什么?
假设 A2 和 B2 都是 128 kbit/s,那么 A1 和 B1 是仅 128 kbit/s 链路共享,还是 64 kbit/s 实时和 128 kbit/s 链路共享,会有什么区别吗?如果有,有什么区别?
如果我使用单独的实时曲线来提高类别的优先级,我为什么还需要“曲线”呢?为什么实时不是一个固定值,链接共享也不是一个固定值?为什么两者都是曲线?原始论文中明确指出了对曲线的需求,因为每个类别只有一个这种属性。但是现在,有三个属性(实时、链接共享和上限),为什么我还需要每个属性上的曲线呢?我为什么要曲线形状(不是平均带宽,而是它们的斜率)对于实时和链接共享流量有什么不同?
根据现有的少量文档,内部类(A 类和 B 类)的实时曲线值完全被忽略,它们只应用于叶类(A1、A2、B1、B2)。如果这是真的,为什么ALTQ HFSC 示例配置(搜索3.3 示例配置) 在内部类上设置实时曲线,并声称这些曲线设置了这些内部类的保证速率?这不是完全没有意义的吗?(注意:pshare 在 ALTQ 中设置链接共享曲线并计算实时曲线;您可以在示例配置上方的段落中看到这一点)。
有些教程说所有实时曲线的总和不得高于线速度的 80%,而另一些教程则说它不得高于线速度的 70%。哪一个是正确的,或者它们可能都是错误的?
一个教程说你应该忘记所有的理论。不管事情如何实际运作(调度程序和带宽分配),请根据以下“简化思维模型”想象三条曲线:实时是此类始终会获得的保证带宽。链路共享是此类希望完全满足的带宽,但无法保证满足。如果带宽过剩,该类甚至可能会获得比满足所需的带宽更多的带宽,但它可能永远不会使用超过上限的带宽。要使所有这些发挥作用,所有实时带宽的总和不得超过线速的 xx%(请参阅上面的问题,百分比会有所不同)。问题:这或多或少是准确的,还是对 HSFC 的完全误解?
如果上述假设确实准确,那么该模型中的优先级在哪里?例如,每个类别可能都有实时带宽(保证)、链路共享带宽(不保证)和可能的上限,但仍然有些类别比其他类别具有更高的优先级需求。在这种情况下,我仍然必须以某种方式确定优先级,即使在这些类别的实时流量中也是如此。我会根据曲线的斜率确定优先级吗?如果是这样,哪条曲线?实时曲线?链路共享曲线?上限曲线?所有曲线?我会给它们所有相同的斜率还是每个不同的斜率,以及如何找出正确的斜率?
我仍然没有放弃希望,这个世界上至少有少数人真正理解 HFSC,并能够准确回答所有这些问题。而且答案不会相互矛盾,这真的很好 ;-)
答案1
阅读有关 HFSC 及其同类的论文并不是理解它的好方法。HFSC 论文的主要目标是提供对其主张的严格数学证明,而不是解释其工作原理。事实上,仅从 HFSC 论文中您无法理解其工作原理,您还必须阅读它引用的论文。如果您对该主张或其证明有疑问,那么联系论文作者可能是一个好主意,否则我怀疑他们不会有兴趣听取您的意见。
我写过HFSC 教程。如果下面的解释不清楚,请阅读它。
我到底需要实时曲线干什么?假设 A1、A2、B1、B2 都是 128 kbit/s 链路共享(两者都没有实时曲线),那么如果根有 512 kbit/s 可供分配(当然 A 和 B 都是 256 kbit/s),那么它们中的每一个都会获得 128 kbit/s,对吗?为什么我还要为 A1 和 B1 提供 128 kbit/s 的实时曲线?这有什么用?给这两个更高的优先级?根据原始论文,我可以使用曲线赋予它们更高的优先级,毕竟这就是 HFSC 的意义所在。通过为这两个类提供 [256kbit/s 20ms 128kbit/s] 的曲线,它们的优先级自动是 A2 和 B2 的两倍(平均仍然只获得 128 kbit/s)
实时曲线和链路共享曲线的评估方式不同。实时曲线考虑了类在其整个历史中所做的事情。它必须这样做才能提供准确的带宽和延迟分配。缺点是它不是大多数人直观认为的那样公平的。在实时情况下,如果某个类在没有其他人需要时借用带宽,则当其他人稍后需要时,该类会受到惩罚。这意味着在实时保证下,某个类可能长时间得不到带宽,因为它在没有人需要时使用了带宽。
链路共享是公平的,因为它不会因为使用空闲带宽而惩罚某个类。然而,这意味着它无法提供强大的延迟保证。
将链路共享与提供延迟保证分开是 HFSC 提出的新内容,论文在开篇就这么说了:在本文中,我们研究了支持链路共享和保证实时服务以及解耦延迟(优先级)和带宽分配的分层资源管理模型和算法。 这句话中的关键词是“解耦”。翻译过来就是,你需要说明如何与 ls 共享未使用的带宽,并指定 rt 需要哪些实时保证(又称延迟保证)。两者是正交的。
实时带宽计入链路共享带宽吗?
是的。在 HFSC 论文中,他们根据类自积压(即有数据包等待发送)以来发送的内容来定义带宽。rt 和 ls 之间的唯一区别是 rt 从每次类积压时开始向前看,并从该集合中计算最低保证带宽,而链路共享仅从类上次积压时开始看。因此 rt 考虑的字节比 ls 多,但 ls 考虑的每个字节也被 rt 考虑。
上限曲线是否也适用于实时,仅适用于链接共享,还是两者兼而有之?
上限不会阻止数据包的发送以满足实时条件。在实时条件下发送的数据包仍计入上限,因此可能会延迟将来在链接共享条件下发送的数据包。这是实时和链接共享之间的另一个区别。
假设 A2 和 B2 都是 128 kbit/s,那么 A1 和 B1 是仅 128 kbit/s 链路共享,还是 64 kbit/s 实时和 128 kbit/s 链路共享,会有什么区别吗?如果有,有什么区别?
是的,这确实有区别。如上所述,如果您使用实时,则延迟是有保证的,但链接共享不公平(特别是类可能会遭受带宽不足),并且不会强制执行上限。如果您使用链接共享,则延迟不能得到保证,但链接共享是公平的,没有带宽不足的风险,并且会强制执行上限。总是在链接共享之前检查实时,但这并不一定意味着链接共享将被忽略。这是因为数据包的计数方式不同。由于历史记录是实时考虑的,因此数据包可能不需要满足实时保证(因为从历史记录中包含了一个计数),但需要满足链接共享,因为它忽略了历史数据包。
如果我使用单独的实时曲线来提高类别的优先级,我为什么还需要“曲线”呢?为什么实时和链接共享不是一个平坦值?为什么两者都是曲线?原始论文中对曲线的需求很明显,因为每个类别只有一个这种属性。但是现在,有三个属性(实时、链接共享和上限),为什么我仍然需要每个属性的曲线?为什么我希望实时和链接共享流量的曲线形状(不是平均带宽,而是它们的斜率)不同?
实时控制曲线允许您将某一特定流量类别(例如 VOIP)的紧密延迟换成其他流量类别(例如电子邮件)的较差延迟。在决定在实时约束下发送哪个数据包时,HFSC 会选择最先完成发送的数据包。但是,它不使用链路的带宽来计算这一点,而是使用实时曲线分配的带宽。因此,如果我们有长度相同的 VOIP 和电子邮件数据包,并且 VOIP 数据包具有凸曲线,如果其比电子邮件的凹曲线高出 10 倍,则将在第一个电子邮件数据包之前发送 10 个 VOIP 数据包。但这只发生在突发时间内,最多应该是发送几个数据包所需的时间 - 即毫秒。此后,VOIP 曲线应该趋于平缓,除非 VOIP 暂时后退(鉴于 VOIP 是一种低带宽应用,它应该会后退),否则 VOIP 将不会获得任何未来的提升。所有这些的最终结果是确保前几个 VOIP 数据包比其他任何东西都发送得更快,从而使 VOIP 具有较低的延迟,但电子邮件的延迟较高。
正如我之前所说,由于链接共享不考虑历史记录,因此无法提供延迟保证。对于像 VOIP 这样的实时流量,需要坚如磐石的保证。但是,平均而言,链接共享凸曲线仍会为其流量提供延迟增加。这只是没有保证。对于大多数事情来说,这没问题,例如通过电子邮件传输的网络流量。
根据现有的少量文档,实时曲线值对于内部类(A 类和 B 类)完全被忽略,它们只应用于叶类(A1、A2、B1、B2)。如果这是真的,为什么 ALTQ HFSC 示例配置(搜索 3.3 示例配置)在内部类上设置实时曲线并声称这些曲线设置了这些内部类的保证速率?这不是完全没有意义的吗?(注意:pshare 在 ALTQ 中设置链接共享曲线并绘制实时曲线;您可以在示例配置上方的段落中看到这一点)。
文档是正确的。层次结构(以及内部节点)对实时计算没有任何影响。我无法告诉你为什么 ALTQ 显然认为它有影响。
有些教程说所有实时曲线的总和不得高于线速度的 80%,而另一些教程则说它不得高于线速度的 70%。哪一个是正确的,或者它们可能都是错误的?
两者都是错误的。如果 70% 或 80% 的流量具有必须实时指定的硬延迟要求,那么现实情况是,您几乎肯定无法通过所使用的链接满足这些要求。您需要更快的链接。
有人认为将 80% 的流量指定为实时流量的唯一原因是,他们将实时流量作为优先级提升。是的,为了提供延迟保证,您实际上是在提高某些数据包的优先级。但这只能持续几毫秒。这是链路可以应对的全部,并且仍能提供延迟保证。
需要延迟保证的流量非常少。VOIP 是其中之一,NTP 是另一个。其余的都应该通过链接共享来完成。如果你想让网络变快,你就可以通过分配大部分链接容量来让它变快。这种共享是长期保证。如果您希望它具有较低的延迟(平均而言),请在链接共享下为其提供凸曲线。
一个教程说你应该忘记所有的理论。不管事情如何实际运作(调度程序和带宽分配),请根据以下“简化思维模型”想象三条曲线:实时是此类始终会获得的保证带宽。链路共享是此类希望完全满足的带宽,但无法保证满足。如果带宽过剩,该类甚至可能会获得比满足所需的带宽更多的带宽,但它可能永远不会使用超过上限的带宽。要使所有这些发挥作用,所有实时带宽的总和不得超过线速的 xx%(请参阅上面的问题,百分比会有所不同)。问题:这或多或少是准确的,还是对 HSFC 的完全误解?
这是很好的描述上限。虽然链接共享描述严格来说准确无误,但它具有误导性。虽然链接共享确实不能像实时那样提供硬延迟保证,但它在为类分配带宽方面比其竞争对手(如 CBQ 和 HTB)做得更好。因此,在说链接共享“不提供保证”时,它将其保持在任何其他调度程序都无法提供的更高标准。
实时的描述既准确又具有误导性,我甚至认为它是错误的。顾名思义,实时的目的不是提供保证带宽。而是提供保证延迟 - 即数据包立即发送,而不是根据链接的使用方式在某个随机时间后发送。大多数流量不需要保证延迟。
话虽如此,实时也不能提供完美的延迟保证。如果链路不是由链路共享管理的,那么它可以,但大多数用户希望同时拥有两者的额外灵活性,而且这并非免费提供。实时可能会在发送一个 MTU 数据包所需的时间内错过其延迟截止时间。(如果发生这种情况,那是因为 MTU 数据包链路共享偷偷溜进来,而实时保持链路空闲,以防它收到具有短截止时间且必须立即发送的数据包。这是链路共享和实时之间的另一个区别。为了提供其保证,实时可能会故意保持线路空闲,即使有数据包要发送,从而提供低于 100% 的链路利用率。链路共享始终使用 100% 的链路可用容量。与实时不同,可以说是“工作保留”。)
可以说实时提供硬延迟保证的原因是延迟是有限制的。因此,如果您尝试在 1Mbit/sec 链接上提供 20ms 延迟保证,并且链接共享正在发送 MTU 大小(1500 字节)的数据包,您知道其中一个数据包将需要 12ms 才能发送。因此,如果您告诉实时您想要 8ms 延迟,您仍然可以满足 20ms 的截止时间 - 绝对保证。
如果上述假设确实准确,那么该模型中的优先级在哪里?例如,每个类别可能都有实时带宽(保证)、链路共享带宽(不保证)和可能的上限,但仍然有些类别比其他类别具有更高的优先级需求。在这种情况下,我仍然必须以某种方式确定优先级,即使在这些类别的实时流量中也是如此。我会根据曲线的斜率确定优先级吗?如果是这样,哪条曲线?实时曲线?链路共享曲线?上限曲线?所有曲线?我会给它们所有相同的斜率还是每个不同的斜率,以及如何找出正确的斜率?
没有优先级模型。说真的。如果你想给流量绝对优先级,使用 pfifo。这就是它的用途。但也要注意,如果你给网络流量绝对优先级,而不是电子邮件流量,这意味着让网络流量饱和链接,因此没有电子邮件数据包通过,根本. 然后,您的所有电子邮件连接都将断开。
实际上,没有人想要这种优先级。他们想要的是 HFSC 提供的。如果您确实有实时流量,HFSC 会提供。但那将全部都是东西。对于其余部分,HFSC 允许您说“在拥塞的链接上,将 90% 分配给网络,让电子邮件以 10% 的速度缓慢通过,哦,快速发送奇怪的 DNS 数据包,但不要让某人用它对我进行 DOS 攻击。”
答案2
您可以用不同的名称定义曲线:
- rt,实时曲线,带宽/延迟保证。
- ls、链路共享曲线、带宽/延迟共享(基于邻居叶子的配置)
- ul,上限曲线,可能达到的最大带宽/延迟。
我到底需要实时曲线干什么?假设 A1、A2、B1、B2 都是 128 kbit/s 链路共享(两者都没有实时曲线),那么如果根有 512 kbit/s 可供分配(当然 A 和 B 都是 256 kbit/s),那么它们中的每一个都会获得 128 kbit/s,对吗?为什么我还要为 A1 和 B1 提供 128 kbit/s 的实时曲线?这有什么用?给这两个更高的优先级?根据原始论文,我可以使用曲线赋予它们更高的优先级,毕竟这就是 HFSC 的意义所在。通过为这两个类提供 [256kbit/s 20ms 128kbit/s] 的曲线,它们的优先级自动是 A2 和 B2 的两倍(平均仍然只获得 128 kbit/s)
当您在 HFSC 中仅使用速率进行定义时,它会自动将“dmax”设置为 0。这基本上意味着它不考虑延迟。良好的 HFSC 配置应包括您要用于类的带宽和延迟边界,否则算法无法准确确定类应获得多少优先级。
只要您为数据包赋予优先级,其他数据包的优先级就必须降低。根据“dmax”和“rate”值,所有类都将使用虚拟计时器进行多路复用。有关更多信息,请参阅 tc-hfsc(7)。
实时带宽是否计入链路共享带宽?例如,如果 A1 和 B1 都只有 64kbit/s 实时带宽和 64kbit/s 链路共享带宽,这是否意味着一旦通过实时方式为他们提供 64kbit/s 带宽,他们的链路共享要求也会得到满足(他们可能会获得额外的带宽,但让我们暂时忽略这一点)或者这是否意味着他们通过链路共享获得了另外 64 kbit/s?那么每个类的带宽“要求”是否都是实时加链路共享?或者,如果链路共享曲线高于实时曲线(当前链路共享要求等于指定的链路共享要求减去已提供给此类的实时带宽),则类的要求是否高于实时曲线?
如果流量未超出类的链接共享定义的边界,则永远不会使用实时曲线。在这种情况下定义实时曲线可以让你例如:保证一定的“dmax”。
如果您的链接共享定义完美无缺,那么您就不需要实时曲线。您可以只定义服务曲线 (sc),但这会使您的配置工作更加困难。
上限曲线是否也适用于实时,只适用于链接共享,还是两者兼而有之?有些教程说一种方式,有些则说另一种方式。有些甚至声称上限是实时带宽 + 链接共享带宽的最大值?真相是什么?
您的类别的上限曲线仅适用于链接共享,当您定义上限曲线时,您必须定义链接共享曲线。但是,父类别的上限曲线仍然适用。
假设 A2 和 B2 都是 128 kbit/s,那么 A1 和 B1 是仅 128 kbit/s 链路共享,还是 64 kbit/s 实时和 128 kbit/s 链路共享,会有什么区别吗?如果有,有什么区别?
例如,如果 A2 = 0 kbits/s 且 B2 = 256 kbits/s,则存在细微差别。那么 A2 的虚拟时间将达到最大值。每当在 A2 中对数据包进行分类时,它们都会被立即处理。然而,B2 的实时曲线仍将确保能够至少传输 64 kbit/s
如果我使用单独的实时曲线来提高类别的优先级,为什么我还需要“曲线”呢?为什么实时不是一个平坦值,而链接共享也不是一个平坦值?为什么两者都是曲线?原始论文中对曲线的需求很明显,因为每个类别只有一个这种属性。但是现在,有三个属性(实时、链接共享和上限),为什么我仍然需要每个属性的曲线?为什么我希望实时和链接共享流量的曲线形状(不是平均带宽,而是它们的斜率)不同?
实时曲线不会在邻近叶子之间共享流量,但链路共享曲线会。
根据现有的少量文档,实时曲线值对于内部类(A 类和 B 类)完全被忽略,它们只应用于叶类(A1、A2、B1、B2)。如果这是真的,为什么 ALTQ HFSC 示例配置(搜索 3.3 示例配置)在内部类上设置实时曲线并声称这些曲线设置了这些内部类的保证速率?这不是完全没有意义的吗?(注意:pshare 在 ALTQ 中设置链接共享曲线并绘制实时曲线;您可以在示例配置上方的段落中看到这一点)。
内部类确实会忽略实时曲线,它们只适用于叶类。但是,在叶类上进行计算时会考虑这些内部类上定义的实时曲线。
有些教程说所有实时曲线的总和不得高于线速度的 80%,而另一些教程则说它不得高于线速度的 70%。哪一个是正确的,或者它们可能都是错误的?
它们的意思是:您无法对所有流量进行优先级排序...每当您为数据包赋予优先级时,其他数据包的优先级都必须降低。如果您过度保证,算法将变得毫无意义。定义获得优先级的类别和可能受到影响的类别。
一个教程说你应该忘记所有的理论。不管事情如何实际运作(调度程序和带宽分配),请根据以下“简化思维模型”想象三条曲线:实时是此类始终会获得的保证带宽。链路共享是此类希望完全满足的带宽,但无法保证满足。如果带宽过剩,该类甚至可能会获得比满足所需的带宽更多的带宽,但它可能永远不会使用超过上限的带宽。要使所有这些发挥作用,所有实时带宽的总和不得超过线速的 xx%(请参阅上面的问题,百分比会有所不同)。问题:这或多或少是准确的,还是对 HSFC 的完全误解?
这是对的。
如果上述假设确实准确,那么该模型中的优先级在哪里?例如,每个类别可能都有实时带宽(保证)、链路共享带宽(不保证)和可能的上限,但仍然有些类别比其他类别具有更高的优先级需求。在这种情况下,我仍然必须以某种方式确定优先级,即使在这些类别的实时流量中也是如此。我会根据曲线的斜率确定优先级吗?如果是这样,哪条曲线?实时曲线?链路共享曲线?上限曲线?所有曲线?我会给它们所有相同的斜率还是每个不同的斜率,以及如何找出正确的斜率?
例如,HFSC 和 HTB 之间的区别在于,HFSC 允许您精确定义您希望它具有的优先级。您可以通过使用“dmax”值定义最小和最大边界来实现这一点。
答案3
最后,有一个指南似乎解释了大多数不一致性以及当前的实现与原始论文的不同之处:
http://manpages.ubuntu.com/manpages/precise/man7/tc-hfsc.7.html
根据本指南,许多其他关于 HFSC 的指南和论坛帖子完全是胡说八道;它只是表明了 HFSC 有多么复杂,因为许多看似专家并假装完全了解 HFSC 的人实际上只具备部分知识,并基于对概念以及所有这些设置如何协同工作的误解做出错误的陈述。
我想我最终会放弃 HFSC。如果你能正确设置 HFSC,这可能是你能获得的最佳 QoS,但你彻底搞砸的可能性远高于你成功的可能性。
答案4
如果您无法联系原作者,那么我将尝试以下方法:
- 进入 Linux 内核源代码树并找到实现“TC 调度框架”的 C 文件
- 查看标题并找到代码的作者。
- 向“TC 调度框架”的程序员发送电子邮件,询问他们有关其实现的文献。
还可以尝试查看引用此文的其他较新论文。可能有较新的论文是该领域研究的延续,并且可能包含有关您提出的问题的更多信息。