14. 控制流量

在本章中,我们将尝试使用 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 中的字节流。

个人而言,我更喜欢 Martin Devera 出色的 HTB 队列规则实现,但实际上此实现不在标准 Linux 中(但将来会加入);为了实现它,您必须在重新编译之前修补您的内核,最好不要使事情复杂化。但是我不得不说,这个队列规则比 CBQ 更容易使用。关于 HTB 队列规则 的更多信息链接在本文档末尾。

编译并重新安装内核后,您必须安装 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.1192.168.1.2 通过端口 10011004 的 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 队列规则是某种公平控制队列。它试图为接口中的每个连接提供相同的机会来调度它们的数据包。

最后,我们将创建过滤器,以将端口 1001100210031004 的流量分别分配给类 1:31:41:51: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 监听端口 10011004,并在 PC #1 中进行对话,如前一章所述,并且 bwcurrent -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 带宽计量器。