OpenWRT QoS – a Simple Recipe

Low priority traffic is clogging your Internet connection? Read on.

This is NOT a definitive guide, as tc is very complex powerful – what follows is merely a simple working example on how to prioritize traffic in OpenWRT (or, actually, any Linux box) using tc.

First of all, traffic prioritization happens only when there is traffic to be sent and only if the pipe is too small, so that the packets have to wait in queue, i.e. when traffic control can choose from multiple packets the packet to send first. It’s not possible to directly prioritize traffic being received (although, for TCP connections, delaying ACK packets will make sender slow down).qos

That said, here is how the script attached below works:

  1. It deletes all queuing disciplines from the internet interface $IF_DSL
  2. It defines root queue 1, specifying that by default traffic will be sent with class 20 (1:20 below)
  3. It creates a sub queue/class 1:1 clamping down traffic at ISP upload speed. This is needed to make sure the queue is created in the router, not in the cable/DSL modem, connected to the router by much faster connection
  4. It creates 3 sub-queues/classes:
    1. 1:10 for real-time priority traffic. The parameters mean that it can send at speed limit for up to 60ms, and after that send at 20% of the speed limit, if there is a queue.
    2. 1:30 for bulk traffic – 10% of the speed limit if there is a queue, otherwise full speed
    3. 1:20 for everything else – 70% of interface speed if there is a queue, otherwise full speed
  5. If all classes are present, they will share the link at 20%:10%:70%, if one is absent, remaining classes will share the link in proportion, e.g. 10%:70%
  6. Now we use iptables to mark the traffic destined for each queue:
    1. Everything coming from the home server $IP_SERVER is considered bulk (e.g. cloud backup)
    2. TCP SYN, RST, ACK are sent in real-time
    3. SSH is sent in real-time
    4. Small TCP (not sustained transmission) and UDP (including VoIP) packets are sent in real-time
    5. ICMP is sent in real-time
    6. Everything else is normal, as specified in the step 2 above

To run the script, make sure you install the following packages: tc, kmod-ipt-ipopt, iptables-mod-ipopt. Upload the script to your router and set it up as a startup script:

  1. Use you favorite ssh FTP app, e.g. winscp on windows or Nemo on linux
  2. Put the file below to /root – your home folder as tc.sh
  3. In LuCi >> System >> Startup page, put a command “/bin/sh /root/tc.sh” without quotes somewhere before last line “exit 0”
#!/bin/sh
 
##############################################################
# Variables
TC=/usr/sbin/tc #-------- location of traffic control
IPT=/usr/sbin/iptables #- location of iptables
IF_DSL=eth0 #------- interface to dsl
UP_RATE=6400 #------------ available bandwidth in kilobits/sec
IP_SERVER=192.168.1.195
 
MODULES='xt_length sch_hfsc sch_ingress'
 
##############################################################
# Load modules
for i in $MODULES ; do
        insmod $i
done
 
##############################################################
# Manipulating qdiscs
$TC qdisc del dev $IF_DSL root    2> /dev/null > /dev/null
$TC qdisc del dev $IF_DSL ingress 2> /dev/null > /dev/null
###
# set root default bucket
$TC qdisc add dev $IF_DSL root       handle  1:   hfsc default 20
$TC class add dev $IF_DSL parent 1:  classid 1:1  hfsc sc rate ${UP_RATE}kbit ul rate ${UP_RATE}kbit
# rt
$TC class add dev $IF_DSL parent 1:1 classid 1:10 hfsc rt m1 ${UP_RATE}kbit d 60ms m2 $((20*$UP_RATE/100))kbit
# normal
$TC class add dev $IF_DSL parent 1:1 classid 1:20 hfsc ls rate $((70*$UP_RATE/100))kbit ul rate ${UP_RATE}kbit
# bulk
$TC class add dev $IF_DSL parent 1:1 classid 1:30 hfsc ls rate $((10*$UP_RATE/100))kbit ul rate ${UP_RATE}kbit

##################################################################
# drop existing mangle rules in POSTROUTING
$IPT -t mangle -F POSTROUTING
 
IPTMOD="$IPT -t mangle -A POSTROUTING -o $IF_DSL"
 
##################################################################################
# server upload - bulk
$IPTMOD -s $IP_SERVER -j CLASSIFY --set-class 1:30
# real-time
$IPTMOD -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j CLASSIFY --set-class 1:10
$IPTMOD -p tcp --dport 22 -j CLASSIFY --set-class 1:10
$IPTMOD -p udp -m length --length :170 -j CLASSIFY --set-class 1:10
$IPTMOD -p tcp -m length --length :148 -j CLASSIFY --set-class 1:10
$IPTMOD -p icmp -j CLASSIFY --set-class 1:10
# everything else is normal traffic
# tc qdisc del dev eth0 root
# tc qdisc del dev eth0 ingress

Download script as a text file: ts-example.sh.txt

Credits:

  1. http://www.linuxquestions.org/questions/linux-networking-3/expanding-my-tc-script-to-include-prioritizing-for-tcp-syn-ack-etc-4175479817/
  2. https://wiki.openwrt.org/doc/howto/packet.scheduler/packet.scheduler.example3
  3. http://man7.org/linux/man-pages/man7/tc-hfsc.7.html

Leave a Reply

Your email address will not be published. Required fields are marked *