Semestrální projekt do TPS

QoS: mechanismy front

Praktické návody


Popis

Jako laboratoř byla použita místnost J257. Cílem bylo vytvořit síť, na které by bylo možné provést měření a porovnat jednotlivé disciplíny front. Konfigurace sítě je zakreslena na obrázku. Byly použity 4 počítače, z nichž jeden byl nakonfigurován jako router a ze zbývajících byly vytvořeny dvě sítě, jedna s veřejnými adresami a druhá s privátními adresami - na routeru tedy docházelo k překladu adres. Tato konfigurace byla použita s tím záměrem, aby celá sít byla připojena do internetu a měřeni mohlo být prováděno v reálném provozu. V této kapitole popíšeme jednotlivé nástroje, které jsme pro konfiguraci a měření použili, dále pak budou uvedeny jednotlivé praktické návody, jak jsme při konfiguraci postupovali. Jednotlivé konfigurace jsou, pro jednodušší použití, sepsány do skriptu .





Konfigurace routeru

Dříve než jsme přistoupili k samotné konfiguraci routovani, bylo nutné zkompilovat podporu QoS do jádra operačního systému. Tomuto kroku se zde nebudeme příliš věnovat, jelikož toto není náplní problematiky QoS, ale spadá to spíše do problematiky operačních systémů .

Dále bylo nutné nainstalovat utilitu pro konfiguraci řízení síťového provozu TC. Název programu TC (Traffic Controller) napovídá, že se jedná o program pro řízení provozu. Pomocí tohoto programu lze na uživatelské úrovni vytvářet a asociovat fronty s výstupními zařízeními. V rámci jednotlivých front umožňuje také vytvářet třídy a filtry založené na směrovací tabulce, u32 klasifikátorech, tcindex klasifikátorech a RSVP klasifikátorech. Filtry slouží k zatřídění paketů do jednotlivých tříd. TC používá pro komunikaci se síťovými funkcemi operačního systému rozhraní netlink socket. Pomocí tohoto nástroje lze konfigurovat všechny queueing disciplines, které jsou v operačním systému standardně k dispozici. Přesná podoba parametrů povelu TC se samozřejmě s každou queueing discipline liší, některé principy jsou však shodné.

Než jsme přistoupili k samotnému měření, bylo nutné nainstalovat program Iptraf, který je součástí distribuce Debianu. Teto program slouží k měření toku dat, který prochází přes jednotlivé rozhraní počítače a umožňuje rozlišovat provoz i podle jednotlivých protokolů a specifikovaných portů .

Jako router byl použit počítač s operačním systémem Unix (Debian), proto bylo nutné provést konfiguraci tohoto počítače, ta je uvedena níže. Nejdříve bylo nutné nastavit jádro systému tak, aby přeposílalo příchozí pakety. Protože jsme použili pouze dvě přímo připojené sítě, konfigurace byla provedena pouze příkazem, který je uvedený níže a nemusely být konfigurovány žádné položky routovací tabulky.


# echo "1" > /proc/sys/net/ipv4/ip_forward


Dále je nutné zajistit, aby na routeru docházelo k překladu adres to zajistíme tímto příkazem:


iptables -A POSTROUTING -s 192.168.1.0/24 -t nat -j MASQUERADE


V následujících kapitolách budou uvedeny jednotlivé konfigurace, které jsem používali pro měření. Protože pro konfiguraci byla použita utilita tc, jsou u jednotlivých konfigurací uvedeny i popisy jednotlivých parametrů této utility.

Použití utility TC

Základní úroveň syntaxe programu TC:
 tc [ OPTIONS ] OBJECT { COMMAND | help }
           kde  OBJECT := { qdisc | class | filter }
                OPTIONS := { -s[statistics] | -d[details] | -r[raw] }
Na této úrovni je nejdůležitějším parametrem OBJECT, který může být queueing discipline, třída, či filtr. Práce s programem TC začíná zpravidla vytvořením queueing disciplines. Zde se uplatní tento syntax:
tc qdisc [ add | del | replace | change | get ] dev STRING
       [ handle QHANDLE ] [ root | parent CLASSID ]
       [ estimator INTERVAL TIME_CONSTANT ]
       [ [ QDISC_KIND ] [ help | OPTIONS ] ]

       tc qdisc show [ dev STRING ]
kde:
QDISC_KIND := { [p|b]fifo | tbf | prio | cbq | red | etc. }
Interpretace jednotlivých částí:
  • HANDLE reprezentuje jedinečné označení, které je přiřazeno queueing discipline. Dvě různé queueing disciplines nemohu mít toto označení shodné.
  • ROOT označuje frontu, která je na vrcholu hierarchie tříd a queueing disciplines pro dané zařízení
  • PARENT obsahuje odkaz na označení (HANDLE) nadřazené queueing discipline či třídy
  • ESTIMATOR je používán pro zjištění, zda byly uspokojeny požadavky fronty.

  • Syntaxe pro vytváření tříd:
    tc class [ add | del | change | get ] dev STRING
           [ classid CLASSID ] [ root | parent CLASSID ]
           [ [ QDISC_KIND ] [ help | OPTIONS ] ]
    
           tc class show [ dev STRING ] [ root | parent CLASSID ]
    Kde:
    QDISC_KIND := { prio | cbq | etc. }
    
    Hodnota dosazená za QDISC_KIND musí být queueing discipline, která podporuje třídy jako například CBQ a nikoliv tedy TBF. Interpretace dalších polí:

  • CLASSID reprezentuje označení (HANDLE), které je přiřazeno třídě. Skládá se ze dvou částí oddělených dvojtečkou. První část je označením úrovně, na které se třída v hierarchickém stromu nalézá, druhá část je jedinečné označení této třídy na příslušné úrovni.
  • ROOT označuje třídu na vrcholu hierarchie tříd pro dané zařízení
  • PARENT obsahuje označení (HANDLE) na nadřazenou třídu


  • A ještě jeden výpis syntaxe - tentokrát výpis syntaxe pro definici filtrů:

    tc filter [ add | del | change | get ] dev STRING
           [ prio PRIO ] [ protocol PROTO ]
           [ root | classid CLASSID ] [ handle FILTERID ]
           [ [ FILTER_TYPE ] [ help | OPTIONS ] ]
    
           tc filter show [ dev STRING ] [ root | parent CLASSID ]
    Kde:
    FILTER_TYPE := { rsvp | u32 | fw | route | etc. }
    FILTERID := ... formát se různí dle FILTER_TYPE
    
    
  • PRIO označuje prioritu, která je filtru přiřazena. Pokud dva filtry mají stejnou hodnotu PROTOCOL, poté má přednost ten, který má vyšší prioritu
  • PROTOCOL je hodnota, která se použije pokud identifikujeme pouze pakety patřící jistému protokolu
  • ROOT označuje, že filtr je na vrcholu hierarchie pro dané zařízení
  • CLASSID reprezentuje označení (HANDLE) třídy, na kterou je filtr aplikován
  • HANDLE je jednoznačné označení filtru. Formát tohoto označení je závislý na FILTER_TYPE
  • Classless Queueing Disciplines

    Pfifo_fast

    Parametry a použití utility tc

    priomap
    Zobrazí mapu priorit. Na obrázku níže je uvedena implicitní mapa priorit nastavená v Linuxu. Jednotlivé čísla znamenají do jaké fronty budou řazeny pakety pro jednotlivé kombinace ToS bitu, z leva číslovaných od 0 do 15.

    1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1

    txqueuelen
    Délka fronty je získaná z nastavení rozhraní, které můžeme vidět a nastavit pomocí ifconfig a ip.
    Tento parametr nelze nastavit pomocí tc.

    Token Bucket Filter(TBF)

    Parametry a použití utility tc

    limit or latency
    Limit je počet bytů, které mohou ve frontě čekat na dostupný token. Toto můžeme nastavit i jinou cestou, a to nastavením parametru latence, který nastavuje maximální množství času, kdy může paket zůstat v TBF
    burst/buffer/maxburst
    Těmto parametrů se budeme věnovat níže.
    mpu
    Minimální velikost paketu.
    rate
    představuje požadovanou bitovou rychlost, která má být přidělena dané třídě (to je tedy pravděpodobně nejdůležitější parametr).

    Ukázková konfigurace

    Ukázka jednoduché, ale velmi používané konfigurace:

    # tc qdisc add dev ppp0 root tbf rate 220kbit latency 50ms burst 1540

    Uvedená konfigurace nám říká, že k zařízení ppp0 přiřadíme qdisc tbf, která bude kořenovou (root) qdisc, maximální bitová rychlost bude 220kbit, latence 50ms a velikost kbelíku(bucket) 1540 bytů.

    Stochastic Fairness Queueing (SFQ)

    Parametry a použití utility tc

    perturb
    překonfigurování hashingu (funkce, která mapuje datové toky na vytvořené fronty) proběhne jednou za nastavený počet sekund. Pokud tato hodnota není nastavena, k rekonfiguraci nedojde nikdy. Dobrou hodnotou je 10sec.
    quantum
    Množství bytů, které se odebírají z kanálu do té doby, než bude kanál přidělen jiné frontě. Minimum je MTU - dávají se však větší hodnoty.

    Ukázková konfigurace

    Jestliže máte zařízení, které má stejnou rychlost linky a aktuální dostupnou rychlost, jako telefonní modem, tato konfigurace bude pomáhat podporovat férovost, to znamená, že nemůže dojít k zablokování některé z front:


    # tc qdisc add dev ppp0 root sfq perturb 10
    # tc -s -d qdisc ls
    qdisc sfq 800c: dev ppp0 quantum 1514b limit 128p flows 128/1024 perturb 10sec
    Sent 4812 bytes 62 pkts (dropped 0, overlimits 0)


    Výše uvedená konfigurace přiřadí zařízení ppp0 queueing disciplines sfq, tato bude jako root, hodnota perturb byla nastavena na 10s. Druhý použitý příkaz již neslouží ke konfiguraci, ale jen k výpisu právě provedené konfigurace.

    Classful Queueing Disciplines

    Priority Queueing (PRIO)

    Zdrojový soubor

    Parametry a použití

    bands
    Počet kanálů, které se mají vytvořit. Každý kanál je v podstatě třída. Jestliže změníte toto číslo, musíte také změnit priomap:
    priomap
    Jestliže nepoužijeme tc filtry pro klasifikaci provozu, PRIO qdisc se podívá na TC_PRIO priority a podle nich rozhoduje, jak se bude provoz řadit do front.

    Ukázková konfigurace

    V následující ukázkové konfiguraci budeme vytvářet hierarchickou strukturu qdisc, která je znázorněna na následujícím obrázku ve formě stromu.

         root 1: prio
           /   |   \
         1:1  1:2  1:3
          |    |    |
         10:  20:  30:
         sfq  tbf  sfq
    band  0    1    2


    Celkový datový tok půjde do kořene stromu (root 1: prio), kterému je přiřazena disciplína priority queueing. V tomto bodě se datový tok dělí do tří tříd: 1:1, 1:2 a 1:3, ke každé této větvi je připojena jedna qdisc tak, jak je vidět na obrázku, v tomto příkladě není nastavený žádný filtr, a proto jsou jednotlivé fronty plněny podle implicitní prioritní mapy. To znamená, že data s nejvyšší prioritou se budou řadit do fronty 10: a data s nejméně významnou prioritou do fronty 30: .
    Následující posloupnost konfiguračních příkazů nám zajistí vytvoření stromové struktury, kterou jsme právě popsali. S tím, že u fronty s označením 20: jsme přiřadili qdisc tbf, která má nastavenou maximální bitovou rychlost na 20kbit, limit byl nastaven na 3000 bytů a buffer má velikost 1600 bytů.


    Příkazová řádka:

    # tc qdisc add dev eth1 root handle 1: prio

    # tc qdisc add dev eth1 parent 1:1 handle 10: sfq
    # tc qdisc add dev eth1 parent 1:2 handle 20: tbf rate 20kbit buffer 1600 limit 3000
    # tc qdisc add dev eth1 parent 1:3 handle 30: sfq


    Výhodou utility tc je, že vše co jsme nakonfigurovali si můžeme zobrazit, tak, jak je vidět na obrázku níže. Je vidět, že máme vytvořeny 3 qdisc v listech stromu plus jednu kořenovou (root). A nyní se podíváme, co jsme vytvořili:

    # tc -s qdisc ls dev eth1
    qdisc sfq 30: quantum 1514b
    Sent 0 bytes 0 pkts (dropped 0, overlimits 0)

    qdisc tbf 20: rate 200Kbit burst 1599b lat 66.8ms
    Sent 0 bytes 0 pkts (dropped 0, overlimits 0)

    qdisc sfq 10: quantum 1514b
    Sent 0 bytes 0 pkts (dropped 0, overlimits 0)

    qdisc prio 1: bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
    Sent 0 bytes 0 pkts (dropped 0, overlimits 0)


    Class-Based Queuing (CBQ)

    Zdrojový soubor

    Parametry a použití

    avpkt
    je velikost průměrného paketu a CBQ ji potřebuje znát, aby mohlo stanovit čas, který je potřeba pro odeslání jednoho paketu. Tento čas je stanoven jako podíl AVPKT a BANDWIDTH.
    bandwidth
    představuje maximální přenosovou rychlost, která je k dispozici pro zařízení, na které je fronta navázána. Pokud je výstupním zařízením ethernetová síťová karta 100 Mb/s, pak bude hodnota 100Mbit (jednotka se zadává právě v tomto tvaru).
    cell
    reprezentuje granularitu výstupního zařízení. Odeslání paketu o velikosti 800 či 806 bytů může totiž z technických důvodů trvat naprosto stejný čas. Hodnota CELL nastavuje právě velikost kroku, po kterém se bude doba potřebná k odeslání paketu zvětšovat. Běžná hodnota je 8 a důležité je, že CELL musí být celá mocnina dvou.
    maxburst
    maximální počet bytů, které lze poslat při krátkodobém rychlém nárůstu požadavků.
    minburst
    představuje nejmenší možný počet bytů, které je nutno poslat.
    mpu
    je minimální počet bytů, které budou poslány v jednom paketu. Pokud je požadavek na odeslání paketu o menším počtu bytů, bude paket dorovnán právě na velikost MPU. Tato hodnota existuje z důvodu technických omezení jednotlivých fyzických sítí, u Ethernetu je MPU rovno 64.
    rate
    představuje požadovanou rychlost, která má být přidělena dané třídě (to je tedy pravděpodobně nejdůležitější parametr).

    prio
    reprezentuje prioritu dané třídy.
    weight
    je poněkud tajemný parametr, jehož přesný význam není zdokumentován, nicméně většina zdrojů se shoduje, že by tento parametr měl být ve všech třídách ve stejném poměru k parametru RATE.
    bounded
    označuje, že třída si nemůže "půjčit" nevyužitou kapacitu od svých rodičů. Pokud není specifikováno, třída si takto půjčovat kapacitu může - pokud jsou k dispozici třídy, které kapacitu "nabízejí", viz další parametr.
    isolated
    označuje, že třída nebude "nabízet" svou nevyužitou kapacitu jiným třídám. Pokud není uvedeno jinak, kapacita je nabízena.


    Ukázková konfigurace



    Nyní si stručně popíšeme následující posloupnost konfiguračních příkazů. V první části vytvoříme kořenovou disciplínu označenou 1:0, která bude používat cbq. Bandwidth v této disciplíně bude nastaven na 10Mbit, podle typu síťové karty, velikost průměrného paketu je nastavena na 1000 bytů a hodnota cell je nastavena na 8. K této qdisc je připojena třída označená 1:1, která také používá cbq, v této třídě je nastaveno spoustu parametrů, jejich význam je vysvětlen výše. Co stojí za zmínku je, že třída 1:1 má nastaven argument bounded, což znamená že si třída nemůže půjčit nevyužitou kapacitu od svých rodičů a celková bitová rychlost nemůže přesáhnout 0,6Mbit/s, což plyne z hodnoty rate, která je nastavena na 0,6Mbit/s.


    # tc qdisc add dev eth1 root handle 1:0 cbq bandwidth 10Mbit avpkt 1000 cell 8
    # tc class add dev eth1 parent 1:0 classid 1:1 cbq bandwidth 10Mbit rate 0.6Mbit \
    weight 0.06Mbit prio 8 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded


    Následující příkazy vytváří další dvě třídy se společnou rodičovskou třídou 1:1. První třída označená 1:3 bude použita pro HTTP provoz, tuto vlastnost zajistíme dále použitím filtru, použitou disciplínou bude opět cbq a v tomto případě bude maximální bitová rychlost nastavena na 0,5 Mbit/s. Druhá třída označená 1:4 bude použita pro FTP provoz, to bude opět zajišťovat správné nastavení filtru. Pro FTP bude maximální bitová rychlost nastavena na 0,3 Mbit/s. Můžeme podotknout, že obě třídy nejsou bounded, tudíž si mohou vypůjčit nevyužitou kapacitu od své rodičovské třídy, ale ta je již omezena maximální bitovou rychlostí 0,6 Mbit/s.


    # tc class add dev eth1 parent 1:1 classid 1:3 cbq bandwidth 10Mbit rate 0.5Mbit \
    weight 0.05Mbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000
    # tc class add dev eth1 parent 1:1 classid 1:4 cbq bandwidth 10Mbit rate 0.3Mbit \
    weight 0.03Mbit prio 5 allot 1541 cell 8 maxburst 20 avpkt 1000


    Následující dva příkazy přiřadí výše vytvořeným třídám disciplíny front, ty budou označeny 30: s rodičovskou třídou 1:3 a 40: s rodičovskou třídou 1:4. Oběma bude přiřazena sfq qdisc.


    # tc qdisc add dev eth1 parent 1:3 handle 30: sfq
    # tc qdisc add dev eth1 parent 1:4 handle 40: sfq


    Na závěr celé konfigurace musíme nastavit používání filtrů pro jednotlivé typy provozu. Z konfiguračních příkazů lze vyčíst, že filtry budou přiřazeny přímo v kořenové třídě. Je použit filtr u32. V prvním příkaze je provoz se zdrojovým portem 80 zařazen do třídy 1:3. V druhém příkaze je provoz se zdrojovým portem 21 zařazen do třídy 1:4.


    # tc filter add dev eth1 parent 1:0 protocol ip prio 1 u32 match ip sport 80 0xffff flowid 1:3
    # tc filter add dev eth1 parent 1:0 protocol ip prio 1 u32 match ip sport 21 0xffff flowid 1:4

    Hierarchical Token Bucket (HTB)

    Zdrojový soubor
    Funkčnost je téměř identická s příkladem na CBQ, který je uvedený výše, s tím rozdílem, že zde vytváříme tři třídy přímo připojené ke kořenové třídě. Jak je vidět v následujících příkazech, všechny třídy používají HTB. Třídy označené jako 1:10 a 1:20 mají stejný význam jako v předchozím příkladě, to znamená že do 1:10 bude řazen HTTP provoz a do 1:20 FTP provoz. Tentokrát nám zde přibude třída označena 1:30, která bude sloužit pro zbývající, blíže nespecifikovaný provoz. Je zajímavé, že v této třídě je nastavena maximální bitová rychlost na 10kbit/s, ale hodnotou ceil je řečeno, že může dosáhnout až rychlosti 0,6Mbit/s.


    # tc qdisc add dev eth1 root handle 1: htb default 30

    # tc class add dev eth1 parent 1: classid 1:1 htb rate 0.6Mbit burst 15k

    # tc class add dev eth1 parent 1:1 classid 1:10 htb rate 0.5Mbit burst 15k
    # tc class add dev eth1 parent 1:1 classid 1:20 htb rate 0.3Mbit ceil 0.6Mbit burst 15k
    # tc class add dev eth1 parent 1:1 classid 1:30 htb rate 10kbit ceil 0.6Mbit burst 15k


    V následující sekvenci příkazů přiřadíme každé třídě jednu disciplínu front, u všech tříd je shodně použito sfq.


    # tc qdisc add dev eth1 parent 1:10 handle 10: sfq perturb 10
    # tc qdisc add dev eth1 parent 1:20 handle 20: sfq perturb 10
    # tc qdisc add dev eth1 parent 1:30 handle 30: sfq perturb 10


    Opět je nutné v závěrečné fázi nakonfigurovat filtry. Konfigurace je stejná jako v předchozím příkladě, pouze u FTP se bere cílový port. To z toho důvodu, že při měření jsme vytvářeli obousměrný provoz tak, že docházelo k přenosu dat z FTP serveru na HTTP server a obráceně.

    # U32="tc filter add dev eth1 protocol ip parent 1:0 prio 1 u32"
    # $U32 match ip sport 80 0xffff flowid 1:10
    # $U32 match ip dport 21 0xffff flowid 1:20