Thursday, March 17, 2011

Bandwidth Control in Linux

There are several ways to control / shape / manage bandwidth in Linux.

Simple approach. Install wondershaper:

#apt-get install wondershaper

Configure it using kilobits (change eth1 according to yours):
from manual "wondershaper [ interface ] [ downlink ] [ uplink ]"
#wondershaper eth1 2048 2048
If you want to clear simply run:
#wondershaper clear eth1

We will control the bandwidth using a tool "tc", which is a part of "iproute" package in Debian.
tc - show / manipulate traffic control settings

Simple, classless Queueing Disciplines:

The Token Bucket Filter (TBF) - Simple and easy, for slowing an interface down. 

qdisc - queuing discipline 
latency - number of bytes that can be queued waiting for tokens to become available.
burst - Size of the bucket, in bytes.
rate - speedknob

#tc qdisc add dev eth1 root tbf rate 220kbit latency 50ms burst 1540
click here for more information on TBF.

Stochastic Fairness Queueing (SFQ) - round robin type, provide each session the chance to send data in turn. It changes its hashing algorithm within an interval.

qdisc - queuing discipline 
perturb - Reconfigure hashing once this many seconds.
#tc qdisc add dev eth1 root sfq perturb 10
click here for more information on SFQ.

To check the status run:
#tc -s -d qdisc show dev eth1
To remove it:
#tc qdisc del dev eth1 root

Classful Queueing Disciplines:

CBQ (Class Based Queueing) - A Classful Queueing
HTB - Another classful Queueing. (we will use it.)

Example classful qdisc

Let assume we want to create some rules for a small office using HTB.
eth0 - external interface - PUBLIC_IP 
eth1 - internal interface - LOCAL_IP 
Email will get the highest priority
General/Other will get the medium priority.
Video streaming will get the lowest priority.

Creating root 1: and 1:1 using HTB (default 6 means follow 1:6 if no rule matched)
#tc qdisc add dev eth1 root handle 1: htb default 6
#tc class add dev eth1 parent 1: classid 1:1 htb rate 2mbit ceil 2mbit

Creating leaf class 1:5 (prio represents priority, and 0 means high priority)
#tc class add dev eth1 parent 1:1 classid 1:5 htb rate 1mbit ceil 1.5mbit
#tc filter add dev eth1 protocol ip parent 1:0 prio 0 u32 match ip src YOUR_MAIL_SERVER_IP/32 flowid 1:5
#tc filter add dev eth1 protocol ip parent 1:0 prio 0 u32 match ip sport 22 0xffff flowid 1:5

Creating leaf class 1:6 (It is set as default in root qdisc, so we are not setting any rules)
#tc class add dev eth1 parent 1:1 classid 1:6 htb rate 0.5mbit ceil 1.5mbit

Creating leaf class 1:7 (use /32 for specific IP, /24 for that series. Priority low - prio 5. You can get the IP address using "iptraf" tool)
#tc class add dev eth1 parent 1:1 classid 1:7 htb rate 0.2mbit ceil 1mbit
#tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 match ip src VIDEO_STREAM_IP/32 flowid 1:7

Optionally we can also add discipline with leaf (for an example we are adding SFQ with leaf class 1:5)
#tc qdisc add dev eth1 parent 1:5 handle 20: sfq perturb 10

To remove it:
#tc qdisc del dev eth1 root handle 1: htb

Click here for more information on HTB.

This document is written to describe a basic of bandwidth controlling/shaping for the new users. Please check the details documentation for advance options.

HTB user guide:


Anonymous said...

tc is a great command to configure bandwidth. I used that for Traffic Shapping in a local ISP.

I had created a script to generated tc script file using perl and sqlite. Need more tweaking. Please Check this out and suggest :

salahuddin66 said...

You set these rules as destination, so it will slow down users request, but it will allow to receive data from those IP without your speficied restriction!

I dont know if you want to do this, or want to limit the services users will get from those IP.

In case of a script, I would like to suggest use variable for defining eth0/eth1 and most common commands. (you dont know which is external and which is internal in other server)

Instead of hardcoded the data transfer rate.
Try to calculate in percentage %.

Specially if you want to write a fully reusable script for a long time. :)