如前所述,通过队列规则,我们改变了数据发送的方式。无类别的队列规则是指那些大致上接受数据,并且仅重新调度、延迟或丢弃数据的规则。
这些可以用于塑造整个接口的流量,而无需任何细分。在继续学习包含队列规则的分类队列规则之前,理解队列的这一部分至关重要!
到目前为止,使用最广泛的规则是 pfifo_fast 队列规则 - 这是默认规则。这也解释了为什么这些高级功能如此强大。它们只不过是“另一个队列”。
这些队列中的每一个都有特定的优点和缺点。并非所有队列都经过充分测试。
正如其名称所示,此队列是先进先出 (FIFO) 的,这意味着没有数据包会受到特殊待遇。至少,不完全是这样。此队列有 3 个所谓的“频带”。在每个频带内,应用 FIFO 规则。但是,只要频带 0 中有数据包在等待,频带 1 就不会被处理。频带 1 和频带 2 也是如此。
内核会遵守数据包的所谓服务类型标志,并注意将“最小延迟”数据包插入到频带 0 中。
不要将此无类别的简单队列规则与分类的 PRIO 队列规则混淆!尽管它们的行为类似,但 pfifo_fast 是无类别的,您无法使用 tc 命令向其添加其他队列规则。
您无法配置 pfifo_fast 队列规则,因为它已硬连线为默认值。以下是其默认配置方式
确定内核分配的数据包优先级如何映射到频带。映射基于数据包的 TOS 八位字节进行,如下所示
0 1 2 3 4 5 6 7 +-----+-----+-----+-----+-----+-----+-----+-----+ | | | | | PRECEDENCE | TOS | MBZ | | | | | +-----+-----+-----+-----+-----+-----+-----+-----+ |
四个 TOS 位(“TOS 字段”)定义为
Binary Decimcal Meaning ----------------------------------------- 1000 8 Minimize delay (md) 0100 4 Maximize throughput (mt) 0010 2 Maximize reliability (mr) 0001 1 Minimize monetary cost (mmc) 0000 0 Normal Service |
由于这四个位的右边有 1 位,因此 TOS 字段的实际值是 TOS 位的两倍。Tcpdump -v -v 向您显示整个 TOS 字段的值,而不仅仅是四个位。这是您在此表的第一列中看到的值
TOS Bits Means Linux Priority Band ------------------------------------------------------------ 0x0 0 Normal Service 0 Best Effort 1 0x2 1 Minimize Monetary Cost 1 Filler 2 0x4 2 Maximize Reliability 0 Best Effort 1 0x6 3 mmc+mr 0 Best Effort 1 0x8 4 Maximize Throughput 2 Bulk 2 0xa 5 mmc+mt 2 Bulk 2 0xc 6 mr+mt 2 Bulk 2 0xe 7 mmc+mr+mt 2 Bulk 2 0x10 8 Minimize Delay 6 Interactive 0 0x12 9 mmc+md 6 Interactive 0 0x14 10 mr+md 6 Interactive 0 0x16 11 mmc+mr+md 6 Interactive 0 0x18 12 mt+md 4 Int. Bulk 1 0x1a 13 mmc+mt+md 4 Int. Bulk 1 0x1c 14 mr+mt+md 4 Int. Bulk 1 0x1e 15 mmc+mr+mt+md 4 Int. Bulk 1 |
很多数字。第二列包含相关四个 TOS 位的值,后跟它们的翻译含义。例如,15 代表一个想要最低货币成本、最高可靠性、最大吞吐量和最小延迟的数据包。我会称之为“荷兰数据包”。
第四列列出了 Linux 内核如何解释 TOS 位,通过显示它们映射到的优先级。
最后一列显示了默认 priomap 的结果。在命令行上,默认 priomap 如下所示
1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 |
这意味着优先级 4,例如,被映射到频带编号 1。priomap 还允许您列出更高的优先级(> 7),这些优先级与 TOS 映射不对应,而是通过其他方式设置的。
RFC 1349 中的此表(阅读它以了解更多详细信息)告诉您应用程序很可能如何设置其 TOS 位
TELNET 1000 (minimize delay) FTP Control 1000 (minimize delay) Data 0100 (maximize throughput) TFTP 1000 (minimize delay) SMTP Command phase 1000 (minimize delay) DATA phase 0100 (maximize throughput) Domain Name Service UDP Query 1000 (minimize delay) TCP Query 0000 Zone Transfer 0100 (maximize throughput) NNTP 0001 (minimize monetary cost) ICMP Errors 0000 Requests 0000 (mostly) Responses <same as request> (mostly) |
此队列的长度是从接口配置中收集的,您可以使用 ifconfig 和 ip 查看和设置。要将队列长度设置为 10,请执行:ifconfig eth0 txqueuelen 10
您无法使用 tc 设置此参数!
令牌桶过滤器 (TBF) 是一种简单的队列规则,它仅传递以不超过某些管理设置速率到达的数据包,但有可能允许短暂的突发流量超过此速率。
TBF 非常精确,对网络和处理器友好。如果您只是想减慢接口速度,它应该是您的首选!
TBF 的实现包括一个缓冲区(桶),不断地以特定速率(令牌速率)填充一些称为令牌的虚拟信息片段。桶最重要的参数是其大小,即它可以存储的令牌数量。
将此算法与令牌和数据这两个流相关联,我们得到三种可能的场景
数据到达 TBF 的速率等于传入令牌的速率。在这种情况下,每个传入的数据包都有其匹配的令牌,并无延迟地通过队列。
数据到达 TBF 的速率小于令牌速率。只有一部分令牌在每个从队列中发送的数据包输出时被删除,因此令牌会累积,直到达到桶大小。未使用的令牌然后可以用于以超过标准令牌速率的速度发送数据,以防发生短暂的数据突发。
数据到达 TBF 的速率大于令牌速率。这意味着桶很快就会耗尽令牌,这将导致 TBF 暂时节流自身。这称为“超限情况”。如果数据包持续涌入,数据包将开始被丢弃。
最后一种情况非常重要,因为它允许管理性地塑造通过过滤器的数据可用的带宽。
令牌的累积允许短暂的超限数据突发仍然可以无损地通过,但任何持久的过载都会导致数据包不断延迟,然后被丢弃。
请注意,在实际实现中,令牌对应于字节,而不是数据包。
即使您可能不需要更改它们,tbf 也有一些旋钮可用。首先是始终可用的参数
Limit 是可以排队等待令牌可用的字节数。您也可以通过设置 latency 参数来以另一种方式指定此参数,该参数指定数据包可以在 TBF 中停留的最长时间。后一种计算考虑了桶的大小、速率以及可能的峰值速率(如果已设置)。
桶的大小,以字节为单位。这是令牌可以瞬间可用的最大字节数。一般来说,较大的整形速率需要较大的缓冲区。对于 Intel 上的 10mbit/s,如果您想达到配置的速率,您至少需要 10kbyte 的缓冲区!
如果您的缓冲区太小,则可能会丢弃数据包,因为每个定时器滴答到达的令牌多于桶中可容纳的令牌。
零大小的数据包不使用零带宽。对于以太网,没有数据包使用少于 64 字节。最小数据包单元确定数据包的最小令牌使用量。
速度旋钮。请参阅上面关于限制的说明!
如果桶包含令牌并且允许清空,则默认情况下它会以无限速度执行此操作。如果这是不可接受的,请使用以下参数
如果令牌可用并且数据包到达,则默认情况下它们会立即以“光速”发送出去。这可能不是您想要的,特别是如果您有一个大桶。
peakrate 可用于指定允许桶耗尽的速度。如果一切都按部就班,这可以通过释放一个数据包,然后等待足够长的时间,然后释放下一个数据包来实现。我们计算了我们的等待时间,以便我们以峰值速率发送。
但是,由于 Unix 的默认 10 毫秒定时器分辨率,对于 10.000 位平均数据包,我们仅限于 1mbit/s 的峰值速率!
如果您的常规速率超过 1mbit/s,则 1mbit/s 的峰值速率不是很有用。通过每个定时器滴答发送更多数据包,可以实现更高的峰值速率,这实际上意味着我们创建了第二个桶!
第二个桶默认为单个数据包,这根本不是桶。
要计算最大可能的峰值速率,请将配置的 mtu 乘以 100(或更正确地说,HZ,在 Intel 上为 100,在 Alpha 上为 1024)。
一个简单但 *非常* 有用的配置是这样的
# tc qdisc add dev ppp0 root tbf rate 220kbit latency 50ms burst 1540 |
好的,为什么这很有用?如果您有一个具有大队列的网络设备,例如 DSL 调制解调器或电缆调制解调器,并且您通过快速设备(例如以太网接口)与其通信,您会发现上传绝对会破坏交互性。
这是因为上传将填充调制解调器中的队列,该队列可能 *非常大*,因为这实际上有助于实现良好的数据吞吐量上传。但这不是您想要的,您希望队列不要太大,以便保持交互性,并且您仍然可以在发送数据时执行其他操作。
上面的行将发送速度降低到不会导致调制解调器中出现队列的速率 - 队列将位于 Linux 中,我们可以在其中将其控制在有限的大小。
将 220kbit 更改为您的上行链路的 *实际* 速度,减去几个百分点。如果您有一个非常快的调制解调器,请稍微提高“burst”。
随机公平队列 (SFQ) 是公平队列算法系列的一个简单实现。它不如其他算法精确,但它也需要较少的计算,同时几乎完全公平。
SFQ 中的关键词是会话(或流),它主要对应于 TCP 会话或 UDP 流。流量被划分为相当多的 FIFO 队列,每个会话一个。然后以轮询方式发送流量,让每个会话都有机会轮流发送数据。
这导致非常公平的行为,并阻止任何单个会话淹没其余会话。SFQ 被称为“随机”,因为它实际上并没有为每个会话分配一个队列,它有一个算法,使用哈希算法将流量分配到有限数量的队列中。
由于哈希,多个会话可能会最终进入同一个桶,这将使每个会话发送数据包的机会减半,从而使可用有效速度减半。为了防止这种情况变得明显,SFQ 经常更改其哈希算法,以便任何两个冲突的会话只会冲突几秒钟。
重要的是要注意,SFQ 仅在您的实际传出接口真的已满的情况下才有用!如果不是,那么您的 linux 机器上就不会有队列,因此也不会有效果。稍后我们将描述如何将 SFQ 与其他队列规则结合使用,以获得两全其美的局面。
具体而言,在通往您的电缆调制解调器或 DSL 路由器的以太网接口上设置 SFQ 是毫无意义的,除非进行进一步的整形!
SFQ 几乎是自调优的
每隔这么多秒重新配置一次哈希。如果未设置,则哈希将永远不会重新配置。不推荐。10 秒可能是一个好值。
流在轮到下一个队列之前允许出队的字节数。默认为 1 个最大尺寸数据包(MTU 尺寸)。不要设置低于 MTU!
如果您的设备具有相同的链路速度和实际可用速率,例如电话调制解调器,则此配置将有助于提高公平性
# tc qdisc add dev ppp0 root sfq perturb 10 # tc -s -d qdisc ls qdisc sfq 800c: dev ppp0 quantum 1514b limit 128p flows 128/1024 perturb 10sec Sent 4812 bytes 62 pkts (dropped 0, overlimits 0) |
数字 800c: 是自动分配的句柄号,limit 表示 128 个数据包可以在此队列中等待。有 1024 个哈希桶可用于记帐,其中 128 个可以同时处于活动状态(队列中不再容纳更多数据包!)。每 10 秒钟重新配置一次哈希。