在本章中,我们将尝试使用 Linux 内核队列规则来控制流量。也许,取决于您如何编译内核,您可能需要再次运行 make menuconfig,重新配置您的选项,重新编译并重新安装您的内核。
本章不是,也不试图成为关于 Linux 中 QoS (服务质量) 实现的教程。如果您之前没有 QoS 经验,最好阅读本文档末尾的一些参考资料,以了解 QoS 实现所需的概念。
鉴于此建议,我不会详细解释在 Linux 中控制流量所需的每个命令,因为这不是本 HOWTO 的目标。但是,其中一些技术的实现将有助于我们展示带宽计量器 (基于 libiptc) 的行为。
首先检查您的内核是否实现了 QoS 实现选项。运行 make menuconfig,按照菜单到网络选项,并查找此选项的最后一个菜单QoS 和/或公平队列。在这里使用(或检查它们是否已激活)这些选项
[*] QoS and/or fair queueing <M> CBQ packet scheduler <M> CSZ packet scheduler [*] ATM pseudo-scheduler <M> The simplest PRIO pseudoscheduler <M> RED queue <M> SFQ queue <M> TEQL queue <M> TBF queue <M> GRED queue <M> Diffserv field marker <M> Ingress Qdisc [*] QoS support [*] Rate estimator [*] Packet classifier API <M> TC index classifier <M> Routing table based classifier <M> Firewall based classifier <M> U32 classifier <M> Special RSVP classifier <M> Special RSVP classifier for IPv6 [*] Traffic policing (needed for in/egress) |
保存您的配置,重新编译您的内核和模块,然后重新安装它。我们将使用 CBQ 数据包调度器 来实现一些队列,以控制我们的 PC #1 NIC 中的字节流。
编译并重新安装内核后,您必须安装 iproute2 软件包,该软件包将用于运行实现队列所需的命令。从此链接下载此软件包:ftp://ftp.inr.ac.ru/ip-routing。
我正在使用版本 2.2.4-now-ss001007。要安装它,请按照以下说明操作
bash# cp iproute2-2.2.4-now-ss001007.tar.gz /usr/local/src bash# tar xzvf iproute2-2.2.4-now-ss001007.tar.gz bash# cd iproute2 bash# make |
在 make 成功编译 iproute2 软件包后,ip 实用程序将位于iproute2/ip目录,tc 实用程序位于iproute2/tc目录。将它们都复制到/usr/bin目录
bash# cp ip/ip /usr/bin bash# cp tc/tc /usr/bin |
现在,使用 tc 实用程序,我们将在 PC #1 计算机的接口 eth0 中创建一个 CBQ 队列。此队列将有 4 个子类,每个子类将用于控制从 192.168.1.1 到 192.168.1.2 通过端口 1001 到 1004 的 4 个流量。
编写并运行以下命令
bash# tc qdisc add dev eth0 root handle 1:0 cbq bandwidth 10Mbit \ avpkt 1000 cell 8 |
此命令在 eth0 接口中创建主 (根) cbq 队列 1:0;此队列的带宽为 10Mbit/秒,对应于我们的以太网接口。
现在编写并运行
bash# tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 10Mbit \ rate 1000kbit prio 8 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded |
此命令创建主 cbq 类 1:1。此类的速率为 1000kbit/秒。
现在我们将创建 4 个由此类拥有的类;这些类的速率分别为 100kbit、200kbit、300kbit 和 400kbit。编写并运行以下命令
bash# tc class add dev eth0 parent 1:1 classid 1:3 cbq bandwidth 10Mbit \ rate 100kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000 bash# tc class add dev eth0 parent 1:1 classid 1:4 cbq bandwidth 10Mbit \ rate 200kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000 bash# tc class add dev eth0 parent 1:1 classid 1:5 cbq bandwidth 10Mbit \ rate 300kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000 bash# tc class add dev eth0 parent 1:1 classid 1:6 cbq bandwidth 10Mbit \ rate 400kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000 |
这些类中的每一个都将附加一个 sfq 队列规则,以调度它们的数据包。编写并运行以下命令
bash# tc qdisc add dev eth0 parent 1:3 handle 30: sfq perturb 15 bash# tc qdisc add dev eth0 parent 1:4 handle 40: sfq perturb 15 bash# tc qdisc add dev eth0 parent 1:5 handle 50: sfq perturb 15 bash# tc qdisc add dev eth0 parent 1:6 handle 60: sfq perturb 15 |
这些命令创建 4 个 sfq 队列规则,每个类一个。sfq 队列规则是某种公平控制队列。它试图为接口中的每个连接提供相同的机会来调度它们的数据包。
最后,我们将创建过滤器,以将端口 1001、1002、1003 和 1004 的流量分别分配给类 1:3、1:4、1:5 和 1:6。编写并按如下方式运行
bash# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \ dport 1001 0xffff flowid 1:3 bash# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \ dport 1002 0xffff flowid 1:4 bash# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \ dport 1003 0xffff flowid 1:5 bash# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \ dport 1004 0xffff flowid 1:6 |
运行所有这些命令后,现在检查您的 bw 计量器(您必须在 PC #2 中运行 netcat 监听端口 1001 到 1004,并在 PC #1 中进行对话,如前一章所述,并且 bw 在 current -c 模式下运行)。您将看到类似这样的内容
Current flow values ... 1099.9k: 108.8k 196.5k 337.9k 456.8k 1104.2k: 115.3k 184.9k 339.9k 464.1k 1102.1k: 117.3k 174.7k 339.7k 470.5k 1114.4k: 113.6k 191.7k 340.7k 468.4k 1118.4k: 113.7k 194.3k 340.5k 469.9k |
bw 向我们展示了如何使用 Linux 内核的队列规则来控制流量。如您所见,CBQ 队列规则 不是非常精确的队列,但您或多或少在接口 eth0 上拥有大约 1000=100+200+300+400 的流量。
要退回,请编写并按如下方式运行
bash# tc qdisc del dev eth0 root handle 1:0 cbq |
在 PC #1 上,删除主(根)队列规则以及拥有的类和过滤器。
bash# killall nc |
在 PC #2 和 PC #1 上,停止 netcat。
bash# iptables -F bash# iptables -X |
在 PC #1 上,清除 iptables 规则和链。
bash# Ctrl-C |
在 PC #1 上,tty1 停止 bw 带宽计量器。