Home of YATS - yet another traffic shaper

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:101:201:301:40
ICMP
SSH
VoIP

TOS: Minimize-Delay
TCP-ACK

TOS: Maximize-Throughput
DefaultP2P

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:

1:1050%
1:2030%
1:3015%
1:405%

Get the script

Download

Does everything work correctly?

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...

Links

As I told you, I was "inspired" by many scripts, for example:
Wondershaper
HOWTO Packet Shaping on gentoo-wiki
Posting in ip-phone-forum


Changelog

10.4.2005: Added variables for iptables/tc command
27.3.2005: Created this site, first version.