There are several scripts for QoS (quality of service) under Linux around the web, so here is another one :)
As I looked over all those scripts in the last weeks, I saw that none of them was really sufficing for my needs. So
I grabbed the best parts of them, tried to understand whats going on, and put them together to my own one.
There was also very poor documentation in the existing ones - I hope I will do it better.
If you have questions or comments, please don't hesitate to write
me.
Of course you need to install iproute2 for
this.
You need to activate the following stuff in your kernel:
IP: Netfilter Configuration
[*] Layer 7 match support (if you patched it in)
[*] TOS match support
[*] LENGTH match support
[*] Packet mangling
[*] MARK target support
(and of course the options you need for your masquerading/other firewall stuff)
QoS and/or fair queueing
[*] QoS and/or fair queueing
[*] HTB packet scheduler
[*] SFQ queue
[*] QoS support
[*] Rate estimator
[*] Packet classifier API
[*] Firewall based classifier
[*] Traffic policing (needed for in/egress)
It's also good to get the latest layer7-patches for
your kernel; you will be able to classify packets because of their layer7 protocol, not just because of their
source/destination address/port.
So how does all that stuff work?
There are four priority classes for outgoing packets. I use the first class, 1:10, for ICMP, SSH, VoIP and packets
which have type of service (TOS) "Minimize-Delay" set. The second, 1:20, is used for tcp-acks, so sending a huge
eMail
won't affect you browsing the web and TOS "Maximize-Throughput". The third class, 1:30, is the default class where
everything else goes in. The
last, 1:40, with lowest priority is used for p2p-upload and TOS "Minimize-Cost".
Classifying IP-Packets
I use netfilter/iptables for setting MARKs 1 to 4 for every
packet according to the class it should go later on.
For example
"iptables -t mangle -o $DEV -A POSTROUTING -p tcp --dport 22 -j MARK --set-mark 1"
marks packets
hopefully going to an sshd with 1.
But what if your favorite ssh-host listens on another port? If you patched your kernel as I told above, you can do
far better:
"iptables -t mangle -o $DEV -A POSTROUTING -m layer7 --l7proto ssh
-j MARK --set-mark 1"
This marks every ssh-packet 1, tricky, isn't it? There are patterns for many protocols, please look at L7-filter Supported Protocols for their
names.
Creating queues and putting packets into
After marking all packets which will pass our router, we just have to create the four queues, and tell that packets
marked 1 have to go into first queue and so on.
So we have the following four queues:
1:10
1:20
1:30
1:40
ICMP SSH VoIP
TOS: Minimize-Delay
TCP-ACK
TOS:
Maximize-Throughput
Default
P2P
TOS: Minimize-Cost
The following command creates a queue named "1:10":
tc class add dev $DEV parent 1:1 classid 1:10 htb rate $[50*UPLINK/100]kbit ceil ${UPLINK}kbit burst 6k prio
1
We gurantee that this queue will always get 50% of our uplink ("rate $[50*UPLINK/100]kbit"), which doesn't mean
that it gets these 50% at maximum: Of course the upper limit for this queue is our maximum uplink rate ("ceil
${UPLINK}kbit").
In my script, the four queues are devided up as follows:
I found this nice Perl-Script in some board once (I actually don't remember where). I creates
a nice table with traffic-statistics about your queues. Once started, it refreshes every 60 seconds. You need this stylesheet to make it look better.
If everything works correct and you download some big file, you should see the sent-MB growing in row for 1:20. If
you call your favorite friend using VoIP traffic should grow up in row 1:10 and so on...