Linux IMQ - Intermediate Queueing Device

Home
News
FAQ
Patches
Usage
WiKi
Links
Mailing List

Usage

By default you have two imq devices (imq0 and imq1). These are dummy interfaces, you can do nothing but attach qdiscs to them. Only egress qdiscs can be used, the current ingress qdisc is just another netfilter hooker. Since packets never get directed to an imq device by the network stack itself no netfilter hooks will ever be called. You can use imq for ingress traffic control, but only using egress qdiscs (which makes more sense anyway since current ingress is very limited).

First you have to attach a qdisc to the imq device. The imq device can be treated like any other network device. The fw classifier can be used for filters. The packet length seen by the qdisc includes link layer headers of the device the packet has entered/will be leaving through so you can work with link speed when limiting traffic.

After attaching a qdisc to the device you have to specify which packets should go through the imq device. An iptables target (`IMQ') is provided for using all the packet-selecting power of iptables.

As soon as the interfaces reaches IFF_UP state selected packets will be enqeued to the imq device. Immediately dequeue is tried and dequeued packet (possibly reordered) gets reinjected into the network stack (software pump).

If you are using IMQ as modules you can: modprobe imq and then modprobe ipt_IMQ. To choose the number of IMQ devices you should: modprobe imq numdevs=X.


Usage examples

/sbin/ip link set imq0 up
/sbin/tc qdisc add dev imq0 root handle 1: htb default 2
/sbin/tc class add dev imq0 parent 1: classid 1:1 htb rate 80000Kbit
/sbin/tc class add dev imq0 parent 1: classid 1:2 htb rate 80000Kbit
/sbin/tc class add dev imq0 parent 1:1 classid 1:10 htb rate 256kbit ceil 384kbit
/sbin/tc class add dev imq0 parent 1:1 classid 1:20 htb rate 512kbit ceil 648kbit
/sbin/tc filter add dev imq0 parent 1: protocol ip prio 1 u32 match ip dst aaa.aaa.aaa.aaa/bb match ip src ccc.ccc.ccc.ccc/dd flowid 1:10
/sbin/tc filter add dev imq0 parent 1: protocol ip prio 1 u32 match ip dst ddd.ddd.ddd.ddd/ee match ip src fff.fff.fff.fff/gg flowid 1:20
/usr/sbin/iptables -t mangle -A PREROUTING -i ppp0 -j IMQ --todev 0
/usr/sbin/iptables -t mangle -A PREROUTING -i ppp1 -j IMQ --todev 0

/sbin/ip link set imq1 up
/sbin/tc qdisc add dev imq1 root handle 2: htb default 2
/sbin/tc class add dev imq1 parent 2: classid 2:1 htb rate 80000Kbit
/sbin/tc class add dev imq1 parent 2: classid 2:2 htb rate 80000Kbit
/sbin/tc class add dev imq1 parent 2:1 classid 2:10 htb rate 256kbit ceil 384kbit
/sbin/tc class add dev imq1 parent 2:1 classid 2:20 htb rate 512kbit ceil 648kbit
/sbin/tc filter add dev imq1 parent 2: protocol ip prio 1 u32 match ip dst ccc.ccc.ccc.ccc/dd match ip src aaa.aaa.aaa.aaa/bb flowid 2:10
/sbin/tc filter add dev imq1 parent 2: protocol ip prio 1 u32 match ip dst fff.fff.fff.fff/gg match ip src ddd.ddd.ddd.ddd/ee flowid 2:20
/usr/sbin/iptables -t mangle -A POSTROUTING -o ppp0 -j IMQ --todev 1
/usr/sbin/iptables -t mangle -A POSTROUTING -o ppp1 -j IMQ --todev 1


Usage with multi-queue version (from 2.6.35)

#!/bin/sh
IMQ_IS_MQ=$(modinfo imq | grep numqueues)
if [ "$IMQ_IS_MQ" = "" ]; then
  # load single-queue imq
  modprobe imq
else
  # load multi-queue imq
  NUM_CPU=$(grep -c 'model name' /proc/cpuinfo)
  modprobe imq numqueues=$NUM_CPU
fi


If the IMQ module support multi-queue, check the /sys/class/net/imqX/queue/rx-CPU/rps_cpus. Also you can set a value in rps_cpus to bind the specific queue on a specific CPU/CPUs. For example:

echo "f" > /sys/class/net/imq0/queue/rx-0/rps_cpu

Will bind queue rx-0 of device imq0 on all four CPUs of my Opteron Quad-Core. The CPU usage will be like this:

Tasks: 128 total, 1 running, 127 sleeping, 0 stopped, 0 zombie
Cpu0 : 0.0%us, 0.0%sy, 0.0%ni, 96.0%id, 0.0%wa, 0.0%hi, 4.0%si, 0.0%st
Cpu1 : 0.0%us, 0.0%sy, 0.0%ni, 98.0%id, 0.0%wa, 0.0%hi, 2.0%si, 0.0%st
Cpu2 : 0.0%us, 0.0%sy, 0.0%ni, 94.1%id, 0.0%wa, 0.0%hi, 5.9%si, 0.0%st
Cpu3 : 0.0%us, 0.0%sy, 0.0%ni, 95.1%id, 0.0%wa, 0.0%hi, 4.9%si, 0.0%st
Mem: 2059980k total, 1987624k used, 72356k free, 216248k buffers
Swap: 2098172k total, 0k used, 2098172k free, 1145576k cached

Of course, each ethernet device like eth0 and the VLANs created under eth0 has queues setted to bind the RX on all CPUs. More details at http://lwn.net/Articles/362339/ and http://lwn.net/Articles/382428/


transparent