Qos su firmware *wrt

Scriverò molte ovvietà per chi è esperto.
Nota: purtroppo non è possibile mettere una qdisc strutturata come ingress, c'è solo una qdisc semplice a cui applicare una policy grezza: quanta banda deve passare prima del drop.
Nota2: sembra che la pfifo_fast non sia usabile come classless qdisc figlia di qualche classe. Devi usare la prio che è in pratica uguale.

Update: no in pratica, almeno nel gargoyle 1.4.0 la pfifo_fast è in pratica la prio, che non è una classful qdisc ma una classless qdisc. LOL.

Nota3: ricorda che la htb non può avere (IIRC) figli non HTB con lo stesso numero maggiore (X:Y in questo caso X)

Informazioni utilizzate


Usando le informazioni contenute qui:

Informazioni sul qos presente nella dd-wrt versione v24-sp2 usando lo scheduler HTB sulla porta WAN


Router: tplink wr741nd. (ma dovrebbe valere in generale)
Usando telnet si scopre che l'interfaccia su cui lavora il qos è eth0.
Su questa interfaccia è applicata una qdisc (politica di accodamento o queueing discipline, io userò a volte la parola scheduler) HTB con alcuni parametri che spero di spiegare in seguito:

root@741nd:~# tc qdisc show dev eth0
qdisc htb 1: root refcnt 2 r2q 10 default 30 direct_packets_stat 6

Si crea il nodo (perchè è possibile creare una gerarchia di condizioni) 1:0 (qui scritto 1:) radice. Un parametro importante è che tutti i pachetti che non riescono ad essere classificati finiranno nel nodo con identificatore 1:30 nella gerarchia (default 30).

Questo è l'unica disciplina presente sull'interfaccia, dopodichè la gestione nel dettaglio è data dalle code suddivise in classi e dai filtri che identificano la giusta classe per ogni pacchetto in uscita dalla rete.

Vediamo le classi.

root@741nd:~# tc class show dev eth0
class htb 1:10 parent 1:2 prio 4 rate 300000bit ceil 400000bit burst 6Kb cburst 2100b
class htb 1:100 parent 1:1 prio 2 rate 100000Kbit ceil 100000Kbit burst 1000Kb cburst 126600b
class htb 1:1 root rate 100000Kbit ceil 100000Kbit burst 1000Kb cburst 126600b
class htb 1:2 parent 1:1 rate 400000bit ceil 400000bit burst 6Kb cburst 2100b
class htb 1:20 parent 1:2 prio 5 rate 60000bit ceil 400000bit burst 6Kb cburst 2100b
class htb 1:30 parent 1:2 prio 6 rate 40000bit ceil 400000bit burst 6Kb cburst 2100b
class htb 1:40 parent 1:2 prio 7 rate 1000bit ceil 400000bit burst 6Kb cburst 2100b

Si ha un primo nodo, 1:1, che è legato alla root. Questo nodo utilizza la qdisc htb, ha un rate normale di 100Mbit con un limite (ceil) di 100Mbit. Può mandare tutti di fila (burst) al massimo 1Mbit se il rate di invio è entro la soglia normale, altrimenti può mandare 126.6Kbit. Tuttavia questa classe, in pratica non "manda" niente, al limite accumula token da distribuire alle classi figlio. Solo le classi figlio (senza nodi figli a loro volta) effettivamente "mandano" dati sulla rete. In pratica un pacchetto passa sempre dalle classi interne (con figli) consumandogli token "virtuali". I token in pratica servono a più scopi, ma qui si può immaginarli come "moneta virtuale" per mandare un pacchetto. Le classi interne hanno moneta virtuale che spendono quando instradano, nella classificazione, un pacchetto ai loro figli.
Il figlio di 1:1 è 1:2, che ha un rate di 400Kbit un limite uguale ed un certo tasso di invio massimo. la 1:2 serve per creare 4 sottoclassi utili.
Poi ci sono le classi legate alle priorità che selezioniamo dalla WebGUI.
La classe 10 (Premium) ha la priorità che è la seconda solo alla classe 1:100 (più è basso il numero più è alta la priorità). La priorità serve a distribuire la banda non richiesta. Comunque si osserva che ci sono 4 figli della classe 1:2. Premium (1:10), Express (1:20), Standard (1:30), Bulk (1:40). Come si vede i pacchetti non classificati finiscono nella classe standard.
Solo una classe è praticamente identica alla classe radice (quella più potente), la classe Exempt (1:100). Tralasciando questa classe notiamo che tutte e 4 le classi hanno un limite uguale (questo perchè, utilizzando la banda disponibile realmente [io ho settato 400Kbit] si può arrivare a sfruttare una banda di 400Kbit se le altre classi non sono in uso) ma una banda disponibile (rate), quando non c'è banda in eccesso, molto diversa. La premium usa quasi tutta la banda (300Kbit su 400), la express usa 60Kbit, la standard 40Kbit e la bult 1Kb. I valori di burst e cburst sono tutti identici, alla fine conviene agire più su rate e la priorità che su altro.

Da notare che essendo la classe di default la 30 (cioè la standard, 1:30) se non si crea una regola via webGUI che assegna a tutto il traffico di "default" in uscita la priorità bulk non si ottengono grandi prestazioni mentre si usano contemporanemante sia connessioni ad alto consumo di banda (ftp/p2p) che a bassa latenza (gaming, skype).

Poi infine ci sono i filtri, che intercettano i pacchetti in uscita e li assegnano alle varie classi.

filter parent 1: protocol ip pref 2 fw
filter parent 1: protocol ip pref 2 fw handle 0x64 classid 1:100
filter parent 1: protocol ip pref 3 fw
filter parent 1: protocol ip pref 3 fw handle 0x28 classid 1:40
filter parent 1: protocol ip pref 4 u32
filter parent 1: protocol ip pref 4 u32 fh 800: ht divisor 1
filter parent 1: protocol ip pref 4 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:10
match 00010000/00ff0000 at 8
filter parent 1: protocol ip pref 4 u32 fh 800::801 order 2049 key ht 800 bkt 0 flowid 1:10
match 00060000/00ff0000 at 8
match 05000000/0f00ffc0 at 0
match 00100000/00ff0000 at 32
filter parent 1: protocol ip pref 5 fw
filter parent 1: protocol ip pref 5 fw handle 0x1e classid 1:30
filter parent 1: protocol ip pref 7 fw
filter parent 1: protocol ip pref 7 fw handle 0x14 classid 1:20
filter parent 1: protocol ip pref 9 fw
filter parent 1: protocol ip pref 9 fw handle 0xa classid 1:10

Alcune scritte sono ancora da decifrate ma è una parte trascurabile per fini pratici. In sostanza lavorano con i "segni" (marks) assegnati ai vari pacchetti dal programma iptables, infatti "fw" indica un controllo sul mark (fw = firewall [marks]). Se il controllo combacia allora si applica il filtro al pacchetto. Si vede che i filtri classificano pacchetti per le classi che abbiamo visto prima, sono tutti quelli che finicono con "classid 1:40" o "flowid 1:10".
Da notare la dicitura "pref" che è come la priorità, è tanto più alta tanto più è basso il numero (pref 2 viene prima di pref 9), quindi si verifica prima il filtro pref 2 e poi il filtro pref 9.

Qdisc disponibili nella versione v24-sp2 11/21/10


Più precisamente

DD-WRT v24-sp2 std (c) 2010 NewMedia-NET GmbH
Release: 11/21/10 (SVN revision: 15778)

Bisogna usare (credo) in /lib/modules/2.6.34.7-svn15501
cat modules.builtin | grep sch_

trovando cbq, htb, hfsc, red (anche se di sicuro c'è il pfifo ed il pfifo fast quindi non è una lista completa, forse ci sono quelli più complessi). Di sicuro manca il tbf (token bucket filter).
Trovato, ho cercato la buil per chip atheros (o almeno questo credo sia la mia) qui (è il file di configurazione per la build). Se si va alla sezione Queueing/Scheduling si vede quali qdisc sono implementate. Fino ad ora è vero che se trovo una qdisc implementata mi funziona e se provo una non implementata non mi funziona. Update: no alcune che dovrebbero essere implementate non funzionano, quindi credo sia a seconda della build/firmware dedicato per un dato router. Vedi pure sezione manual settings

Old "manual" settings


goal: don't waste upload bandwidth but try to keep low latency for gaming traffic even if all the bandwith is required.

#set the main queueing discipline (qdisc) for the interface eth0
tc qdisc add dev eth0 root handle 1:0 htb default 40

#add child of the main qdisc as tree:
# root is 1:0 (handle 1:0), the child is 1:1
# child of 1:1 are 1:20, ... , 1:40
# Each leaf class (1:20, ... , 1:40) has differents "guaranteed" rates, but alla classes can reach the same max rate (ceil).
# each leaf class has different priority that is useful for assign the unused bandwidth and (I am not sure @ 100%) the priority of the packet dequeueing
tc class add dev eth0 parent 1:0 classid 1:1 htb rate 405kbit burst 6kb
tc class add dev eth0 parent 1:1 classid 1:10 htb prio 1 rate 250kbit ceil 405kbit burst 6kb
tc class add dev eth0 parent 1:1 classid 1:20 htb prio 2 rate 100kbit ceil 405kbit burst 6kb
tc class add dev eth0 parent 1:1 classid 1:30 htb prio 3 rate 40kbit ceil 405kbit burst 6kb
tc class add dev eth0 parent 1:1 classid 1:40 htb prio 4 rate 1kbit ceil 405kbit burst 6kb

#here we classify directly, using iptables, the packets of different clients in different classes
iptables -t mangle -A POSTROUTING -s 192.168.1.200 -j CLASSIFY --set-class 1:30
iptables -t mangle -A POSTROUTING -s 192.168.1.9 -j CLASSIFY --set-class 1:30
iptables -t mangle -A POSTROUTING -s 192.168.1.201 -j CLASSIFY --set-class 1:40
iptables -t mangle -A POSTROUTING -s 192.168.1.10 -j CLASSIFY --set-class 1:40

notes on wr741nd with 15778 build:

  1. the following qdiscs (classless or classful) don't work -

cbq, wrr, tbf, prio

  1. the following targets for iptable's chains don't work

-j TOS (useful to exploit the pfifo_fast qdisc)

PS: i didn't use red or hfsc qdisc manually (that are available), maybe these ones are more powerful to achieve the goal.

My WR741ND v2.4 dd-wrt experience


Ok, since free and shared knowledge is better than all other things in this world, and i have spent a lot of hours to search main informations about 3rd party firmwares on WR741ND, i will write some stuff to other users that have had my same doubts. (sorry for English)

First: dd-wrt works on v2.4? yes (at least build 15778)

1. download images from dd-wrt router databases (that works, in the descriptions, from 1.X to 2)

2. load the first image (factory 2 dd-wrt)

3. do a 30-30-30 hard reset

4. load the second image ( webflash )

5. do a 30-30-30 hard reset

6. here you are, your router is ready with a really good, user friendly and with a lot of options firmware (the best for average home user imo).

Now, i needed (also actually) a good qos system, so i play a bit with HTB and HFSC qdisc (queueing disciplines) with via web gui. HTB is great for assign the right bandwidth, and the HFSC is better for latency but i weren't satisfied. So i start to learn some things about traffic control to set my own rules.

Then i discovered that some qdisc like tbf, prio, wrr are missing from the 15778 build. Anyway at least htb, hfsc, p/bfifo, pfifo_fast, red are available. I didn't want to spend a lot of time on this, so i skip the (maybe) powerful but not so user friendly hfsc and red qdisc to use the others.
p/bfifo is too simple, unfortunately
pfifo_fast should be enough but i can change the TOS of packets with iptables's target -j TOS , maybe because the TOS target is missing in build 15778.
After i used the Htb. Htb works almost well with fine tuning hierarchy, but is a bit worse than my old (but gold) qos on usr 9105 when i use a lot of upload bandwidth with p2p and in the same time i play online. (i repeat myself, it's my fault that i didn't learn how to set manually the red/hfsc qdisc)

Eventually i decided to try openwrt, so i need the revert back firmware (here: http://www.dd-wrt.com/phpBB2/viewtopic.php?t=85237)

7. load the revert back the firmware and do the 30.30.30 reset

(note that dd-wrt's products allow the entire process of load and revert a custom firmware with user friendly steps)

8. after that, do what you want. For example now i'm trying gargoyle (openwrt based) that, on a first impression, has less WebGUi options in some fields.

Manual qos settings on tplink wr741nd with gargoyle 1.4.0 r27980


REMEMBER UNIX (\N) LINE ENDINGS ENCODE!

Nota sul dequeueing dei pacchetti di una struttura con qdisc htb


Chiedendo sul chanale irc del http://lartc.org/ ho avuto conferma che l'htb crea un flusso di uscita dei pacchetti ordinato secondo priorità. Mi spiego meglio: se ho 2 classi foglia di un albero con regole htb, una con priorità 1 ed una con priorità 2. Anche se entrambe possono mandare pacchetti, se i pacchetti sono accodati, passeranno prima i pacchetti della classe con priorità 1 e poi quelli con priorità 2. Una sorta di riferimento, qui.

Update: Niente, come al solito quando si ha fretta di ottenere informazioni per avere una cosa funzionante si fanno mezzi pasticci. Allora nell'htb manual alla sezione 6 si spiega con un esempio che ruolo ha la priorità. Non solo la priorità ha un ruolo sulla banda (come distribuisco la banda non utilizzata se due classi che han saturato la banda me ne chiedono altra?) ma anche sul delay, basta vedere che quando una delle classi, dopo 3 secondi, ottiene una priorità migliore (0) poi il suo ritardo nei pacchetti è in pratica nullo (indipendentemente dai settings sulla banda). Domanda: allora perchè mi metto a giocare sui settings sulla banda se la priorità invia all'interfaccia i pacchetti in modo indipendente da questi? Riposta: sia perchè l'ISP taglia la connessione se rileva variazioni troppo repentine, sia perchè l'interfaccia comunque richiede un certo tempo per inviiare i pacchetti quindi la priorità non basta ma bisogna fare in modo che quando arrivano pacchetti prioritari i pacchetti meno prioritari si accumulino più velocemente.

Note sul borrowing dei pacchetti di una struttura con qdisc htb


In aggiornamento man mano che consolido la mia conoscenza per tentativi/domande sui forum/analisi del codice (seh).
Il problema è avere una linea che permetta upload continuo, basso ping quando serve che non attivi la condizione di "disconnessione" imposta a monte dall'ISP, che, a quanto ho capito, viene attivata quando si vogliono inviare molti pacchetti in poco tempo (situazione standard subito dopo uan riconnessione)


Leggendo sul manuale online (htb home) e vedendo il comportamento sul router (con tc -s class show dev nomeInterfacciaSuCuiSiHaIlQos), si ha che: 1 token = 1 byte, mentre il borrowing è legato ai token ed ai pacchetti.
In pratica una classe figlia chiede alla classe padre (o altri ma in generale al padre) un quantativo di token (e quindi di banda) pari alla dimensione in byte del pacchetto da inviare. Se il prestito (a fondo perduto) ha successo, il padre segna +1 nel campo lended (cioè pacchetti prestati e non token) ed il figlio segna +1 nel campo borrowed (cioè prestiti sui pacchetti). Quindi il borrowing dipende dai token, la generazione dei token dipende dal burst e dal rate. Se si permette un burst troppo alto, si avranno sempre token (specie se il rate non è basso) e ciò non va bene poichè bisogna avere token limitati altrimenti si inviano troppi pacchetti in poco tempo. Sto facendo dei test per verificare l'idea.
Per ora si è visto che anche con burst miseri (500byte, 1/3 della dimensione max del pacchetto, di 1492 byte) tutto funge bene, almeno in upload e la linea sembra soffrire poco.

Nota importante: una classe "genitore" indirizzerà i pacchetti ai figli (nota che un pacchetto viene inviato solo dopo che è arrivato alla classe oglia) fintantochè ha tokens disponibili (anche se la classe stessa non invia, realmente, nulla), altrimenti i pacchetti i accumuleranno. I token, come abbiamo detto, dipendono dal valore di rate e burst della classe. Quindi è possibile che una classe genitore abbia un valore di burst inferiore del valore di burst di una classe figlia. Semplicemente ciò vuol dire che la classe figlia, con molta probabilità, avrà un quantitativo di token disponibili molto alto (e quindi difficilmente consumabile) e non chiederà mai prestiti alla classe genitore (sempre se il burst elevato è associato ad un rate sfficiente).
In questo modo (con burst limitati che limitano i token disponibili) si possono creare classi figlie che chiedono pochi prestiti e possono inviare molti pacchetti senza problemi ed altre classi figlie che chiedono spesso prestiti ma trovano anche le classi genitore prive di token e quindi comunque devono aspettare.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License