This is an old revision of the document!


Laboratorul 11. Lorem ipsum

Introducere

Laborator

01. [10p] iperf (generator de trafic)

Pentru a fi capabili să evaluăm politicile de QoS setate în rețeaua administrată de noi, avem nevoie de un utilitar care să genereze diferite tipuri de pachete, de diferite dimensiuni (UDP, TCP) și să măsoare viteza cu care acestea au fost transmise. Cel mai folosit utilitar pentru acest lucru este iperf. Acesta creează pachete direct în memorie și le trimite pe rețea, eliminând overhead-ul altor dispozitive I/O (exemplu: dacă testam cu un transfer FTP se adăuga overhead-ul citirii/scrierii pe disc a fișierului transferat).

Utilitarul iperf poate rula în 2 moduri:

  • client: cel care generează traficul
  • server: cel care primește traficul

În cadrul acestui laborator dorim să limităm traficul de download, astfel clientul iperf va rula pe gateway, iar server-ul iperf, cel care primește traficul, va rula pe mașinile virtuale client1 și client2.

Instalați iperf pe toate cele 3 stații:

root@client1:~# apt-get update
root@client1:~# apt-get install iperf
 
root@client2:~# apt-get update
root@client2:~# apt-get install iperf
 
root@gateway:~# apt-get update
root@gateway:~# apt-get install iperf

Pe stația client1, porniți iperf în modul server:

iperf -s

Pe stația gateway, porniti iperf în modul client:

iperf -c 192.168.1.1

După 10 secunde, atât server-ul (client1) cât și clientul (gateway) vor afișa statistici legate de traficul schimbat:

root@gateway:~# iperf -c 192.168.1.1
------------------------------------------------------------
Client connecting to 192.168.1.1, TCP port 5001
TCP window size: 22.9 KByte (default)
------------------------------------------------------------
[  3] local 192.168.1.3 port 57685 connected with 192.168.1.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   190 MBytes   159 Mbits/sec
 
root@client1:~# iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[  4] local 192.168.1.1 port 5001 connected with 192.168.1.3 port 57685
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0-10.0 sec   190 MBytes   159 Mbits/sec

Generați trafic de tip UDP între stația gateway și stația client2 în care lungimea pachetelor să fie de 256 de octeți (Hint: --len).

2014/01/26 13:07

02. [10p] Generarea traficului pe baza unor caracteristici și constrângeri din lumea reală

În cadrul laboratorului, vom explora principalele strategii de QoS din Linux. Pentru a observa comportamentul strategiilor implementate, vom folosi un model de trafic, compus din:

  • trafic de voce (UDP, port 8000)
  • trafic video (UDP, port 6000)
  • trafic FTP (TCP, port 21)
  • trafic HTTP (TCP, port 80)

Traficul nu va fi real ci îl vom simula cu ajutorul lui iperf prezentat anterior.

Fiecare tip de trafic din cele considerate mai sus are anumite caracteristici și constrângeri. Pentru o funcționare optimă, trebuie să ținem seama de acestea:

  • trafic de voce
    • sensibil la: delay, jitter, packet loss
    • consum de banda: mic, constant
  • trafic video
    • sensibil la: delay, jitter, packet loss
    • consum de banda: mare, constant
  • trafic FTP si HTTP
    • sensibil la: nimic
    • consum de banda: mare, variabil, greedy (tinde sa “umple” intreaga latime de banda a legaturii)

Dupa cum ați observat la exercițiul anterior, o conexiune iperf client-server generează un singur tip de trafic (implicit, trafic TCP pe portul 5001). Noi dorim să generăm mai multe tipuri de trafic, concomitent, pentru a vedea cum se afectează între ele. Deci va trebui să instanțiem mai multe astfel de perechi, în background.

Vom crea un script cu numele iperf-client1.sh care va porni 4 servere iperf pe stația client1 (urmăriți comentariile):

iperf-client1.sh
#!/bin/bash
 
# Asculta trafic UDP, pe port-ul 8000 - fluxul de voce
iperf --server --udp --port 8000 &> out1.txt  &
 
# Asculta trafic UDP, pe port-ul 6000 - fluxul video
iperf --server --udp --port 6000 &> out2.txt &
 
# Asculta trafic TCP, pe port-ul 21 - fluxul FTP
# Daca nu se specifica --udp, implicit este TCP
iperf --server --port 21 &> out3.txt &
 
# Asculta trafic TCP, pe port-ul 80 - fluxul HTTP
# Daca nu se specifica --udp, implicit este TCP.
iperf --server --port 80 &> out4.txt &
 
echo "iperf servers started. Now run the script on the gateway."

Vom crea pe stația gateway un script cu numele iperf-gateway.sh care se va conecta la cele 4 servere pornite pe stația client1, generând cele 4 tipuri de trafic prezentate anterior. Simulăm tipurile de trafic prin generare de pachete ce au caracteristici asemănătoare cu cele din cazurile reale. Urmăriți comentariile din fișier:

iperf-gateway.sh
#!/bin/bash
 
IP_VM="192.168.1.1"
TIME=60 # Durata unui test
 
# Initiaza un flux UDP catre server, pe portul 8000
# Fiecare datagrama are dimensiunea de 128 octeti (tipic pentru pachetele de voce)
# Se trimite la o rata de 640Kbps (dorim sa simulam 10 conversatii VoIP, a cate 64Kbps)
iperf -x SC --client $IP_VM --port 8000 --udp --len 128 --bandwidth 640K --time $TIME > out3.txt 2> /dev/null &
 
# Initiaza un flux UDP catre server, pe portul 6000
# Fiecare datagrama are dimensiunea maxima (pentru ca nu o specificam explicit)
# Se trimite la o rata de 30Mbps
iperf -x SC --client $IP_VM --port 6000 --udp --bandwidth 30M --time $TIME > out4.txt 2> /dev/null &
 
# Initiaza un flux TCP catre server, pe portul 80 (HTTP)
# Limitam dimensiunea unui segment la 512 octeti
iperf -x SC --client $IP_VM --port 80 --mss 512 --time $TIME > out1.txt 2> /dev/null &
 
# Initiaza un flux TCP catre server, pe portul 21 (FTP)
# Dimensiunea unui segment va fi de 1400 octeti (dorim ca fluxul FTP sa fie mai agresiv)
# Dimensiunea ferestrei TCP va fi de 256K (dorim ca fluxul FTP sa fie mai agresiv)
iperf -x SC --client $IP_VM --port 21 --window 256K --mss 1400 --time $TIME > out2.txt 2> /dev/null &
 
wait
for i in out*; do echo; cat $i; done
rm out*.txt

Rulați script-urile create anterior (iperf-client1.sh pe stația client1 și iperf-gateway.sh pe stația gateway). Așteptați 60 de secunde și inspectați output-ul de pe stația gateway. Ce observați?

Observăm că fluxurile UDP au suferit packet loss, ele neavând nici un mecanism pentru retransmitere sau reglare a vitezei în funcție e starea legăturii. Pentru fluxul video, o pierdere de pachete de câteva procente este inacceptabilă. În continuare vom studia mecanismele implicite de QoS din Linux și cum putem preveni aceste pierderi de pachete.

2014/01/26 13:07

03. [10p] Clasificarea folosind ToS

În Linux, strategiile de QoS se inspectează și configurează folosind comanda tc. Termenul folosit pentru strategiile de QoS este qdisc (de la queueing discipline).

Afisați detalii despre qdisc-ul implicit, asociat interfeței eth0 de pe stația gateway:

# tc qdisc show dev eth0
qdisc pfifo_fast 0: root refcnt 2 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1

Observați că qdisc-ul implicit este pfifo_fast (strategia implicită de QoS):

  • Numele vine de la priority FIFO.
  • Este un qdisc classless (nu putem clasifica traficul și limita traficul, îl putem doar prioritiza)
  • Nu este o simpla coada FIFO, ci conține 3 (sub)cozi, numite 0, 1 si 2 (fiecare din ele fiind FIFO). Cât timp coada coada 0 conține pachete, cozile 1 si 2 NU vor fi servite.

Ce reprezintă priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1? În Linux, kernel-ul asociază fiecărui pachet o prioritate, în functie de campul TOS (Type of Service) din header-ul IP. Prioritatea ne selectează una din cele 3 (sub)cozi din pfifo_fast: coada 0, 1 sau 2. Asocierile se fac după următorul tabel:

TOS     Means                    Linux Priority    Band
-------------------------------------------------------
0x0     Normal-Service           0 Best Effort     1
0x2     Minimize-Monetary Cost   1 Filler          2
0x4     Maximize-Reliability     0 Best Effort     1
0x6     mmc+mr                   0 Best Effort     1
0x8     Maximize-Throughput      2 Bulk            2
0xa     mmc+mt                   2 Bulk            2
0xc     mr+mt                    2 Bulk            2
0xe     mmc+mr+mt                2 Bulk            2
0x10    Minimize-Delay           6 Interactive     0
0x12    mmc+md                   6 Interactive     0
0x14    mr+md                    6 Interactive     0
0x16    mmc+mr+md                6 Interactive     0
0x18    mt+md                    4 Int. Bulk       1
0x1a    mmc+mt+md                4 Int. Bulk       1
0x1c    mr+mt+md                 4 Int. Bulk       1
0x1e    mmc+mr+mt+md             4 Int. Bulk       1

Observăm că pachetele normale (cu TOS 0x00) sunt introduse în (sub)coada 1. La punctul anterior, fluxul UDP avea o pierdere semnificativă de pachete. O primă soluție ar fi marcarea pachetelor de voce și video cu un ToS favorabil (de exemplu, 0x10), pentru a avea prioritate mai mare față de pachetele. Marcarea se realizează folosind lanțul mangle al comenzii iptables:

root@gateway:~#  iptables -t mangle -A OUTPUT -p udp --dport 6000:8000 -j TOS --set-tos Minimize-Delay

Comanda anterioară marchează toate pachetele UDP cu porturile în intervalul 6000 și 8000 cu tag-ul Minimize-Delay. Se observă că se poate folosi numele tag-ului în loc de valoare (0x10).

Rulați din nou scriptul iperf-gateway.sh pe stația gateway și observați că procentele pierdute s-au diminuat foarte puțin. Nu e suficientă doar o prioritizare a pachetelor.

2014/01/26 13:07

04. [5p] Traffic shaping în Linux

Am observat faptul că policing-ul pe baza ToS-ului nu este suficient pentru a asigura echitatea între servicii. Soluția ce se apoate aplica este dată de limitarea serviciilor FTP și HTTP.

tbf este cea mai simplă metodă de a face traffic shaping în Linux. Este, de asemenea, un qdisc classless (ca și pfifo_fast).

Dorim să limităm viteza pentru fluxurile FTP și HTTP (însumate) la aproximativ 9Mbps. Deoarece fluxul de voce are 640kbps, iar cel video are 30Mbps, rezulta ca o valoare acceptabila pentru viteza totală ar fi 40Mbps. Pe stația gateway ne dorim următoarele setări:

  • Viteza maximă de transfer să fie 50Mbps (40Mbps pentru datele propriu zise și o marjă de 20% pentru încapsulare - headere IP, TCP/UDP, Ethernet)
  • În caz de congestie, acceptăm un surplus de 128Kbps, pentru 50ms.

Vom seta qdisc-ul tbf, pe interfața eth0 astfel:

root@gateway:~# tc qdisc add dev eth0 root tbf rate 50mbit burst 128kbit latency 50ms

Rulați din nou script-ul iperf-gateway.sh de pe stația gateway. Asteptați 60 de secunde și inspectați output-ul afișat. Ce observați? Pierderile de pachete pentru conexiunea UDP au dispărut, qdisc-ul tbf asigurând echitate între conexiuni.

Cu toate că suma vitezelor fluxurilor este de aproximativ 50Mbps, ea nu este distribuită așa cum ne-am fi asteptat. Fluxurile FTP și HTTP ocupa mai mult decât 9Mbps. Motivul este că limitarea a fost facută printr-o metoda classless, ce limitează întreg traficul de pe o interfață, fără a avea posibilitatea de a selecta și clasifica diferite tipuri de trafic. Soluția este dată de aplicarea unui qdisc classful, ce trateaza in mod separat diferitele clase de trafic.

2014/01/26 13:07

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:

               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)

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:

root@gateway:~# tc qdisc del dev eth0 root

Adăugam qdisc-ul htb, cu majorul 1: (sau 1:0):

root@gateway:~# tc qdisc add dev eth0 root handle 1: htb

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ă
root@gateway:~# tc class add dev eth0 parent 1: classid 1:1 htb rate 1mbit burst 128k

Procedăm analog și pentru restul claselor:

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

Verificăm qdisc-ul asociat interfeței eth0 și ierarhia de clase adăugată:

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

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:
    root@gateway:~# tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dport 8000 0xffff flowid 1:1

Procedăm analog și cu celelalte filtre:

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

Verificăm filtrele create:

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

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.
2014/01/26 13:07

06. [15p] Politici de limitare per client

Ștergeți qdisc-ul root adăugat anterior.

Realizați configurațiile necesare astfel încât să limitați stația client1 la 5 mbps, iar stația client2 la 3mbps. În plus dorim ca cei 3mbps ai stației client2 să fie împărțiți după cum urmează:

  • 1mbps pentru traficul ce ajunge pe portul 1111 (Hint: folosiți 2 reguli de match ale clasificatorului u32)
  • 2mbps pentru traficul de pe restul porturilor

Testați folosind iperf.

2014/01/26 13:07
saisp/labs/11.1390734478.txt.gz · Last modified: 2014/01/26 16:22 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0