QoS si HTB in Linux: Diferență între versiuni

De la Wiki.lug.ro
Salt la: navigare, căutare
(rospelled)
Linia 7: Linia 7:
  
  
In articolul de fata imi propun sa detaliez implementarea unei solutii de QoS folosind Linux si HTB.
+
În articolul de faţă îmi propun detaliez implementarea unei soluţii de QoS folosind Linux şi HTB.
  
Aceasta solutie este ideala retelelor care impart o singura iesire in internet (internet prin cablu, DSL, ISDN, etc) folosind NAT (Network Address Translation). Atat in Romania cat si in strainatate acest tip de configurare (stub network) este extrem de raspandit pentru retelele mici si medii (maxim cateva sute de calculatoare).
+
Această soluţie este ideală reţelelor care împart o singura ieşire pe internet (internet prin cablu, DSL, ISDN, etc) folosind NAT (Network Address Translation). Atât în România cât şi în străinătate acest tip de configurare (stub network) este extrem de răspândit pentru reţelele mici şi medii (maxim câteva sute de calculatoare).
  
Subiectul de fata este considerat avansat, de aceea o baza solida in ceea ce priveste Linux, Networking si QoS este necesara pentru intelegerea in profunzime. Anumite expresii le voi lasa in limba engleza intentionat, fiindca traducera lor ar fi nenaturala si nejustificata.
+
Subiectul de fata este considerat avansat, de aceea o bază solidă în ceea ce priveşte Linux Networking şi QoS este necesară pentru înţelegerea în profunzime. Anumite expresii le voi lăsa în limba engleza intenţionat, deoarece traducerea lor ar fi nenaturală şi nejustificată.
  
Scopul procesului de "bandwidth management" este de a nu permite unui singur protocol sau client sa consume toata banda existenta sau mai mult de cat ii este permis. Banda acesta trebuie sa fie impartita intre toate protocoalele in functie de necesitati. Noi trebuie sa fim cei care controleza coada si nu ISP-ul sau modemul de dsl/catv unde nu avem nici o influenta. Aceasta trebuie sa fie minima sau cel mai bine sa nu existe.
+
Scopul procesului de "bandwidth management" este de a nu permite unui singur protocol sau client consume toata banda existentă sau mai mult de cât îi este permis. Banda acesta trebuie fie împărţită între toate protocoalele în funcţie de necesităţi. Noi trebuie fim cei care controlează coada şi nu ISP-ul sau modemul de dsl/catv unde nu avem nici o influenţa. Aceasta trebuie fie minima sau cel mai bine nu existe.
Exista si un trade-off. In general se poate folosi maxim 75% din banda oferita de ISP. Pentru a avea coada mica suntem obligati sa transmitem la doar 70-75% din capacitate. Oricum informatia utila nu scade considerabil daca transmitem la 75% fiindca in momentul in care transmitem la 100%, multe pachete se pierd, apar coliziuni etc si trebuie retransmise.
+
Exista şi un trade-off. In general se poate folosi maxim 75% din banda oferită de ISP. Pentru a avea coada mică suntem obligaţi să transmitem la doar 70-75% din capacitate. Oricum informaţia utilă nu scade considerabil dacă transmitem la 75% fiindcă în momentul în care transmitem la 100%, multe pachete se pierd, apar coliziuni etc şi trebuie retransmise.
  
Foarte important este de retinut ca avem control numai asupra traficului de tip egress, adica cel pe care il generam noi. Acest trafic poate fi prioritizat, impartit intre clienti, intre protocoale etc. Acest lucru se numeste "traffic shaping". Nu avem control asupra traficului de tip ingress ("traffic policing").
+
Foarte important este de reţinut că avem control numai asupra traficului de tip egress, adică cel pe care îl generăm noi. Acest trafic poate fi prioritizat, împărţit intre clienţi, intre protocoale etc. Acest lucru se numeşte "traffic shaping". Nu avem control asupra traficului de tip ingress ("traffic policing").
  
Pentru inceput imi propun sa explic cativa termeni utilitati si cateva concepte:
+
Pentru început îmi propun explic câţiva termeni utilităţi şi câteva concepte:
  
 
<code>
 
<code>
* Trafic interactiv = trafic care trebuie sa aiba delay minim si care in general este format din doar unul sau cateva pachete. Nu ne intereseaza volumul de trafic (throughput-ul) ci doar delay-ul, timpul necesar de a ajunge de la sursa la destinatie. In aceasta categorie se incadreaza: ssh, VoIP - Voice Over IP, pachetele ACK, ACK/SYN, FIN, RST, FTP-Control (port 21), telnet, etc
+
* Trafic interactiv = trafic care trebuie să aibă delay minim şi care în general este format din doar unul sau câteva pachete. Nu ne interesează volumul de trafic (throughput-ul) ci doar delay-ul, timpul necesar de a ajunge de la sursă la destinaţie. În această categorie se încadrează: ssh, VoIP - Voice Over IP, pachetele ACK, ACK/SYN, FIN, RST, FTP-Control (port 21), telnet, etc
* Bulk traffic = trafic care nu are nevoie de delay scazut, doar volumul conteaza. Ex: email, P2P, web download, ftp-data, bittorent etc
+
* Bulk traffic = trafic care nu are nevoie de delay scăzut, doar volumul contează. Ex: email, P2P, web download, ftp-data, bittorent etc
* Coada (queue) si disciplina cozii (queueing discipline). In Linux (dar si pe alte routere dedicate (ex. cisco)), traficul care trebuie trimis catre o destinatie este salvat intr-un buffer, intr-o coada, asta fiindca in general computerele si reteaua din spatele routerului trimit date mult mai repede decat routerul sau conexiunea acestuia la Internet pot procesa. Pentru a nu pierde pachetele, routerul le pune intr-o coada. Nota: Cand spun router ma refer atat la un router dedicat cisco dar si la un calculator care ruleaza Linux si are functie de router.
+
* Coada (queue) şi disciplina cozii (queueing discipline). În Linux (dar şi pe alte routere dedicate (ex. Cisco)), traficul care trebuie trimis către o destinaţie este salvat într-un buffer, într-o coadă, asta fiindcă în general computerele şi reţeaua din spatele routerului trimit date mult mai repede decât router-ul sau conexiunea acestuia la Internet pot procesa. Pentru a nu pierde pachetele, router-ul le pune într-o coadă. Notă: Când spun router ma refer atât la un router dedicat Cisco dar şi la un calculator care rulează Linux şi are funcţie de router.
Aceasta coada este de fapt un buffer in care pachetele asteapta sa fie livrate. Dimensiunea cozii este de maxim cativa MB. O coada de 3MB este considerata gigantica. Cu fiecare coada se asociaza o disciplina (queueing discipline), adica modul/ordinea in care pachetele sunt puse in coada si livrate. Acesta disciplina este de obicei by default de tip FIFO (First In First Out). Fiecare pachet asteapta ca toate cele dinaintea lui sa fie livrate pentru a-i veni randul. Pentru a maximiza bandwidth-ul acest lucru este foarte bun, dar se maximizeaza si delay-ul. In acest mod traficul interactiv are mult de suferit.
+
Această coadă este de fapt un buffer în care pachetele aşteaptă să fie livrate. Dimensiunea cozii este de maxim câţiva MB. O coadă de 3MB este considerată gigantică. Cu fiecare coada se asociază o disciplină (queueing discipline), adică modul/ordinea în care pachetele sunt puse în coadă şi livrate. Acestă disciplină este de obicei implicit de tip FIFO (First In First Out). Fiecare pachet aşteaptă ca toate cele dinaintea lui fie livrate pentru a-i veni rândul. Pentru a maximiza bandwidth-ul acest lucru este foarte bun, dar se maximizează şi delay-ul. In acest mod traficul interactiv are mult de suferit.
 
* qdisc = queueing discipline (disciplina cozii)
 
* qdisc = queueing discipline (disciplina cozii)
* classfull queueing qdisc = traficul se poate imparti in clase, exista clase parinte, clase copil, clase de tip leaf (clase din care nu mai deriva nimeni). Principiul este asemanator cu cel din programarea orientate obiect.
+
* classfull queueing qdisc = traficul se poate împărţi în clase, există clase părinte, clase copil, clase de tip leaf (clase din care nu mai derivează nimeni). Principiul este asemănător cu cel din programarea orientată pe obiecte.
* prio = prioritatea oferita fiecarei clase de a imprumuta de la clasa parinte. Cu cat prio este mai mica cu atat prioritatea este mai mare.
+
* prio = prioritatea oferită fiecărei clase de a împrumuta de la clasa părinte. Cu cat prio este mai mica cu atât prioritatea este mai mare.
* classless qdisc = nu exista nici o subdiviziune a traficului, totul este la gramada
+
* classless qdisc = nu exista nici o subdiviziune a traficului, totul este la grămadă
* clasa = un tip de trafic (ex. tot traficul care se duce catre yahoo.com de la un anume IP catre portul 25).
+
* clasa = un tip de trafic (ex. tot traficul care se duce către yahoo.com de la un anume IP către portul 25).
 
* rate = traficul minim garantat pentru fiecare clasa
 
* rate = traficul minim garantat pentru fiecare clasa
* ceil = traficul maxim pe care are voie sa-l atinga o clasa
+
* ceil = traficul maxim pe care are voie -l atingă o clasa
* burst = cantitatea de trafic care se trimite la ceil-speed pana se trece sa se serveasca o alta clasa
+
* burst = cantitatea de trafic care se trimite la ceil-speed până se trece se servească o alta clasă
* cburst= cantitatea de trafic care se trimite la wire-speed pana se trece sa se serveasca o alta clasa
+
* cburst= cantitatea de trafic care se trimite la wire-speed până se trece se servească o alta clasă
Daca o clasa nu foloseste toata banda care ii este alocata, o clasa copil poate imprumuta banda de la clasa parinte (daca aceasta are surplus de banda).
+
Dacă o clasă nu foloseşte toata banda care îi este alocată, o clasa copil poate împrumuta banda de la clasa părinte (dacă aceasta are surplus de banda).
* quantum = numarul de bytes imprumutati de parinte clasei copil pana sa imprumute unei alte clase. Nu trebuie sa fie mai mic decat MTU (1500 bytes)
+
* quantum = numărul de bytes împrumutaţi de părinte clasei copil până să împrumute unei alte clase. Nu trebuie fie mai mic decât MTU (1500 bytes)
* egress = traficul expediat prin interfata externa a border router-ului (gateway). Aici intervenim.
+
* egress = traficul expediat prin interfaţa externă a border router-ului (gateway). Aici intervenim.
* ingress = traficul receptionat prin interfata externa a border router-ului (gateway). Nu putem interveni in managementul lui.
+
* ingress = traficul recepţionat prin interfaţa externă a border router-ului (gateway). Nu putem interveni în managementul lui.
* Traffic Shaping = ignorarea sau intirzierea pachetelor ce trebuie expediate, in vederea respectarii unei anumite rate si astfel a minimizarii cozii si respectiv delay-ului.
+
* Traffic Shaping = ignorarea sau întârzierea pachetelor ce trebuie expediate, în vederea respectării unei anumite rate şi astfel a minimizării cozii şi respectiv delay-ului.
* Traffic Policing = ignorarea traficului receptionat (efecte pozitive se obtin greu sau imposibil)
+
* Traffic Policing = ignorarea traficului recepţionat (efecte pozitive se obţin greu sau imposibil)
* filter = imparte traficul in categorii de trafic in functie de un criteriu si il asociaza cu o clasa (ex: traficul de tip ftp in clasa 2:20).
+
* filter = împarte traficul în categorii de trafic în funcţie de un criteriu şi îl asociază cu o clasă (ex: traficul de tip ftp în clasa 2:20).
* HTB = Hierarchical Token Bucket. Un algoritm classfull care foloseste notiunea de token (buffer) si bucket (buffer). Este cea mai folosita si la indemana modalitate de QoS in Linux. Exemplul de fata va folosi HTB.
+
* HTB = Hierarchical Token Bucket. Un algoritm classfull care foloseşte noţiunea de token (buffer) şi bucket (buffer). Este cea mai folosită şi la îndemână modalitate de QoS în Linux. Exemplul de fata va folosi HTB.
* root qdisc = root qdisc este qdisc atasat direct unei interfete.  
+
* root qdisc = root qdisc este qdisc ataşat direct unei interfeţe.  
  
Fiecarei interfete de retea ii este atasat un qdisc. Qdisc si class sunt legate una de cealalta. Qdisc este cel care trimite traficul generat de fiecare clasa. Fiecare clasa are un qdisc.
+
Fiecărei interfeţe de reţea îi este ataşat un qdisc. Qdisc şi class sunt legate una de cealaltă. Qdisc este cel care trimite traficul generat de fiecare clasă. Fiecare clasă are un qdisc.
 
</code>
 
</code>
  
Avand explicate majoritatea conceptelor din HTB, putem da un exemplu practic.
+
Având explicate majoritatea conceptelor din HTB, putem da un exemplu practic.
  
 
'''Exemplul 1'''
 
'''Exemplul 1'''
  
Presupunem ca exista un router Linux, care leaga o retea locala de mai multe calculatoare in Internet. Exista un singur IP public, iar routerul face NAT.
+
Presupunem ca exista un router Linux, care leagă o reţea locala de mai multe calculatoare la Internet. Exista un singur IP public, iar router-ul face NAT.
Presupunem ca ISP ofera o legatura asimetrica de 1024 Kbs download si 256Kbs upload.
+
Presupunem ca ISP oferă o legătură asimetrică de 1024 Kbs download şi 256Kbs upload.
Dupa un studiu amanuntit am identificat traficul generat ca fiind de tip: dns, web, ftp, ssh, email si p2p. Acest tip de trafic vrem sa-l prioritizam dupa nevoie. Vrem ca in momentul in care dc++ sau eMule ruleaza, sa primeasca doar traficul care ramane nefolosit (daca exista), iar daca nici un alt protocol nu foloseste banda vrem ca p2p sa primesca tot. Vrem ca web,ssh si dns si packetele care contin flagurile tcp ack, syn/ack, rst, fin sa aiba delay minim, astfel incat paginile sa se incarce repede chiar daca altcineva face download la un fisier mare sau trimite mailuri.
+
După un studiu amănunţit am identificat traficul generat ca fiind de tip: dns, web, ftp, ssh, email şi p2p. Acest tip de trafic vrem -l prioritizăm după nevoie. Vrem ca în momentul în care dc++ sau eMule rulează, să primească doar traficul care rămâne nefolosit (dacă exista), iar dacă nici un alt protocol nu foloseşte banda vrem ca p2p să primească tot. Vrem ca web,ssh şi dns şi pachetele care conţin flagurile tcp ack, syn/ack, rst, fin să aibă delay minim, astfel încât paginile se încarce repede chiar dacă altcineva face download la un fişier mare sau trimite mailuri.
  
Downlodurile, ftp si mailul vrem sa aiba delay mare dar si throughput mare. P2P (kazaa, dc++, eMule, bittorent) vrem sa aiba prioritate minima.
+
Downlod-urile, ftp şi mailul vrem să aibă delay mare dar şi throughput mare. P2P (kazaa, dc++, eMule, bittorent) vrem să aibă prioritate minimă.
  
In Linux HTB se implementeaza folosind tc (man tc). tc insemna traffic control. Toate comenzile le vom scrie intr-un script pentru o mai usoara folosire a lor. In plus scriptul va porni la bootare, imediat dupa interfata Ethernet care genereaza traficul.
+
In Linux HTB se implementează folosind tc (man tc). tc însemnă traffic control. Toate comenzile le vom scrie într-un script pentru o mai uşoară înţeleger a lor. În plus scriptul va porni la bootare, imediat după interfaţa Ethernet care generează traficul.
Pentru a clasifica traficul vom folosi iptables cu optiunea --mark. Exista si alte modalitati (ex: u32, campul tos din headerul ip, layer 7 classification etc).
+
Pentru a clasifica traficul vom folosi iptables cu opţiunea --mark. Există şi alte modalităţi (ex: u32, câmpul tos din header-ul ip, layer 7 classification etc).
  
 
<pre><nowiki>
 
<pre><nowiki>
Linia 72: Linia 72:
  
 
####################definirea claselor de trafic###########################
 
####################definirea claselor de trafic###########################
##root qdisc este atasat interfetei. Exista unul singur si are ip 1:0 sau 1: Default 12 presupune ca traficul care nu se incadreza in nici o clasa va intra in clasa 12. Acesta este pentru noi traficul p2p.
+
##root qdisc este atasat interfetei. Exista unul singur şi are ip 1:0 sau 1: Default 12 presupune ca traficul care nu se incadreza in nici o clasa va intra in clasa 12. Acesta este pentru noi traficul p2p.
  
 
tc qdisc add dev $IF root handle 1: htb default 12
 
tc qdisc add dev $IF root handle 1: htb default 12
Linia 114: Linia 114:
  
 
#restul traficului intra in clasa default 1:12. Nu este nevoie sa-l clasificam.
 
#restul traficului intra in clasa default 1:12. Nu este nevoie sa-l clasificam.
#Nota: pentru eMule si alti p2p, clasificare traficului este greoaie sau imposila fiindca emule foloseste sute de conexiuni cu clienti diferiti folosind porturi aleatoare. Pentru a-l clasifica corect trebuie sa folosim o extensie a lui iptables care clasifica in functie de layer7. (kernelul si iptables trebuie recompilate pentru a suporta acesta extensite optionala - http://l7-filter.sourceforge.net/L7-HOWTO-Netfilter )
+
#Nota: pentru eMule si alti p2p, clasificare traficului este greoaie sau imposila fiindca emule foloseste sute de conexiuni cu clienti diferiti folosind porturi aleatoare. Pentru a-l clasifica corect trebuie folosim o extensie a lui iptables care clasifica in functie de layer7. (kernelul si iptables trebuie recompilate pentru a suporta acesta extensite optionala - http://l7-filter.sourceforge.net/L7-HOWTO-Netfilter )
  
 
#celor 3 clase le oferim sanse egale folosind sfq (Stochastic Fair Queuing). Este optional
 
#celor 3 clase le oferim sanse egale folosind sfq (Stochastic Fair Queuing). Este optional
Linia 132: Linia 132:
  
  
Acest script poate fi folosit si adaptat pentru orice retea mica-medie care foloseste o singura conexiune la Internet. Bineinteles ca traficul se prioritizeaza in functie de preferintele fiecaruia.
+
Acest script poate fi folosit şi adaptat pentru orice reţea mică-medie care foloseşte o singura conexiune la Internet. Bineînţeles ca traficul se prioritizează în funcţie de preferinţele fiecăruia.
  
Pentru a testa ca functioneza, recomand folosirea lui iftop (http://www.ex-parrot.com/~pdw/iftop/) in timp ce se genereaza trafic. Pentru a fi clar este bine ca pe o legatura super rapida intre doua calculatoare (fast Ethernet 100Mbs) sa se simuleze o legatura extrem de inceata ca sa se observe diferenta. Se seteaza HTB si se limiteaza cateva protocoale la cativa zeci de Kbytes si se verifica in timp real cu iftop ca functioneaza corect.
+
Pentru a testa că funcţioneză, recomand folosirea lui iftop (http://www.ex-parrot.com/~pdw/iftop/) în timp ce se generează trafic. Pentru a fi clar este bine ca pe o legătură super rapidă între două calculatoare (fast Ethernet 100Mbs) se simuleze o legătura extrem de înceată ca se observe diferenţa. Se setează HTB şi se limitează câteva protocoale la câţiva zeci de Kbytes şi se verifică în timp real cu iftop că funcţionează corect.
  
Ex: limitam ftp la 10 kbit, web la 2kbit si trasferul de fisiere cu smb (Server Message Block) la 15 kbit. Apoi se incearca trasferul de fisiere mari cu ftp sau smb sau interogarea serverului web.
+
Ex: limitam ftp la 10 kbit, web la 2kbit şi transferul de fişiere cu smb (Server Message Block) la 15 kbit. Apoi se încearcă transferul de fişiere mari cu ftp sau smb sau interogarea serverului web.
  
 
'''Exemplu 2'''
 
'''Exemplu 2'''
  
Presupunem ca functionam ca un mic ISP de cartier si ca vrem sa impartim banda intre 3 clienti in functie de tipul de abonament. Daca exista banda nefolosita de un client, poate fi oferita unui alt client in ordinea importantei: client2, client1, client3
+
Presupunem ca funcţionăm ca un mic ISP de cartier şi că vrem să împărţim banda intre 3 clienţi în funcţie de tipul de abonament. Dacă exista banda nefolosită de un client, poate fi oferită unui alt client în ordinea importantei: client2, client1, client3
 
<pre><nowiki>
 
<pre><nowiki>
 
Total = 2048 kbit
 
Total = 2048 kbit
Linia 147: Linia 147:
 
Client 3 (ip 10.0.0.3) = 1795 kbit
 
Client 3 (ip 10.0.0.3) = 1795 kbit
  
#Cream o clasa root din care deriva toate celelalte trei clase si atasam o prioritate fiecareia
+
#Cream o clasa root din care deriva toate celelalte trei clase si ataşăm o prioritate fiecăreia
 
RATE1=128
 
RATE1=128
 
RATE2=256
 
RATE2=256
Linia 185: Linia 185:
 
tc qdisc add dev $IF parent 1:40 handle 120: sfq perturb 10
 
tc qdisc add dev $IF parent 1:40 handle 120: sfq perturb 10
 
</nowiki></pre>
 
</nowiki></pre>
Informatiile prezentate mai sus va pot oferi un bun start in invatarea despre QoS si HTB folosind Linux. In nici un caz nu sunt complete sau suficiente. Pot spune ca "just scratched the surface". Pentru mai multe informatii cititi resursele.  
+
Informaţiile prezentate mai sus pot oferi un bun start în învăţarea despre QoS şi HTB folosind Linux. În nici un caz nu sunt complete sau suficiente. Pot spune ca "just scratched the surface". Pentru mai multe informaţii citiţi resursele.  
  
 
'''Resurse'''
 
'''Resurse'''

Versiunea de la data 12 ianuarie 2006 18:56

QoS si HTB in Linux

de Andrei Dumitrescu / 28.09.2005

mici corectii si adaugiri lonely wolf / 11.01.2006


În articolul de faţă îmi propun să detaliez implementarea unei soluţii de QoS folosind Linux şi HTB.

Această soluţie este ideală reţelelor care împart o singura ieşire pe internet (internet prin cablu, DSL, ISDN, etc) folosind NAT (Network Address Translation). Atât în România cât şi în străinătate acest tip de configurare (stub network) este extrem de răspândit pentru reţelele mici şi medii (maxim câteva sute de calculatoare).

Subiectul de fata este considerat avansat, de aceea o bază solidă în ceea ce priveşte Linux Networking şi QoS este necesară pentru înţelegerea în profunzime. Anumite expresii le voi lăsa în limba engleza intenţionat, deoarece traducerea lor ar fi nenaturală şi nejustificată.

Scopul procesului de "bandwidth management" este de a nu permite unui singur protocol sau client să consume toata banda existentă sau mai mult de cât îi este permis. Banda acesta trebuie să fie împărţită între toate protocoalele în funcţie de necesităţi. Noi trebuie să fim cei care controlează coada şi nu ISP-ul sau modemul de dsl/catv unde nu avem nici o influenţa. Aceasta trebuie să fie minima sau cel mai bine să nu existe. Exista şi un trade-off. In general se poate folosi maxim 75% din banda oferită de ISP. Pentru a avea coada mică suntem obligaţi să transmitem la doar 70-75% din capacitate. Oricum informaţia utilă nu scade considerabil dacă transmitem la 75% fiindcă în momentul în care transmitem la 100%, multe pachete se pierd, apar coliziuni etc şi trebuie retransmise.

Foarte important este de reţinut că avem control numai asupra traficului de tip egress, adică cel pe care îl generăm noi. Acest trafic poate fi prioritizat, împărţit intre clienţi, intre protocoale etc. Acest lucru se numeşte "traffic shaping". Nu avem control asupra traficului de tip ingress ("traffic policing").

Pentru început îmi propun să explic câţiva termeni utilităţi şi câteva concepte:

  • Trafic interactiv = trafic care trebuie să aibă delay minim şi care în general este format din doar unul sau câteva pachete. Nu ne interesează volumul de trafic (throughput-ul) ci doar delay-ul, timpul necesar de a ajunge de la sursă la destinaţie. În această categorie se încadrează: ssh, VoIP - Voice Over IP, pachetele ACK, ACK/SYN, FIN, RST, FTP-Control (port 21), telnet, etc
  • Bulk traffic = trafic care nu are nevoie de delay scăzut, doar volumul contează. Ex: email, P2P, web download, ftp-data, bittorent etc
  • Coada (queue) şi disciplina cozii (queueing discipline). În Linux (dar şi pe alte routere dedicate (ex. Cisco)), traficul care trebuie trimis către o destinaţie este salvat într-un buffer, într-o coadă, asta fiindcă în general computerele şi reţeaua din spatele routerului trimit date mult mai repede decât router-ul sau conexiunea acestuia la Internet pot procesa. Pentru a nu pierde pachetele, router-ul le pune într-o coadă. Notă: Când spun router ma refer atât la un router dedicat Cisco dar şi la un calculator care rulează Linux şi are funcţie de router.

Această coadă este de fapt un buffer în care pachetele aşteaptă să fie livrate. Dimensiunea cozii este de maxim câţiva MB. O coadă de 3MB este considerată gigantică. Cu fiecare coada se asociază o disciplină (queueing discipline), adică modul/ordinea în care pachetele sunt puse în coadă şi livrate. Acestă disciplină este de obicei implicit de tip FIFO (First In First Out). Fiecare pachet aşteaptă ca toate cele dinaintea lui să fie livrate pentru a-i veni rândul. Pentru a maximiza bandwidth-ul acest lucru este foarte bun, dar se maximizează şi delay-ul. In acest mod traficul interactiv are mult de suferit.

  • qdisc = queueing discipline (disciplina cozii)
  • classfull queueing qdisc = traficul se poate împărţi în clase, există clase părinte, clase copil, clase de tip leaf (clase din care nu mai derivează nimeni). Principiul este asemănător cu cel din programarea orientată pe obiecte.
  • prio = prioritatea oferită fiecărei clase de a împrumuta de la clasa părinte. Cu cat prio este mai mica cu atât prioritatea este mai mare.
  • classless qdisc = nu exista nici o subdiviziune a traficului, totul este la grămadă
  • clasa = un tip de trafic (ex. tot traficul care se duce către yahoo.com de la un anume IP către portul 25).
  • rate = traficul minim garantat pentru fiecare clasa
  • ceil = traficul maxim pe care are voie să-l atingă o clasa
  • burst = cantitatea de trafic care se trimite la ceil-speed până se trece să se servească o alta clasă
  • cburst= cantitatea de trafic care se trimite la wire-speed până se trece să se servească o alta clasă

Dacă o clasă nu foloseşte toata banda care îi este alocată, o clasa copil poate împrumuta banda de la clasa părinte (dacă aceasta are surplus de banda).

  • quantum = numărul de bytes împrumutaţi de părinte clasei copil până să împrumute unei alte clase. Nu trebuie să fie mai mic decât MTU (1500 bytes)
  • egress = traficul expediat prin interfaţa externă a border router-ului (gateway). Aici intervenim.
  • ingress = traficul recepţionat prin interfaţa externă a border router-ului (gateway). Nu putem interveni în managementul lui.
  • Traffic Shaping = ignorarea sau întârzierea pachetelor ce trebuie expediate, în vederea respectării unei anumite rate şi astfel a minimizării cozii şi respectiv delay-ului.
  • Traffic Policing = ignorarea traficului recepţionat (efecte pozitive se obţin greu sau imposibil)
  • filter = împarte traficul în categorii de trafic în funcţie de un criteriu şi îl asociază cu o clasă (ex: traficul de tip ftp în clasa 2:20).
  • HTB = Hierarchical Token Bucket. Un algoritm classfull care foloseşte noţiunea de token (buffer) şi bucket (buffer). Este cea mai folosită şi la îndemână modalitate de QoS în Linux. Exemplul de fata va folosi HTB.
  • root qdisc = root qdisc este qdisc ataşat direct unei interfeţe.

Fiecărei interfeţe de reţea îi este ataşat un qdisc. Qdisc şi class sunt legate una de cealaltă. Qdisc este cel care trimite traficul generat de fiecare clasă. Fiecare clasă are un qdisc.

Având explicate majoritatea conceptelor din HTB, putem da un exemplu practic.

Exemplul 1

Presupunem ca exista un router Linux, care leagă o reţea locala de mai multe calculatoare la Internet. Exista un singur IP public, iar router-ul face NAT. Presupunem ca ISP oferă o legătură asimetrică de 1024 Kbs download şi 256Kbs upload. După un studiu amănunţit am identificat traficul generat ca fiind de tip: dns, web, ftp, ssh, email şi p2p. Acest tip de trafic vrem să-l prioritizăm după nevoie. Vrem ca în momentul în care dc++ sau eMule rulează, să primească doar traficul care rămâne nefolosit (dacă exista), iar dacă nici un alt protocol nu foloseşte banda vrem ca p2p să primească tot. Vrem ca web,ssh şi dns şi pachetele care conţin flagurile tcp ack, syn/ack, rst, fin să aibă delay minim, astfel încât paginile să se încarce repede chiar dacă altcineva face download la un fişier mare sau trimite mailuri.

Downlod-urile, ftp şi mailul vrem să aibă delay mare dar şi throughput mare. P2P (kazaa, dc++, eMule, bittorent) vrem să aibă prioritate minimă.

In Linux HTB se implementează folosind tc (man tc). tc însemnă traffic control. Toate comenzile le vom scrie într-un script pentru o mai uşoară înţeleger a lor. În plus scriptul va porni la bootare, imediat după interfaţa Ethernet care generează traficul. Pentru a clasifica traficul vom folosi iptables cu opţiunea --mark. Există şi alte modalităţi (ex: u32, câmpul tos din header-ul ip, layer 7 classification etc).

#!/bin/bash
#definim variabilele
######################start htb#####################################
CEIL=192 #(75% din uploadul maxim posibil)
IF=eth0 #interfata pe care pleaca pachetele

#flush everything
tc qdisc del dev $IF root
iptables -F OUTPUT -t mangle

####################definirea claselor de trafic###########################
##root qdisc este atasat interfetei. Exista unul singur şi are ip 1:0 sau 1: Default 12 presupune ca traficul care nu se incadreza in nici o clasa va intra in clasa 12. Acesta este pentru noi traficul p2p.

tc qdisc add dev $IF root handle 1: htb default 12

#class 1:1 attached to root qdisc. Fiecare clasa are un ID care o identifica unic.
#rate=banda minim garantata, ceil=manda maxima pe care o primeste (prin imprumut de la clasa parinte). Din aceasta clasa vor deriva toate celelalte clase, deci primeste tot, iar RATE=CEIL
tc class add dev $IF parent 1: classid 1:1 htb rate ${CEIL}kbit ceil ${CEIL}kbit

#class 1:10 -> 80kbit-192kbit for ACK,SSH. Prio=1, rezulta prioritate maxima de a imprumuta de la parinte.
tc class add dev $IF parent 1:1 classid 1:10 htb rate 80kbit ceil ${CEIL}kbit prio 1

#class 1:11 (email), prioritatea este mai mica deci imprumuta numai dupa ce clasa 1:10 este complet satisfacuta.
tc class add dev $IF parent 1:1 classid 1:11 htb rate 108kbit ceil ${CEIL}kbit prio 2

#default class 1:12 for bulk traffic (aMule, alti p2p). Are garantat doar 8kbit dar poate ajunge la maxim (1024 kbs) daca nu exista alt tip de traffic.
tc class add dev $IF parent 1:1 classid 1:12 htb rate 8kbit ceil ${CEIL}kbit prio 3

##############marcarea si atasarea traficului claselor#########################
#clasificam traficul cu iptables si apoi il atasam clasei 1:10
#mark ack,syn ack,rst,fin, ssh packets and add them to class 1:10 (high priority)
iptables -A OUTPUT -t mangle -o $IF -p tcp --sport 22 -j MARK --set-mark 1
iptables -A OUTPUT -t mangle -o $IF -p tcp --dport 22 -j MARK --set-mark 1

iptables -A OUTPUT -t mangle -o $IF -p tcp --tcp-flags SYN,RST,ACK SYN,FIN -j MARK --set-mark 1
#mark dns packets
iptables -A OUTPUT -t mangle -o $IF -p udp --dport 53 -j MARK --set-mark 1
#mark web packets
iptables -A OUTPUT -t mangle -o $IF -p udp --dport 80 -j MARK --set-mark 1
#atasam traficul clasei 1:10 (prioritate maxima)
tc filter add dev $IF parent 1: protocol ip handle 1 fw classid 1:10

#mark smtp packets
iptables -A OUTPUT -t mangle -o $IF -p udp --dport 25 -j MARK --set-mark 2
#mark pop3 packets
iptables -A OUTPUT -t mangle -o $IF -p udp --dport 110 -j MARK --set-mark 2
#mark imap packets
iptables -A OUTPUT -t mangle -o $IF -p udp --dport 143 -j MARK --set-mark 2

#atasam traficul clasei 1:11 (prioritatea medie)
tc filter add dev $IF parent 1: protocol ip handle 2 fw classid 1:11

#restul traficului intra in clasa default 1:12. Nu este nevoie sa-l clasificam.
#Nota: pentru eMule si alti p2p, clasificare traficului este greoaie sau imposila fiindca emule foloseste sute de conexiuni cu clienti diferiti folosind porturi aleatoare. Pentru a-l clasifica corect trebuie să folosim o extensie a lui iptables care clasifica in functie de layer7. (kernelul si iptables trebuie recompilate pentru a suporta acesta extensite optionala - http://l7-filter.sourceforge.net/L7-HOWTO-Netfilter )

#celor 3 clase le oferim sanse egale folosind sfq (Stochastic Fair Queuing). Este optional
tc qdisc add dev $IF parent 1:10 handle 100: sfq perturb 10
tc qdisc add dev $IF parent 1:11 handle 110: sfq perturb 10
tc qdisc add dev $IF parent 1:12 handle 120: sfq perturb 10

#pentru a avea delay minim, facem drop la 10% din banda oferita de ISP pe ingress
##INGRESS - drop everithing over 948kbit
tc qdisc del dev $IF ingress
tc qdisc add dev $IF handle ffff: ingress
tc filter add dev $IF parent ffff: protocol ip prio 10 u32 match \
ip src 0.0.0.0/0 police rate 948kbit burst 80kbit drop flowid :1



Acest script poate fi folosit şi adaptat pentru orice reţea mică-medie care foloseşte o singura conexiune la Internet. Bineînţeles ca traficul se prioritizează în funcţie de preferinţele fiecăruia.

Pentru a testa că funcţioneză, recomand folosirea lui iftop (http://www.ex-parrot.com/~pdw/iftop/) în timp ce se generează trafic. Pentru a fi clar este bine ca pe o legătură super rapidă între două calculatoare (fast Ethernet 100Mbs) să se simuleze o legătura extrem de înceată ca să se observe diferenţa. Se setează HTB şi se limitează câteva protocoale la câţiva zeci de Kbytes şi se verifică în timp real cu iftop că funcţionează corect.

Ex: limitam ftp la 10 kbit, web la 2kbit şi transferul de fişiere cu smb (Server Message Block) la 15 kbit. Apoi se încearcă transferul de fişiere mari cu ftp sau smb sau interogarea serverului web.

Exemplu 2

Presupunem ca funcţionăm ca un mic ISP de cartier şi că vrem să împărţim banda intre 3 clienţi în funcţie de tipul de abonament. Dacă exista banda nefolosită de un client, poate fi oferită unui alt client în ordinea importantei: client2, client1, client3

Total = 2048 kbit
Client 1 (ip 10.0.0.1) = 128 kbit
Client 2 (ip 10.0.0.2) = 256 kbit
Client 3 (ip 10.0.0.3) = 1795 kbit

#Cream o clasa root din care deriva toate celelalte trei clase si ataşăm o prioritate fiecăreia
RATE1=128
RATE2=256
RATE3=1795
CEIL=2048
IF=ppp0

tc qdisc del dev $IF root
iptables -F OUTPUT -t mangle
##root qdisc
tc qdisc add dev $IF root handle 1: htb

#class 1:10 attached to root qdisc (din ea deriva cele 3 clase)
tc class add dev $IF parent 1: classid 1:10 htb rate ${CEIL}kbit ceil ${CEIL}kbit

#class 1:20 petru client1
tc class add dev $IF parent 1:10 classid 1:20 htb rate ${RATE1}kbit ceil ${CEIL}kbit prio 1

#class 1:30 pentru client2
tc class add dev $IF parent 1:10 classid 1:30 htb rate ${RATE2}kbit ceil ${CEIL}kbit prio 0

#class 1:40 pentru client3
tc class add dev $IF parent 1:10 classid 1:40 htb rate ${RATE3}kbit ceil ${CEIL}kbit prio 2

#clasificam traficul cu iptables si il atasam fiecarei clase
iptables -A OUTPUT -t mangle -o $IF -d 10.0.0.1 -j MARK --set-mark 20
iptables -A OUTPUT -t mangle -o $IF -d 10.0.0.2 -j MARK --set-mark 30
iptables -A OUTPUT -t mangle -o $IF -d 10.0.0.3 -j MARK --set-mark 40

tc filter add dev $IF parent 1: protocol ip handle 20 fw classid 1:20
tc filter add dev $IF parent 1: protocol ip handle 30 fw classid 1:30
tc filter add dev $IF parent 1: protocol ip handle 40 fw classid 1:40

#optional, oferim sanse egale fiecarei grupe
tc qdisc add dev $IF parent 1:20 handle 100: sfq perturb 10
tc qdisc add dev $IF parent 1:30 handle 110: sfq perturb 10
tc qdisc add dev $IF parent 1:40 handle 120: sfq perturb 10

Informaţiile prezentate mai sus vă pot oferi un bun start în învăţarea despre QoS şi HTB folosind Linux. În nici un caz nu sunt complete sau suficiente. Pot spune ca "just scratched the surface". Pentru mai multe informaţii citiţi resursele.

Resurse

man page a lui tc

http://linux-net.osdl.org/index.php/Iproute2

Rusty's Remarkably Unreliable Guides

man page pt iptables

Linux Advanced Routing & Traffic Control

http://www.docum.org/docum.org/docs/

HTB Linux queuing discipline manual - user guide

A Traffic Control Journey: Real World Scenarios

ADSL Bandwidth Management HOWTO

http://forums.gentoo.org/viewtopic-t-347779-highlight-htb.html

http://gentoo-wiki.com/HOWTO_Packet_Shaping

http://forums.gentoo.org/viewtopic-t-225863-highlight-htb.html

l7-filter

ipp2p

Fair NAT for Linux Routers