I have a DSL contract with 1&1 in Germany with the following nominal speeds: 1Mbps downlink and 128Kbps uplink. Having these limited speeds I have found bandwidth management to be a critical tool in order to achieve a good performance. Therefore, the intention of this article is to describe some particular bandwidth management techniques that I have found to be useful.
My home network setup is the following: I have the DSL modem from 1&1 and a Netgear WNDR3700v2 box running OpenWRT which provides Wi-Fi connectivity in the 2.4Ghz band. Regarding the connected devices we have an Asus Eeebox with Wi-Fi connected to a TV and acting as home theater PC, and then a couple of laptops and a couple of smartphones all connected also using Wi-Fi.
The main problem with our home network is latency under load. Our home theater PC often downloads media content from the Internet. Thus, when that happens the downlink path of the access link becomes congested, and being ours a line of only 1Mbps, the performance of anything else running in our home network heavily degrades.
To illustrate the previous problem the following two figures depict the latency incurred in fetching from a laptop in our home network the following two web pages: El Pais, a media site from Spain, and the main page of YouTube. These graphs are obtained using smokeping. Simultaneously to smokeping retrieving the web pages, our Asus Eeebox downloads a large file that completes at 22:25h. The effect of the file download on the latency in retrieving the web pages is obvious: El Pais goes from around one second under load down to around 200ms without load, and YouTube goes from around six seconds under load down to two seconds and almost no variability without load.
Figure 1: El Pais (www.elpais.com). Until 22:20 with background load, from then on without background load
Figure 2: YouTube (www.youtube.com). Until 22:20 with background load, from then on without background load
Ideally, we would like the media content being downloaded by the Asus Eeebox to not interfere with the web browsing done by other devices in the network. In order to do so what we can do is to set up two priority classes in the OpenWrt box that will divide the traffic coming from the Internet into a low priority and a high priority class. All the traffic addressed to the Asus Eeebox will be classified as low priority and the rest of the traffic will be classified as high priority.
In order to implement the previous policy the first thing to be done is to shift the bottleneck queue from the DSLAM sitting in 1&1 to our OpenWRT box. Thus, if the bottleneck occurs in our box, packets will queue up there instead of in the DSLAM, and we will be able to apply our policy by delaying the packets addressed to the Eeebox and expediting the transmission of the other packets. There is a catch though, and is that in order to push the congestion point from the DSLAM in 1&1 down to our OpenWRT box we need to give up some bandwidth. In the script that we show next this is achieved by using a token bucket filter that limits the downstream speed to 900Kbps instead of the contracted 1Mbps.
The bandwidth management script that we use is the following:
#!/bin/sh
#################################################################
# We want to police ingress in the following way: all traffic is
# moved to imqX that has two subclasses a HP one and a LP one.
# All the traffic from $IP_LP is classified into the LP class,
# and the rest of the traffic is classified into the HP class.
# The two classes can borrow bandwidth from each other in case
# one class does not have enough traffic.
# Author: Daniel Camps
# Date: Feb. 2012
#################################################################
INTERNET="eth1"
IMQ="imq1"
IP_LP="192.168.1.22/32"
DL_RATE="900kbit"
HP_RATE="890kbit"
LP_RATE="10kbit"
TC="tc"
IPTABLES="iptables"
IFCONFIG="ifconfig"
# Loading the required modules
insmod ifb
insmod sch_htb
insmod sch_ingress
insmod ipt_IMQ
insmod act_mirred
insmod act_connmark
insmod cls_u32
insmod cls_fw
insmod em_u32
# Bringing up the IMQ device
$IFCONFIG $IMQ up
# Adding the HTB scheduler to the ingress interface
$TC qdisc add dev $IMQ root handle 1: htb default 11
# add main rate limit classes
$TC class add dev $IMQ parent 1: classid 1:1 htb rate $DL_RATE
# add leaf classes: set the maximum bandwidth that each priority class can get, and the maximum borrowing they can do
$TC class add dev $IMQ parent 1:1 classid 1:10 htb rate $LP_RATE ceil $DL_RATE
$TC class add dev $IMQ parent 1:1 classid 1:11 htb rate $HP_RATE ceil $DL_RATE
# Filtering packets according to destination IP address
$TC filter add dev $IMQ parent 1: protocol ip prio 1 u32 match ip dst $IP_LP flowid 1:10
# Sending packets after SNAT has been done into the IMQ device
$IPTABLES -t mangle -A FORWARD -i $INTERNET -j IMQ --todev 1
In detail what the script does is to set up income traffic shaping on the interface connecting OpenWRT to the DSL modem, in our case eth1
. In order to do so you need to define a new IMQ device (imq1
), so that eth1
, redirects all incoming traffic to imq1
. In imq1
we then define the appropriate queuing disciplines. In particular we use a hierarchical token bucket, htb, to first define a token bucket filter that rate limits the interface to 900Kbps (in order to own the bottleneck in the OpenWRT box), and then define a high and low priority subclasses that share the available bandwidth. The high and low priority sub-classes have a minimum reserved bandwidth in case both classes have enough data to carry, otherwise one class is allowed to grab bandwidth from the other's share. Thus, this script should allow the low priority class to grab all the bandwidth when there is no high priority traffic, and yield to high priority when such traffic is present. Let's see how it works.
Figure 3: Concurrent background load (green) and YouTube video streaming (red). The YouTube video is transmitted with priority over the background traffic. The overall traffic is limited to 900Kbps.
Let us now assess the performance of our QoS script with Web traffic. For this purpose we repeat our original experiment where we used smokeping in order to track the page donlwoad time of El Pais and YouTube. In this case though, the Asus Eeebox starts performing a download in background at 16:25h. We can see now in the next two figures, how the web page download time is not affected by the background traffic as it used to be without the QoS script. A slight increase in download time is appreciated when the Asus Eeebox starts downloading at 16:25h, but this small increase results in no significant degradation in user experience.Figure 4: El Pais (www.elpais.com). Background traffic starts at 16:25.
Figure 5: YouTube (www.youtube.com). Background traffic starts at 16:25.
Ubuntu upgrades are another kind of annoying traffic that should go to low priority. However, I am not yet clear on how to filter it. I could classify all the long lived connections to low priority after they exceed a certain number of bytes using conntrack
, however that would probably screw up YouTube traffic, so no good.
There is no much uplink traffic in my network. However, I am considering using DropBox to share some files with friends and family. If we do that then DropBox will saturate our uplink bandwidth and bandwidth management will be required. If all DropBox traffic comes from the same device then filtering is easy, otherwise I am not yet sure how to do it.