QoS (Quality of Service) prioritize your network trafic. Here is a way to do it on your OpenWrt.

The proposed script divide your outgoing network trafic into 5 priority classes as follow:

  • 1 - ping, DNS, ack : very fast
  • 2 - gaming, SSH : high priority, reliable
  • 3 - local services : good bitrate, average response time
  • 4 - users: web and email(default class)
  • 5 - peer 2 peer

Download the qos script. It contains a few comments (in french) but here are more details:

The first script section contains a set of defines where you can set average and maximum bitrate for your network connexion and each priority class. Change the values according to your internet connexion bitrate.

MAX_DL=10000
MAX_DL_BURST=200
MAX_UP=2000
MAX_UP_BURST=40

AVER_PRIO=200
MAX_PRIO=200

AVER_JEUX=300
MAX_JEUX=300

AVER_SERVEURS=200
MAX_SERVEURS=1000

AVER_UTILISATEURS=300
MAX_UTILISATEURS=1000

AVER_P2P=50
MAX_P2P=500

First of all, the modules used by QoS has to be loaded. If you get any error during the module loading sequence, make sure the associated packages are installed.

echo 'Chargement des modules' >> $log 2>> $log
insmod sch_htb >> $log 2>> $log
insmod sch_tbf >> $log 2>> $log
insmod sch_sfq >> $log 2>> $log
insmod cls_u32 >> $log 2>> $log
insmod cls_fw >> $log 2>> $log
insmod sch_ingress >> $log 2>> $log
insmod ipt_connmark >> $log 2>> $log
insmod ipt_CONNMARK >> $log 2>> $log
insmod ipt_ipp2p >> $log 2>> $log

We remove all existing rules before creating new ones.

echo 'Suppression des tables' >> $log 2>> $log
tc qdisc del dev $WAN root >> $log 2>> $log
tc qdisc del dev $WAN ingress >> $log 2>> $log

Now let's create some classes. We will be using an HTB (Hierarchical Token Bucket) queue for all our rules. This manager copes well with network bitrate changes. For more information about HTB, check Martin Devera (devik)'s pages.

echo '*** Création des classes ***' >> $log 2>> $log

echo 'Création de la racine HTB' >> $log 2>> $log
tc qdisc add dev $WAN root handle 1: htb default 40 >> $log 2>> $log

echo 'Limitation globale du lien' >> $log 2>> $log
tc class add dev $WAN parent 1: classid 1:1 htb \
rate ${MAX_UP}kbit ceil ${MAX_UP}kbit burst ${MAX_UP_BURST}k >> $log 2>> $log

echo 'Classe ping' >> $log 2>> $log
tc class add dev $WAN parent 1:1 classid 1:10 htb \
rate ${AVER_PRIO}kbit ceil ${MAX_PRIO}kbit burst 50k prio 0 >> $log 2>> $log

echo 'Classe jeux' >> $log 2>> $log
tc class add dev $WAN parent 1:1 classid 1:20 htb \
rate ${AVER_JEUX}kbit ceil ${MAX_JEUX}kbit burst 50k prio 1 >> $log 2>> $log

echo 'Classe serveurs' >> $log 2>> $log
tc class add dev $WAN parent 1:1 classid 1:30 htb \
rate ${AVER_SERVEURS}kbit ceil ${MAX_SERVEURS}kbit burst 50k prio 2 >> $log 2>> $log

echo 'Classe utilisateurs' >> $log 2>> $log
tc class add dev $WAN parent 1:1 classid 1:40 htb \
rate ${AVER_UTILISATEURS}kbit ceil ${MAX_UTILISATEURS}kbit burst 30k prio 3 >> $log 2>> $log

echo 'Classe p2p' >> $log 2>> $log
tc class add dev $WAN parent 1:1 classid 1:50 htb \
rate ${AVER_P2P}kbit ceil ${MAX_P2P}kbit burst 5k prio 4 >> $log 2>> $log

Our classes are now created and are going to attach them to a SFQ manager. It will split available bandwidth in a quite fair way between the streams enqueued in the HTB manager.

echo 'Gestion des classes' >> $log 2>> $log
tc qdisc add dev $WAN parent 1:10 handle 10: sfq perturb 10 >> $log 2>> $log
tc qdisc add dev $WAN parent 1:20 handle 20: sfq perturb 10 >> $log 2>> $log
tc qdisc add dev $WAN parent 1:30 handle 30: sfq perturb 10 >> $log 2>> $log
tc qdisc add dev $WAN parent 1:40 handle 40: sfq perturb 10 >> $log 2>> $log
tc qdisc add dev $WAN parent 1:50 handle 50: sfq perturb 10 >> $log 2>> $log

We now create filters to flag network trafic and put each packet in the right queue.

The first class is for the ICMP (to get a low ping), DNS requests, TCP ACK and VPN trafic.

echo 'Classe 1' >> $log 2>> $log
echo ' - ICMP' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 0 \
u32 match ip protocol 1 0xff flowid 1:10 >> $log 2>> $log
echo ' - ACK' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 0 \
u32 match ip protocol 6 0xff \
match u8 0x05 0x0f at 0 \
match u16 0x0000 0xffc0 at 2 \
match u8 0x10 0xff at 33 \
flowid 1:10 >> $log 2>> $log
echo ' - DNS' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 0 \
u32 match ip dport 53 0xff flowid 1:10 >> $log 2>> $log
echo ' - VPN' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 1 u32 \
match ip dport 1723 0xffff flowid 1:10 >> $log 2>> $log

Second class will take care of SSH connections...

echo 'Classe 2' >> $log 2>> $log
# le bit Délai Minimum du champ TOS (ssh, PAS scp) est dirigé vers 1:10
echo ' - Champ TOS' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip tos 0x10 0xff flowid 1:20 >> $log 2>> $log
echo ' - serveur SSH' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip dport 22 0xffff flowid 1:20 >> $log 2>> $log
echo ' - client SSH' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip sport 22 0xffff flowid 1:20 >> $log 2>> $log

... and provide us low ping on network games! Adjust the port list to the one used by your favorite video games.

echo ' - serveur DC' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip sport 14567 0xffff flowid 1:20 >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip sport 14667 0xffff flowid 1:20 >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip sport 14690 0xffff flowid 1:20 >> $log 2>> $log
echo ' - serveur CZ' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip sport 27015 0xffff flowid 1:20 >> $log 2>> $log
echo ' - serveur Q3' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip sport 27960 0xffff flowid 1:20 >> $log 2>> $log
echo ' - serveur TS' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip sport 8767 0xffff flowid 1:20 >> $log 2>> $log

echo ' - client DC' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip dport 14567 0xffff flowid 1:20 >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip dport 14667 0xffff flowid 1:20 >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip dport 14690 0xffff flowid 1:20 >> $log 2>> $log
echo ' - client CZ' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip dport 27015 0xffff flowid 1:20 >> $log 2>> $log
echo ' - client Q3' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip dport 27960 0xffff flowid 1:20 >> $log 2>> $log
echo ' - client TS' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 5 u32 \
match ip dport 8767 0xffff flowid 1:20 >> $log 2>> $log

The third class will limit outgoing trafic resulting from a local HTTP or FTP server.

echo 'Classe 3' >> $log 2>> $log
echo ' - HTTP' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 10 u32 \
match ip sport 80 0xffff flowid 1:30 >> $log 2>> $log
echo ' - HTTPS' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 10 u32 \
match ip sport 443 0xffff flowid 1:30 >> $log 2>> $log
echo ' - FTP' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 10 u32 \
match ip sport 20 0xffff flowid 1:30 >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 10 u32 \
match ip sport 21 0xffff flowid 1:30 >> $log 2>> $log
#tc filter add dev $WAN parent 1: protocol ip prio 10 u32 \
#match ip sport 49152 0xc000 flowid 1:30 >> $log 2>> $log
#tc filter add dev $WAN parent 1: protocol ip prio 10 u32 \
#match ip sport 65535 0xc000 flowid 1:30 >> $log 2>> $log

Then comes the "user trafic", basically web surfing and mail.

tc filter add dev $WAN parent 1: protocol ip prio 20 u32 \
match ip dport 80 0xffff flowid 1:40 >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 20 u32 \
match ip dport 443 0xffff flowid 1:40 >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 20 u32 \
match ip dport 8080 0xffff flowid 1:40 >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 20 u32 \
match ip dport 25 0xffff flowid 1:40 >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 20 u32 \
match ip dport 143 0xffff flowid 1:40 >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 20 u32 \
match ip dport 993 0xffff flowid 1:40 >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip prio 20 u32 \
match ip dport 995 0xffff flowid 1:40 >> $log 2>> $log

And last class is for p2p. Note we're using iptables and mangle to flag connexions.

echo 'Classe 5' >> $log 2>> $log
echo ' - initialisation mangle' >> $log 2>> $log
/usr/sbin/iptables -t mangle -F
/usr/sbin/iptables -t mangle -X
echo ' - Récupération du marquage des connexions' >> $log 2>> $log
/usr/sbin/iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
echo ' - Elimination des connexions déjà marquées' >> $log 2>> $log
/usr/sbin/iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j ACCEPT

echo ' - Création des règles de gestion du traffic P2P'
/usr/sbin/iptables -t mangle -N p2p_mangle
/usr/sbin/iptables -t mangle -A PREROUTING -m ipp2p --ipp2p -j p2p_mangle

echo ' - Redirection des connexions TCP P2P marquées' >> $log 2>> $log
tc filter add dev $WAN parent 1: protocol ip handle 50 fw flowid 1:50

echo ' - Marquage du traffic P2P' >> $log 2>> $log
/usr/sbin/iptables -t mangle -A p2p_mangle -m ipp2p --ipp2p -j MARK --set-mark 50 >> $log 2>> $log

echo ' - Sauvegarde des marques pour la durée de la connexion' >> $log 2>> $log
/usr/sbin/iptables -t mangle -A PREROUTING -j CONNMARK --save-mark

Great, we applied traffic shaping to all our outgoing connexions Laughing

Now let's talk about ingoing trafic. When you are downloading something, your ISP enqueue packets so you always have data to download and can use your connexion at its maximum speed. However, enqueuing packet creates lag. The following rule's goal is to remove some packets to lower your ISP emission queue, ensuring a more dynamic and responsive trafic.

echo 'Création ingress' >> $log 2>> $log
tc qdisc add dev $WAN handle ffff: ingress >> $log 2>> $log
echo 'Limitation de la queue de téléchargement' >> $log 2>> $log
tc filter add dev $WAN parent ffff: protocol ip prio 1 u32 match ip src \
0.0.0.0/0 police rate ${MAX_DL}kbit burst ${MAX_DL_BURST}k drop flowid :1 >> $log 2>> $log

That's it, you should now be able to play online while your roomate is downloading stuff or watching videos online Wink