The Hierarchical Token Bucket Quality of Service (HTB QoS) system is a great tool to use for controlling the bandwidth of a network link, especially when you have a bunch of doggs on your network that love to use up all the internets they can get! Lets take a look at a quick and simple HTB QoS setup on a CentOS 6 Linux box.

First, go to Google and run some bandwidth tests in order to get a good idea of your actual line speed. Take note of your maximum upload and download speeds. On my home network, I measured around 23Mbit down and 1Mbit up. Write these numbers down and save them for later…

Next, make sure that you have the iproute package installed, to install the necessary prerequisite programs.

# yum install iproute

Now we can download the necessary htb.init script and examples to get us started. The htb.init script can be downloaded from here. Stick this script in your /etc/init.d/ directory. Next, download the example files and put them into the /etc/sysconfig/htb/ directory. Below are the commands I ran…

# wget
# mv htb.init-v0.8.5 /etc/init.d/htb.init
# chmod 755 /etc/init.d/htb.init
# wget
# mkdir htb
# tar zxf htb-lartc.tar.gz -C ./htb
# mv ./htb /etc/sysconfig/

Now, one other set of commands I want to run, to slightly change the names of the htb files to fit my needs. I am only going to have two classes of traffic, plus the default. I want to make sure my www and ssh connections each have a separate allocated bucket of bandwidth, and everything else can share the default bucket. The commands below will rename the htb configuration files to match. Please note that we are using the eth0 device in this example, since it is our internet connection.

# cd /etc/sysconfig/htb
# mv eth0-2\:10.www eth0-2\:10.ssh
# mv eth0-2\:20.smtp eth0-2\:20.www

Ok! Now that we have the init script in place, and the rules files in place, we can actually start some bandwidth shaping!

You will notice in the /etc/sysconfig/htb/ folder that there are a number of different files, with some slightly different names. The first file we’ll look at, eth0, is just to specify what device we are working with. Inside this file are lines setting the default rule (the one used when no others match), and our R2Q. Note that the rate divided by R2Q gives us our quantum, which is the amount of bandwidth given to one class before servicing another class. The faster your available network connection, the larger your quantum can be. I’m using a r2q of 100, however you can always adjust this value depending on your needs and bandwidth speed. Below are the contents of the eth0 file:

# eth0 device

Next, the eth0-2.root file. This specifies the default rate, ceiling rate, and burst speed. The default rate is the minimum rate for the class (device eth0 in this case). The ceiling rate is the maximum rate for the class. Finally, the burst rate is the maximum amount of bandwidth that can be sent through the hardware without moving on to service another class. Below are the contents of the eth0-2.root file:

# root class containing total bandwidth

Notice here that we are setting the rates at 20Mbit, which is below our maximum tested rate of 23Mbit. By setting our rate lower than the actual link rate, we limit the buffering done by any network equipment beyond our router (like the cable/DSL modem). This will decrease our lag time by keeping any traffic buffers on our faster equipment. I will gladly sacrifice a small amount of total speed for lower latency.

Finally, we have our rules files. I set my ssh traffic to be given a minimum of 128Kbit, and a maximum of 20Mbit. This traffic also has the highest priority, in order to increase the availability of bandwidth to ssh traffic. A similar setup is done for the www traffic, and the default traffic. Below are the three files defining these classes…


# class for SSH traffic


# class for WWW traffic


# class for all other traffic

Now, lets take a look at the RULE= lines from the eth0-2:10.ssh file above.


Rules are specified with the pattern RULE=[[saddr[/prefix]][:port[/mask]],][daddr[/prefix]][:port[/mask]], so the first line, RULE=*:22, will match all traffic with a source port of 22. The second line, RULE=*:22 matches any traffic with a destination of port 22. We do the same thing with the appropriate port numbers for our www class in order to shape our www traffic. There are many options here, since this is where we control what traffic matches which class; you can specify traffic by source port, destination port, source IP, destination IP, or a combination of them! Take a look at the links below for some more examples. Finally, the default rule will apply to any traffic which does not match our first two rules.

The image below illustrates the hierarchy within this specific setup.
HTB - Hierarchical Token Bucket Example

Now, in order to start using the rules and make them persistent on every reboot, we will add the htb.init service to the system, set it to start on boot, and turn it on right now! The commands below will do this for us:

# chkconfig --add htb.init
# chkconfig htb.init on
# service htb.init start

If you get a warning along the lines of find: warning: you have specified the -maxdepth option after a non-option argument -type, but options are not positional then you will need to uncomment the following line in your /etc/init.d/htb.init script:


Using this simple HTB QoS setup, we can provide network bandwidth control to our small home network, preventing any one dogg from hogging all the internets! This setup will also scale fairly well to much larger installations.

Take a look at the htb.init-v0.8.5 we downloaded earlier for some more rule examples, as well as explainations of the configuration options.

Also check out the following websites for some more information on HTB QoS network traffic control.
HTB Linux queuing discipline manual – user guide
Linux Advanced Routing & Traffic Control HOWTO

Print Friendly, PDF & Email