I have recently been working with the Vyatta Linux routing platform in an attempt to replace Cisco. It seems that Vyatta will support everything that I need except for bandwidth management and traffic shaping. Luckily, newer versions on Linux have this built into the kernel.
I will show you how to use HTB to control traffic based on what IP address you are coming from. Remember that HTB only shapes outgoing traffic, but since we have at least 2 interfaces on a router - and traffic is always outgoing on one of the interfaces - we can control up and down speeds.
Lets assume that eth0 is your ‘inside’ network and eth1 is your ‘outside’ network and you are trying to limit the bandwidth to 2mbit for Traffic going to or from IP address 12.13.14.15.
To accomplish this we are going to start by attached the HTB algorithm to device eth0 and give it a handle of “1:” (You enter this in your bash shell btw):
tc qdisc add dev eth0 root handle 1: htb default 12
Next, add a tc class. The is like a ‘pool’ of bandwidth. Set this to whatever your interface speed is:
tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit
Now we can create classes for specific bandwidth that we are going to assign to the IP address. The first line of code will be our limit and the second is our default as specified in the first command above:
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 2mbit ceil 2mbit
tc class add dev eth0 parent 1:1 classid 1:12 htb rate 5mbit ceil 5mbit
After that, create some tc filters to match certain criteria. In our case it is IP address. The ’src’ or ‘dst’ is specific to whether this interface is outside network or inside network. Notice how the flowid matches our classid from above. In a nutshell, if the IP address matches 12.13.14.15, we are going to get 2mbit, and if it is any other IP address we will get 5mbit:
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 12.13.14.15 flowid 1:10
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 0.0.0.0 flowid 1:12
Those commands will get you managing bandwith on eth0. To manage bandwidth in the same manner on the internal interface (eth1), enter the above commands, only replace “eth0″ with “eth1″ and in the tc filter commands replace “dst” with “src”.
This was a quick overview and example of HTB bandwidth management filtering by IP address for tc command on Linux. If you are interested in implementing these strategies take a look at some reading material below:
HTB Manual | Linux Advanced Routing & Traffic Control HOWTO | The tc manpage
EDIT: Looks like using HTB alone is a bit primitave. If a second data stream starts, it will only get whats left of the remaining bandwidth. So we add a SFQ command in the mix. This will treat all connections equally, even from the same IP and data streams will even each other out:
tc qdisc add dev eth0 parent 1:10 handle 20: sfq perturb 10
tc qdisc add dev eth0 parent 1:12 handle 30: sfq perturb 10
EDIT: It also has came to my attention that all tc commands are lost on reboot. The solution:
- mkdir /etc/tc
- vi /etc/tc/start.sh
#!/bin/sh
#Custom tc commands to throttle bandwidth
#All changes must be saved here, or a reboot will loose config!
#INSIDE NETWORK:
ENTER TC COMMANDS HERE
#OUTSIDE NETWORK:
ENTER TC COMMANDS HERE
- vi /etc/tc/stop.sh
#!/bin/sh
#Shutdown commands for tc traffic shaping, this is a static file
#INSIDE NETWORK:
tc qdisc del dev eth0 root
#OUTSIDE NETWORK:
tc qdisc del dev eth1 root
- vi /etc/init.d/tc
#!/bin/sh
### BEGIN INIT INFO
# Provides: Traffic Control
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 2 3 5
# Description: tc qdisc ;p
### END INIT INFO
case .$1. in
.start.)
/etc/tc/start.sh
;;
.stop.)
/etc/tc/stop.sh
;;
*)
echo “Usage: $0 { start | stop }”
;;
esac
exit 0