9.7. 中间排队设备 (IMQ)

中间排队设备不是一个 qdisc,但其用法与 qdisc 紧密相关。在 Linux 中,qdisc 被附加到网络设备,并且所有排队到设备的内容首先被排队到 qdisc。由此概念,产生了两个限制:

1. 仅出口整形是可能的(存在入口 qdisc,但其可能性与 classful qdisc 相比非常有限)。

2. 一个 qdisc 只能看到一个接口的流量,无法设置全局限制。

IMQ 的存在是为了帮助解决这两个限制。简而言之,您可以将您选择的任何内容放入 qdisc 中。特别标记的数据包在 netfilter NF_IP_PRE_ROUTING 和 NF_IP_POST_ROUTING 钩子中被拦截,并通过附加到 imq 设备的 qdisc。iptables target 用于标记数据包。

这使您能够进行入口整形,因为您可以标记从某处进入的数据包和/或将接口视为类来设置全局限制。您还可以做很多其他事情,例如仅将您的 http 流量放入 qdisc,将新连接请求放入 qdisc,等等...

9.7.1. 示例配置

首先想到的可能是使用入口整形来为自己提供高保证带宽。;)配置就像任何其他接口一样
tc qdisc add dev imq0 root handle 1: htb default 20

tc class add dev imq0 parent 1: classid 1:1 htb rate 2mbit burst 15k

tc class add dev imq0 parent 1:1 classid 1:10 htb rate 1mbit
tc class add dev imq0 parent 1:1 classid 1:20 htb rate 1mbit

tc qdisc add dev imq0 parent 1:10 handle 10: pfifo
tc qdisc add dev imq0 parent 1:20 handle 20: sfq

tc filter add dev imq0 parent 10:0 protocol ip prio 1 u32 match \
		ip dst 10.0.0.230/32 flowid 1:10
在此示例中,u32 用于分类。其他分类器应按预期工作。接下来,必须选择流量并标记为排队到 imq0。
iptables -t mangle -A PREROUTING -i eth0 -j IMQ --todev 0

ip link set imq0 up

IMQ iptables targets 在 mangle 表的 PREROUTING 和 POSTROUTING 链中有效。它的语法是
IMQ [ --todev n ]	n : number of imq device
还提供了 ip6tables target。

请注意,流量不是在命中 target 时排队的,而是在之后。流量进入 imq 设备的准确位置取决于流量的方向(入/出)。这些是 iptables 使用的预定义 netfilter 钩子
enum nf_ip_hook_priorities {
        NF_IP_PRI_FIRST = INT_MIN,
        NF_IP_PRI_CONNTRACK = -200,
        NF_IP_PRI_MANGLE = -150,
        NF_IP_PRI_NAT_DST = -100,
        NF_IP_PRI_FILTER = 0,
        NF_IP_PRI_NAT_SRC = 100,
        NF_IP_PRI_LAST = INT_MAX,
};

对于入口流量,imq 在 NF_IP_PRI_MANGLE + 1 优先级注册自己,这意味着数据包在通过 mangle PREROUTING 链后直接进入 imq 设备。

对于出口,imq 使用 NF_IP_PRI_LAST,这尊重了过滤器表丢弃的数据包不会占用带宽的事实。

补丁和更多信息可以在 imq 站点找到。