Adaptivni Quality of Service s routerom Zyxel VMG5313-B30 i OpenWRT-om

Naslov ne govori puno o ovom projektiću, ali valjda ću ga dovoljno pojasniti da nekome bude koristan.

Situacija je sljedeća – imam Iskonov VDSL s maksimalnom brzinom od 30 megabita, iako mi linija daje između 23 i 26 mbita. Uz to imam i Iskon TV i koji mi uredno oduzima dostupan bandwidth dok radi. Kako je “zakupljena” brzina veća od brzine spajanja modema, s isključenim IPTV prijemnikom mogu iskoristiti i ta preostala tri-četiri megabita.

Uz sve ovo, imam TP-LINK TL-WDR3600  router koji odrađuje PPPoE konekciju i N-WLAN na 2.5 i 5 GHz. Gore se vrti OpenWRT Barrier Breaker. Jedna od korisnih mogućnosti koju OpenWRT nudi je jednostavno podesiv Quality of Service koji jamči da će svi klijenti imati jednake šanse kod pristupa netu i koji smanjuje prioritet stvarima koje su sklone zakucati vezu (npr. P2P). Da bi QoS dobro radio, potrebno mu je točno reći s kojom brzinom raspolaže i tu je problem koji sam imao – ako stavim nižu brzinu nikada neću moći iskoristiti povećanje brzine kod isključenog IPTV prijemnika. Ako stavim višu, QoS jednostavno neće raditi svoj posao.

Potrebno je, dakle, automatski mijenjati maksimalnu brzinu downloada u QoS servisu OpenWRT-a ovisno o tome radi li prijemnik ili ne.

Uz Iskonovu VDSL uslugu isporučuje se VDSL2 router Zyxel VMG5313-B30 koji je bogat opcijama, ali većina ih je uredno skrivena od običnih korisnika. Više o mogućnostima i kako do njih doći možete naći na forumima, ali ja sam trebao rješenje koje funkcionira s uobičajenom razinom pristupa.

Rješenje je bilo sljedeće, u kratkim crtama:

1. Kako je moj VDSL2 router u bridge modu, prvo sam morao osigurati pristup do modema kroz redovni LAN. To sam napravio tako što sam dodao još jedan mrežni interface s fiksnom IP adresom u subnetu modema (to je kod Iskona 192.168.5.x).

Konkretno, u /etc/config/interfaces trebalo je dodati:

config interface 'modem'
        option proto 'static'
        option netmask '255.255.255.0'
        option ifname 'eth0.2'
        option ipaddr '192.168.5.254'

(uz, naravno, kvačicu pokraj “Bring up on boot”).

2. Sad kad imamo pristup modemu, trebamo se u njega ulogirati i pronaći način kako da doznamo radi li IPTV receiver.

Prvo je jednostavno, u skriptu ćemo curlom napraviti post na login stranicu i snimiti cookije.

curl -s -l -b /tmp/cookie -c /tmp/cookie http://192.168.5.1/login/login-page.cgi -d "AuthName=Administrator&Display=Administrator&AuthPassword=Administrator"

Drugo je bilo malo teže. Jedini način prepoznati radi li IPTV receiver bilo je pod System Monitor – Traffic Status gdje se nalazi broj paketa u uploadu i downloadu po sučeljima (VDSL_VoIP, VDSL_IPTV, VDSL_Management). Trebamo, dakle, izvući taj podatak dva puta u određenom vremenskom razmaku i vidjeti ima li promjene i kolika je.

Uz popriličnu gnjavažu s Curlom i ostalim alatima za manipulaciju stringovima, dobio sam nešto ovakvo:

curl -s -b /tmp/cookie -c /tmp/cookie  http://192.168.5.1/pages/systemMonitoring/trafficStatus/wan.html | sed -nr 's/.*VDSL_IPTV\|ptm0\.3\|(.*)@1\|VDSL_Management.*/\1/p' | cut -d, -f4

Dakle isto to ponovimo za 10 sekundi i ako je razlika veća, receiver vjerojatno radi (čak i kada je isključen, na tom interfaceu postoji slab promet od jednog do dva paketa u sekundi, ne više od 15 paketa u 10 sekundi).

3. Treći dio je zapravo najjednostavniji – preko UCI sučelja postaviti odgovarajuću vrijednost brzine i reloadati QoS.

uci set qos.wan.download=VRIJEDNOST
uci commit qos
/etc/init.d/qos reload

A evo i cijele skripte. Prvo /etc/qostuner.sh, koju naravno treba učiniti izvršnom (chmod +x /etc/qostuner.sh)

#!/bin/sh
logger="logger -p daemon.info $0 $@"
WAIT="30"
HIGHER="24000"
LOWER="20500"
TRENUTNO=$(uci get qos.wan.download)
if [ "$TRENUTNO" == "$HIGHER" ]; then
IPTVON="0"
else
IPTVON="1"
fi
$logger "Starting up. Current speed limit is $TRENUTNO, Receiver: $IPTVON"
if [[ -s /tmp/cookie ]]
then
LOGIN="1"
else
LOGIN="0"
fi
while [ 1 ]; do
if [ "$LOGIN" == "0" ]; then
RESPONSE=$(curl -s -l -b /tmp/cookie -c /tmp/cookie http://192.168.5.1/login/login-page.cgi -d "AuthName=Administrator&Display=Administrator&AuthPassword=Administrator" | awk 'NR==4' | sed -e "s/\(.*'\)\(.*\)\('.*\)/\\2/")
if [[ $RESPONSE == "/index.html" ]]; then
LOGIN="1"
fi
fi

TRAFFIC=$(curl -s -b /tmp/cookie -c /tmp/cookie  http://192.168.5.1/pages/systemMonitoring/trafficStatus/wan.html | sed -nr 's/.*VDSL_IPTV\|ptm0\.3\|(.*)@1\|VDSL_Management.*/\1/p' | cut -d, -f4)
if [ $TRAFFIC != "" ]; then
sleep 10
TRAFFIC2=$(curl -s -b /tmp/cookie -c /tmp/cookie  http://192.168.5.1/pages/systemMonitoring/trafficStatus/wan.html | sed -nr 's/.*VDSL_IPTV\|ptm0\.3\|(.*)@1\|VDSL_Management.*/\1/p' | cut -d, -f4)
RAZLIKA=`expr $TRAFFIC2 - $TRAFFIC`
if [ "$RAZLIKA" -gt "50" ]; then
if [ "$IPTVON" == "0" ]; then
IPTVON="1"
$logger "IPTV Receiver on. Lowering QOS maximum speed to $LOWER."
uci set qos.wan.download=$LOWER
uci commit qos
/etc/init.d/qos reload
fi
else
if [ "$IPTVON" == "1" ]; then
$logger "IPTV Receiver is off. QOS maximum speed set to $HIGHER."
uci set qos.wan.download=$HIGHER
uci commit qos
IPTVON="0"
/etc/init.d/qos reload
fi
fi
else
LOGIN="0"
rm /tmp/cookie
fi
sleep $WAIT
done

Uz to, trebat ćemo i startup skriptu (/etc/init.d/qostuner)

#!/bin/sh /etc/rc.common
START=90
start() {
/etc/qostuner.sh &
}

stop() {
killall -9 qostuner.sh
}

Naravno, u skripti trebate podesiti vrijednosti više i niže brzine ovisno o svojoj liniji, te omogućiti da se skripta pokreće automatski kod pokretanja routera.