本文档中概述的方法应该适用于其他 Linux 配置,但除了以下配置外,尚未在任何其他配置中进行测试
Red Hat Linux 7.3
2.4.18-5 内核,完全启用 QoS 支持(模块正常),并包含以下内核补丁(最终可能会包含在更高版本的内核中)
HTB 队列 - http://luxik.cdi.cz/~devik/qos/htb/
注意:据报告,自版本 2.4.18-3 起随 Mandrake (8.1, 8.2) 发布的内核已经为 HTB 打了补丁。
IMQ 设备 - http://luxik.cdi.cz/~patrick/imq/
iptables v1.2.6a 或更高版本(Red Hat 7.3 随附的 iptables 版本缺少 length 模块)
为了保持简单,本文档中所有对网络设备和配置的引用都将参考以下网络布局图
<-- 128kbit/s -------------- <-- 10Mbit --> Internet <--------------------> | ADSL Modem | <-------------------- 1.5Mbit/s --> -------------- | | eth0 V ----------------- | | | Linux Router | | | ----------------- | .. | eth1..ethN | | V V Local Network |
数据包队列是为网络设备保存数据的桶,当数据无法立即发送时使用。大多数数据包队列使用 FIFO(先进先出)原则,除非它们已特别配置为其他方式。这意味着,当设备的数据包队列完全满时,最近放入队列的数据包将仅在当时队列中的所有其他数据包都已发送后才通过设备发送。
使用 ADSL 调制解调器,带宽是不对称的,通常下行 1.5Mbit/s,上行 128kbit/sec。虽然这是线路速度,但 Linux 路由器 PC 和 ADSL 调制解调器之间的接口通常为 10Mbit/s 或更高。如果到本地网络的接口也为 10Mbit/s,则当数据包从本地网络发送到互联网时,路由器上通常不会发生排队。数据包从 eth0 发送出去的速度与从本地网络接收的速度一样快。相反,数据包在 ADSL 调制解调器处排队,因为它们以 10Mbit/s 的速度到达,而仅以 128kbit/s 的速度发送。最终,ADSL 调制解调器的数据包队列将满,并且发送给它的任何更多数据包都将被静默丢弃。TCP 旨在处理这种情况,并将相应地调整其传输窗口大小,以充分利用可用带宽。
虽然数据包队列与 TCP 结合使用可以最有效地利用带宽,但大型 FIFO 队列会增加交互式流量的延迟。
另一种有点像 FIFO 的队列类型是 n 频段优先级队列。但是,n 频段优先级队列不是只有一个队列来排列数据包,而是有 n 个 FIFO 队列,数据包根据其分类放置在这些队列中。每个队列都有一个优先级,数据包始终从包含数据包的最高优先级队列中出队。使用此原则,FTP 数据包可以放置在比 telnet 数据包优先级更低的队列中,这样即使在 FTP 上传期间,单个 telnet 数据包也会跳过队列并立即发送。
本文档已修订为使用 Linux 中称为分层令牌桶 (HTB) 的新队列。HTB 队列非常像上面描述的 n 频段队列,但它具有限制每个类别的流量速率的能力。除此之外,它还能够在其他类别下设置流量类别,从而创建类别层次结构。完全描述 HTB 超出了本文档的范围,但更多信息可以在 http://www.lartc.org 找到
传入 ADSL 调制解调器的流量以与传出流量大致相同的方式排队,但队列位于您的 ISP 处。因此,您可能无法直接控制数据包的排队方式或哪些类型的流量获得优先处理。降低延迟的唯一方法是确保人们不会以太快的速度向您发送数据。不幸的是,没有办法直接控制数据包到达的速度,但由于您的大部分流量很可能是 TCP,因此有一些方法可以减慢发送者的速度
有意丢弃入站数据包 - TCP 旨在充分利用可用带宽,同时避免链路拥塞。这意味着在批量数据传输期间,TCP 将发送越来越多的数据,直到最终丢弃一个数据包。TCP 检测到这一点并减小其传输窗口。此循环在整个传输过程中持续进行,并确保数据尽可能快地移动。
操纵通告的接收窗口 - 在 TCP 传输期间,接收器会发回连续的确认 (ACK) 数据包流。ACK 数据包中包含窗口大小通告,该通告声明接收器应发送的最大未确认数据量。通过操纵出站 ACK 数据包的窗口大小,我们可以有意地减慢发送者的速度。目前,Linux 上没有(免费的)此类流控制的实现(但我可能正在开发一个!)。