21.2. Linux QoS using “tc”

Linux is using “tc” from the “iproute2” package to configure traffic shaping, generally described in the Linux Advanced Routing & Traffic Control HOWTO.

21.2.1. Example for a constant bitrate queuing

With the “cbq” scheduler, pipes with constant bit rates can be defined.

21.2.1.1. Root qdisc definition

Define root qdisc with a bandwidth of 1000 MBit/s on eth1

# tc qdisc add dev eth1 root handle 1: cbq avpkt 1000 bandwidth 1000Mbit

21.2.1.2. QoS class definition

Define a class 1:1 with 1 MBit/s

# tc class add dev eth1 parent 1: classid 1:1 cbq rate   1Mbit allot 1500 bounded 

Define a class 1:2 with 50 MBit/s

# tc class add dev eth1 parent 1: classid 1:2 cbq rate  50Mbit allot 1500 bounded

Define a class 1:3 with 10 MBit/s

# tc class add dev eth1 parent 1: classid 1:3 cbq rate  10Mbit allot 1500 bounded

Define a class 1:4 with 200 kBit/s

# tc class add dev eth1 parent 1: classid 1:4 cbq rate 200kbit allot 1500 bounded

21.2.1.3. QoS filter definition

Define a filter for IPv4 (protocol ip), TCP (match ip protocol 6 0xff) destination port 5001 (match ip dport 5001 0xffff) using class 1:2 from above

# tc filter add dev eth1 parent 1: protocol ip   u32 match ip  protocol 6 0xff match ip dport 5001 0xffff flowid 1:1

Define a filter for IPv6 (protocol ip), TCP (match ip6 protocol 6 0xff) destination port 5001 using class 1:2 from above

# tc filter add dev eth1 parent 1: protocol ipv6 u32 match ip6 protocol 6 0xff match ip6 dport 5001 0xffff flowid 1:2

Define a filter for IPv6 for packets having flow label 12345 (match ip6 flowlabel 12345 0x3ffff) using class 1:3 from above

# tc filter add dev eth1 parent 1: protocol ipv6 u32 match ip6 flowlabel 12345 0x3ffff flowid 1:3 

Define a filter for IPv6 for packets having Linux iptables mark 32 (handle 32 fw) specified using class 1:4 from above

# tc filter add dev eth1 parent 1: protocol ipv6 handle 32 fw flowid 1:4

The last filter definition requires an entry in the ip6tables to mark a packet

# ip6tables -A POSTROUTING -t mangle -p tcp --dport 5003 -j MARK --set-mark 32 

21.2.1.4. Testing filter definitions using iperf

Start on server side each one one separate console:

# iperf -V -s -p 5001
# iperf -V -s -p 5002
# iperf -V -s -p 5003

Start on client side and compare results:

# iperf -V -c SERVER-IPv4 -p 5001    (expected:      1 MBit/s)
# iperf -V -c SERVER-IPv6 -p 5001    (expected:     50 MBit/s)
# iperf -V -c SERVER-IPv4 -p 5002    (expected:  >> 50 MBit/s && <= 1000 MBit/s)
# iperf -V -c SERVER-IPv6 -p 5002    (expected:  >> 50 MBit/s && <= 1000 MBit/s)
# iperf -V -c SERVER-IPv4 -p 5003    (expected:  >> 50 MBit/s && <= 1000 MBit/s)
# iperf -V -c SERVER-IPv6 -p 5003    (expected:    200 kBit/s)

The rate result should be as defined in the classes (see above), the results on port 5002 should be very similar independend from used IP version.