Tc tutorial
The most known tc and iproute tutorial is
LARTC but it does not cover some aspects.
Another good place which talks about very specific cases is
www.docum.org, but there you will not find
complete solutions.
Here you will find some hints how to more effectively manage traffic. You
should have some experience with iptables, tc and iproute.
You can achieve best results when using all these tools at once. This page is
targeted to those who need to control low speed traffic.
Some History of linux traffic control:
The first attempt was module named shaper.o which was primitive way to slow
down interface, basicaly it did not measured trafic at all, and was only able to
decrease interface speed to some percentage of full speed. it was available for
very long time. the way it work is similar as your computer power power supply
works, It is using PWM ( pulse width modulation ) if you have 36v and want to
make 12v then you can switch supply off for 2ms then switch on for 1ms this way
you will transfer power equal to 12v from 36v.
shaper does the same with your network card (of course it will not turn off its
power). PWM have one adwantage that it does not require much processor power mo
matter how much trafic it need to pass., but quality is bad.
The main problem with this module is that it cant classify traffic at all,
and unless you add separate nic for everybody it wont do anything much useful.
Then CBQ appeared, it is basically shaper.o which can classify traffic, but it
works in the same way.
instead of controlling interface it controls each traffic class in the same way.
still wery effective in processor usage, but quality is bad, since it do not
count how much traffic is passing, all it cares how long you can use interface.
from that time shaping became quite popular and new modules started to appear
HTB is the first one which uses diferent way, it controls trafic per packet.
instead of time slots, this makes it independent from nic type, and basically
real nic is even not necessary.
All further drivers use this way, which allows to implement very precise control
in expense of higher cpu load. that is why some people still like to use CBQ for
very high speed control.
anyway cpu load difference is not so big to care about it in most situations.
For now HTB remains most popular shaper.
In future htb will probably will replaced with HSFC which is even more advanced but works the same way as htb with more features.
I assume you already read tc manual, so you should know its basic usage. For
those who are too lazy here is short reference.
set -v ---- for easer debugging of bash script
tc qdisc del dev eth0 root --- deletes all tc configuration for eth0
tc qdisc add dev eth0 root handle 2 htb default 5 ----- creates starting
point for configuration on eth0 (and directs all unclasified trafic to class 5)
optional
tc class add dev eth0 parent 2: classid 2:8 htb rate 135Kbit ceil 500Kbit prio 2
---- creates new class 8 which belongs to root 2
tc qdisc add dev eth0 parent 2:8 sfq ---- attach the shaper itself to the class 8 if you will not use this fifo shaper will be used by default
tc filter add dev eth0 parent 2: protocol u32 match ip dst 192.168.1.3
classid 2:8 ----- in the root place check if packet destination is 1.3 and then
direct it to class 8
Usage of filters will be explained in details later.
I recommend do not type tc configuration by hand, since you will need to
retype it all every time if you change something.
The most easy way is to create bash script even for most simple configurations.
To see how it works add set -v in second line.
then copy sample rules from anywhere you like and modify them to suit your needs
Example:
#!/bin/bash
set -v
# type your commands here
....
linux tc system looks like this:

This drawing is little different than can be seen on other pages.
Classification and shaping structures are mirror images of each other.
In classification side this structure doesn't do anything but provides handles
to attach filters,
packets can be dequeued from any class when they passed all applicable filters.
each filter can either move packet to other class either drop immediately.
When packets pass filters, they are queued. every class have default fifo
queue, which can be changed into any.
queues cant have classes, and are called classless qdisc
Queues can be simple like fifo, red whose have only one internal queue or
advanced like sfq, that have many internal queues.
Shaping can be done by classfiull qdiscs like htb or prio, they cant even
touch packets, and only dequeues them directly to interface
Each qdisc can only give permission to its parent to dequeue its quantum number
of bytes.
in this example root 2: will give permission to 2:1 to dequeue 10000 bytes, then
2:1 will give permission to 2:10 to dequeue 3000 bytes
and 2:11 6000 bytes. dequeued packets goes directly to interface.
this way shaper cycles through all classes in order of their priorities,
so the classes with lowest priority numbers are dequeued first.
If class have child classes, then it do not have ability to attach queue
anymore, this is some htb limitation, probably packets are directed to
root's default class
(the drawing needs to be fixed)
HTB shaper can have these parameters:
| rate | Usually don't do anything usefull, but provides the way to
calculate automatic quantums for classes, the same can be achieved by using quantums. Also sets the the minimal rate at which class will dequeue packets. ( usefull for those who have fast links. and only few classes) at low speed links and high number of classes it doesnt work well, since if you will divide 100kbit to 20 classes rate will be only 5kbit, that is not worth typing. so set it to 1kbit in such case. |
| ceil | (optional ) sets max rate at which class can dequeue packets. This parameter is most easy to understand, by default ceil=rate, but that way that class will not prioritize traffic. |
| quantum | (optional) tells how many bytes should be dequeued at one pass, by default it is calculated this way quantum=rate/r2q more the quantum, the higger priority will have that class, quantum should be not less than mtu (1500bytes) if class 10 have quantum 1500 and class 20 quantum 3000 then they will divide rate in 1 to 2 proportion. less quantum means faster shaper response. so quantums should be kept as low as possible |
| cburst | (optional) max amount of data that can be accumulated if
real rate is lower than ceil, this amount can be taken anytime without ceil
limitation later, by default it is about one packet size, Can also by used
for limiting amount of data the the class can pass over some time without
speed limitations example: you may set cburst to 5mbytes, and ceil to 80 kbit, this will limit class to average speed of 80 kbit with unlimited maximum. when user will download 5Mbytes at 100kbytes/s rate will drop to 10 kbyte/s. |
| burst | (optional) similar to cburst but does the same with rate |
all classes can have independent parameters, but if parent parameter is lower
than child then of course it will limit child's parameter.
(if you will set parent ceil to 50kbit and its child's ceil to 100kbit then is
still will not exceed 50kbit)
Packet classification is done usually by filters, they can direct packets
anywhere, probably even in loop, must should be avoided
filters have lots of options, but all are very straight and and usually
just match some part of packet memory, with optional mask.
nothing more advanced can be done. iptables can be used for classification too,
either by marking packets either with classify target.
Very popular mistake is that many people thinks filter can be applied only to
root class, this is total nonsense,
however root must have some filter which direct packets to next class.
Some filters in chain can be used: first classify by firewall mark then by
port, then by destination.
example:
tc filter add dev imq parent 2: protocol ip pref 4 handle 0x21 fw classid 2:6
tc filter add dev imq parent 2:6 protocol ip pref 2 u32 match ip sport 80 0xffff
classid 2:8
tc filter add dev imq parent 2:8 protocol ip u32 match ip dst 192.168.1.3
classid 2:70
Classification options are widely discussed so no need to do that again.
detailed info can be found here:
LARTC
Not so well know are policers. They are extensions of filters, ( policer is
processed before filter decision)
Policers are more or less independent form filter, and can be used to take some
actions according to packet rate.
the only available options are drop packet, and skip current filter, or do
nothing.
Policers can have these parameters:
| rate | rate to match |
| busrst | amount of data nedded to measure rate |
| index | poorly documented, should make policer share rate counters for policers with same index number. From my observations, behavior is very strange and need further research. |
Since policers can indirectly affect packet classification (by skipping
current filter) they can be used for very advanced classification by rate.
---------------
I stil not tested such configuration, so no example available.
---------------
but theoreticaly it should be possible to do something like this:
if ( web trafic rate is >100kbit/s) then {limit p2p trafis to 20kbit}
else {p2p unlimited}
Examples:
Standard usage of htb for traffic shaping.
#setup root
tc qdisc del dev eth0 root
tc qdisc add dev eth0 root handle 2 htb default 1
tc class add dev eth0 parent 2: classid 2:6 htb rate 250kbit
#User 1
tc class add dev eth0 parent 2:6 classid 2:100d htb rate 80Kbit ceil 200kbit
tc qdisc add dev eth0 parent 2:100d sfq
tc filter add dev eth0 parent 2: protocol ip pref 4 u32 match ip dst
192.168.1.5 classid 2:100d
#User 1
tc class add dev eth0 parent 2:6 classid 2:101d htb rate 80Kbit ceil 200kbit
tc qdisc add dev eth0 parent 2:101d sfq
tc filter add dev eth0 parent 2: protocol ip pref 4 u32 match ip dst 192.168.1.6 classid 2:101d
Do not forget to set ceil or else it will do nothing than hardlimit everything to rate.
New way to prevent users from constant downloading, but leaving speed high for everyone who do not download so much.
Usual way to share traffic is when everybody gets constant portion from total
capacity. the portion size depends on how many users are active.
unfortunately, if you are poor, then any attempt co connect 20 users to
256 kbit dsl may be unsuccessful,
imagine that everybody just browse www, then probably only 3-4 users will be
active at a time what means acceptable speed
but if 5 of then start downloading? than 9 users may become active at once what
decreases speed to ridiculous numbers.
and worst that downloaders will get more since transfers need time to
accelerate.
here is example configuration which can solve this problem.
max speed needs no explanation, average means the speed averaged
per long time about 5 min
averaging amount of data is amount that user can download at
max speed when it is consumed speed will be limited to average
is user uses less than average speed then he can rebuild its reserve and use
it with full speed again.
#mark the packets we need to shape
#we shape only forwarded traffic since local is free anyway
iptables -A PREROUTING -t mangle -j MARK 50
#setup root class
tc qdisc del dev eth0 root
tc qdisc add dev eth0 root handle 2 htb default 1
tc class add dev eth0 parent 2: classid 2:6 htb rate 250Kbit
tc filter add dev eth0 parent 2: protocol ip pref 2 handle 50 fw classid 2:6
#User 1
tc class add dev eth0 parent 2:6 classid 2:100 htb rate 160Kbit quantum 3000
# << max speed for user
tc class add dev eth0 parent 2:100 classid 2:100d htb rate 80Kbit cburst 1000kb
quantum 3000 #<< average speed and averaging
amount of data
tc qdisc add dev eth0 parent 2:100d sfq
tc filter add dev eth0 parent 2:6 protocol ip pref 4 u32 match ip dst
192.168.1.4 classid 2:100d
#User 2
tc class add dev eth0 parent 2:6 classid 2:101 htb rate 160Kbit quantum 3000
tc class add dev eth0 parent 2:101 classid 2:101d htb rate 80Kbit cburst 1000kb
quantum 3000
tc qdisc add dev eth0 parent 2:101d sfq
tc filter add dev eth0 parent 2:6 protocol ip pref 4 u32 match ip dst
192.168.1.5 classid 2:101d
repeat for other users in the same way
I have made perl script which can setup this configuration easy, by taking data from text file. later I will add it here.
Using imq for advanced configurations.
later.....
Later I will add more information how to make shaping more easy by using imq.
also I will try to add some extremely complex example.