This shows you the differences between two versions of the page.
saisp:labs:11:contents:05 [2014/01/26 13:07] 127.0.0.1 external edit |
saisp:labs:11:contents:05 [2015/05/25 16:04] (current) alexandru.carp [05. [10p] Traffic shaping classful] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ==== 05. Lorem ipsum ==== | + | ==== 05. [10p] Traffic shaping classful ==== |
- | ... | + | ''htb'' este un qdisc **classful** (tratează traficul în mod diferențiat, în funcție de clasa din care face parte). Este varianta **classful** a ''tbf'' (împarte traficul pe clase, apoi aplica ''tbf'' pe fiecare în parte). |
+ | Clasele sunt organizate într-o structura de arbore. Cu cât o clasa este mai jos în ierarhie, cu atât este mai specifică. Fiecare clasă are asociată o strategie de QoS (qdisc). În mod implicit, qdisc-ul este pfifo_fast, iar acesta poate fi modificat. | ||
+ | Exemplu de ierarhie: <code> | ||
+ | 1: root qdisc (always present) | ||
+ | | | ||
+ | 1:1 child class (with default qdisc) | ||
+ | / \ | ||
+ | / \ | ||
+ | 1:3 1:4 leaf classes (with user-defined qdiscs) | ||
+ | | | | ||
+ | 30: 40: qdiscs | ||
+ | (sfq) (sfq) | ||
+ | </code> | ||
+ | |||
+ | Observații: | ||
+ | * Fiecare clasa este identificată printr-un **major** și un **minor**, sub forma "major:minor". Toate clasele dintr-o ierarhie trebuie să aiba același major. | ||
+ | * Fiecare qdisc este identificat doar printr-un **major**. Minorul este întotdeauna zero. O scriere de forma ''major:'' este echivalentă cu ''major:0''. | ||
+ | * Deși nu este reprezentat, clasa ''1:1'' are un qdisc asociat (cel implicit). | ||
+ | * Claselor ''1:3'' și ''1:4'' le-a fost schimbat qdisc-ul implicit (în loc de ''pfifo_fast'', avem ''sfq'', un qdisc ce funcționează după modelul Round Robin) | ||
+ | |||
+ | Tratarea pachetelor: | ||
+ | * Dacă un pachet se potrivește cu clasa ''1:1'', dar NU se potrivește cu clasa ''1:3'' sau ''1:4'', va fi tratat conform qdisc-ului implicit al clasei ''1:1'', adica ''pfifo_fast''. | ||
+ | * Dacă un pachet se potrivește cu clasa ''1:1'' ȘI cu clasa ''1:3'', va fi tratat conform qdisc-ului clasei ''1:3'', adica ''sfq''. | ||
+ | * Analog pentru clasa ''1:4''. | ||
+ | |||
+ | Clasificarea pachetelor: | ||
+ | * Pentru a decide din ce clasă face parte un pachet, trebuie definite **filtre**. | ||
+ | * Un filtru specifică condițiile de ''match'' și clasa în care trebuie inclus pachetul. | ||
+ | * De obicei, filtrele se atașează rădăcinii. | ||
+ | |||
+ | Ne propunem sa alocam cate o clasa fiecarui tip de trafic din cele definite în scenariu. Fiecare clasă de trafic va fi limitată la o lățime de bandă bine definită, astfel: | ||
+ | * voce: 1Mbps | ||
+ | * video: 40Mbps | ||
+ | * FTP: 5Mbps | ||
+ | * HTTP: 3Mbps | ||
+ | |||
+ | Toate configurațiile vor fi făcute pe interfața ''eth0'' a stației ''gateway'' (politifice de traffic shaping pot fi aplicate doar pentru traficul care iese pe o interfață). Mai întâi, trebuie să ștergem orice alt qdisc de pe interfața ''eth0'':<code bash> | ||
+ | root@gateway:~# tc qdisc del dev eth0 root | ||
+ | </code> | ||
+ | |||
+ | Adăugam qdisc-ul ''htb'', cu majorul ''1:'' (sau ''1:0''):<code bash> | ||
+ | root@gateway:~# tc qdisc add dev eth0 root handle 1: htb | ||
+ | </code> | ||
+ | |||
+ | Definim prima clasa, cea pentru traficul de voce. Trebuie să specificăm: | ||
+ | * părintele, care este ''1:'' | ||
+ | * id-ul, fie acesta ''1:1'' (majorul trebuie sa fie același cu al părintelui, minorul poate fi orice) | ||
+ | * parametrii htb: viteza și depășirea (burst-ul) acceptată | ||
+ | <code> | ||
+ | root@gateway:~# tc class add dev eth0 parent 1: classid 1:1 htb rate 1mbit burst 128k | ||
+ | </code> | ||
+ | |||
+ | Procedăm analog și pentru restul claselor:<code> | ||
+ | tc class add dev eth0 parent 1: classid 1:2 htb rate 40mbit burst 128k | ||
+ | tc class add dev eth0 parent 1: classid 1:3 htb rate 5mbit burst 128k | ||
+ | tc class add dev eth0 parent 1: classid 1:4 htb rate 3mbit burst 128k | ||
+ | </code> | ||
+ | |||
+ | Verificăm qdisc-ul asociat interfeței ''eth0'' și ierarhia de clase adăugată:<code bash> | ||
+ | root@gateway:~# tc qdisc show dev eth0 | ||
+ | qdisc htb 1: root refcnt 2 r2q 10 default 0 direct_packets_stat 82 direct_qlen 1000 | ||
+ | |||
+ | root@gateway:~# tc class show dev eth0 | ||
+ | class htb 1:1 root prio 0 rate 1000Kbit ceil 1000Kbit burst 128Kb cburst 1600b | ||
+ | class htb 1:2 root prio 0 rate 40000Kbit ceil 40000Kbit burst 128Kb cburst 1600b | ||
+ | class htb 1:3 root prio 0 rate 5000Kbit ceil 5000Kbit burst 128Kb cburst 1600b | ||
+ | class htb 1:4 root prio 0 rate 3000Kbit ceil 3000Kbit burst 128Kb cburst 1599b | ||
+ | </code> | ||
+ | |||
+ | Cu toate că am definit ierarhia de clase, nu am definit cum selectăm traficul pentru aceste clase. Vom folosi noțiunea de filtre oferită de utilitarul ''tc''. Definim primul filtru, ce selectează trafic cu portul destinație ''8000''. Trebuie să specificam: | ||
+ | * protocolul de nivel 3: IP | ||
+ | * parintele: ''1:'' - vom atasa toate filtrele în nodul rădăcina | ||
+ | * prioritatea: ''1'' - toate filtrele vor avea aceeași prioritate | ||
+ | * tipul de filtru: ''u32'', ce poate face match pe header-ul IP | ||
+ | * condiția de match: portul destinație (8000), și masca (0xffff - dorim să facem match pe toți cei 16 biți asociați câmpului destinație) | ||
+ | * clasa în care va fi încadrat traficul (flowid): ''1:1'':<code bash> | ||
+ | root@gateway:~# tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dport 8000 0xffff flowid 1:1 | ||
+ | </code> | ||
+ | |||
+ | Procedăm analog și cu celelalte filtre:<code bash> | ||
+ | root@gateway:~# tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dport 6000 0xffff flowid 1:2 | ||
+ | root@gateway:~# tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dport 21 0xffff flowid 1:3 | ||
+ | root@gateway:~# tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dport 80 0xffff flowid 1:4 | ||
+ | </code> | ||
+ | |||
+ | Verificăm filtrele create:<code bash> | ||
+ | root@gateway:~# tc filter show dev eth0 | ||
+ | filter parent 1: protocol ip pref 1 u32 | ||
+ | filter parent 1: protocol ip pref 1 u32 fh 800: ht divisor 1 | ||
+ | filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 | ||
+ | match 00001f40/0000ffff at 20 | ||
+ | filter parent 1: protocol ip pref 1 u32 fh 800::801 order 2049 key ht 800 bkt 0 flowid 1:2 | ||
+ | match 00001770/0000ffff at 20 | ||
+ | filter parent 1: protocol ip pref 1 u32 fh 800::802 order 2050 key ht 800 bkt 0 flowid 1:3 | ||
+ | match 00000015/0000ffff at 20 | ||
+ | filter parent 1: protocol ip pref 1 u32 fh 800::803 order 2051 key ht 800 bkt 0 flowid 1:4 | ||
+ | match 00000050/0000ffff at 20 | ||
+ | </code> | ||
+ | |||
+ | Pe stația gateway, rulați din nou script-ul ''iperf-gateway.sh''. Asteptați 60 de secunde și inspectați output-ul afișat. Ce observați? | ||
+ | * Fiecare flux de trafic nu a depasit banda alocata. | ||
+ | * Packet-loss-ul este în continuare apropiat de 0% (ca la ''tbf'') pentru flow-urile UDP. |