Quality of Service

Honza Bartoš <207656@mail.muni.cz>
  1. QoS, úvod
  2. Teorie QoS
    1. Differentiated services
    2. policing, shaping
    3. qdisc
    4. pfifo_fast
    5. Token Bucket Filtres
    6. Stochastic Fairness Queueing
    7. Random early detection
    8. PRIO
    9. CBQ
    10. HTB
  3. Konfigurace v Linuxu
  4. IMQ
  5. Rozložení zátěže
  6. Sledování provozu

QoS, úvod

IP rodina protokolů je navržena jako tzv. best effort služba, tedy neexistuje vzájemné zvýhodnění jednotlivých služeb/uživatelů, sítě nezaručují kvalitu služby (např. dostupnost dané šířky pásma, které mohou vyžadovat multimediální aplikace, nebo i jen prosté zvýhodnění víceplatících uživatelů…). Tyto možnosti je tedy nutné implementovat mimo (nad) tyto protokoly. Prostředky které toto umožňují budeme nazývat QoS -- Quality of Service. V Linuxu lze QoS provádět se síťovým systémem, který je jeho součástí od verze 2.2, konfiguraci provádíme pomocí balíku iproute2. Původním autorem je Alexey Kuznetsov ([přepis podle českých pravidel?]). QoS lze samozřejmě provádět i v jiných systémech (např. FreeBSD nabízí systém Dummynet).

Teorie QoS

Z pohledu QoS se zajímáme o následující parametry přenosu:

Každá různá aplikace může mít jiné požadavky na každé měřítko. Např. pro streamování zvukové nahrávky můžeme snést velké zpoždění, ale chceme co nejmenší možou ztrátovost a rozptyl.

Differentiated services

Zajištění kvality služby je možné několika způsoby (např. overprovisioning), nicméně pro tento referát je podstatný protokol rozlišených služeb (differentiated services). Tento model je založen na rozdělení síťového provozu (jednotlivých paketů) do několika různých tříd se kterými pak aktivní prvky zacházejí různě. Třídy je možno zapsat do IP hlavičky (případně i do hlaviček nižší vrstvy).

policing, shaping

Nástroje určené k omezování provozou přicházejícího a odcházejícího ze sítě. Příchozí provoz už z principu nejsme moc schopni regulovat. Policing se nazývá zahazování případně pozdržování paketů nad určitou stanovenou míru. Předpokládáme pak, že odesílatel jich začne posílat méně (TCP).

K řízení odchozího provozu použijeme traffic shaping. Celé řízení provádíme pomocí fronty paketů určených k odeslání, způsob práce s frontou se nazývá qdisc (queue discipline).

qdisc

qdiscy přiřazujeme jednotlivým rozhraním a dělíme je na třídní a beztřídní (classful, classless). Beztřídní jsou jednodušší a neobsahují další qdiscy.

pfifo_fast

Výchozí qdisc, pakety jsou prostě řazeny do fronty a posléze odeslány. Fronty jsou tři, 0-2, přičemž se postupuje tak, že dokud není odesláno vše z fronty 0, zbytek čeká, stejně tak pro frontu 1, kdy dokud ta není prázdná, neodesílá se nic z fronty 2. Pakety se do fronty zařadí podle svého TOS (IP hlavička) příznaku. Rozdělení je následující:

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

Token Bucket Filter

Tento qdisc slouží k jednoduchému omezení toku dat. Funguje na principu žetonového koše (ano, mohli jsme to nechat nepřeložené, ale…), ten obsahuje určité množství žetonů a každý paket podle své velikosti k odeslání potřebuje jejich určité množství. Tokeny postupně přibývají. Tento qdisc umožní určité špičky nad stanovenou šířku pásma.

Příklad konfigurace: tc qdisc add dev ppp0 root tbf rate 220kbit latency 50ms burst 1540

Stochastic Fairness Queueing

Tento qdisc rozděluje podle (stále měněné) hašovací funkce pakety do několika front a jim náhodně dává slovo. Zajišťuje tak poměrně spravedlivé omezení šířky pásma. (pro jednotlivé přenosy)

Random Early Detection

Určeno spíše pro páteřní spoje. Pakety jsou zde zahazovány ještě před tím, než dojde k zahlcení sítě. Nejsou zde žádné další možnosti shapingu. Rozšíření WRED dovoluje rozlišování jednotlivých služeb.

Další qdiscy jsou třídní, umožňují tedy zanořování dalších qdisců. Proto zde qdiscy tvoří stromovou strukturu, kde máme jeden kořenový (výchozím je právě pfifo_fast) a provoz se dále větví pod něj.

PRIO

Tento qdisc neprovádí samotné shapování, pouze rozděluje provoz do nižších qdisců (chová se tedy trochu jako pfifo_fast, nicméně třídně). Výchozí chování je takové, že jsou vytvořeny tři podtřídy s jednoduchou frontou.

Počet podtříd je možno nastavit, těmto třídám je i možno nastavit další jiné qdiscy. S tímto qdiscem nelze přímo provádět shaping.

CBQ

Velmi používaný qdisc s velkými možnostmi nastavení. V zásadě tento qdisc pracuje tak, že se snaží linku udržet nečinnou po určitý čas (a tak omezit provoz) vypočtený na základě velikosti paketů a propustnosti linky.

Právě průměrnou velikost paketu a fyzickou přenosovou rychlost linky je nutno nastavit. CBQ umožňuje podtřídy, mezi kterými se rozhoduje pomocí váženého round-robin.

HTB

Protože je konfigurace CBQ poměrně složitá (může být těžké dosáhnout s CBQ to co chcete), vznikl qdisc HTB -- Hierarchical Token Bucket.

Ten funguje zhruba jako třídní TBF. Dovoluje shapování a použití priorit.

Konfigurace v Linuxu

Předpokladem je mít nástroje iproute2 (ip, tc), iptables a k nim odpovídající jadernou část.

Přiřazení a qdisců budeme provádět příkazem tc (traffic control).

Vzorové nastavení:

tc qdisc del dev eth0 root
tc qdisc add dev eth0 root handle 1: htb default 30

tc class add dev eth0 parent 1: classid 1:1 htb rate 6mbit burst 15k

tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5mbit burst 15k
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 3mbit ceil 6mbit burst 15k
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 1kbit ceil 6mbit burst 15k

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

Toto nastavení (ukradené z LARTC) napřed nahradí výchozí qdisc na rozhraní eth0 qdiscem HTB. Všechny qdiscy a třídy mají svá id, která lze uvést explicitně nebo jsou přiřazeny automaticky. Skládají se z major a minor čísla, oddělené :. parametr default udává třídu do které půjde neklasifikovaný provoz.

Vytvoříme třídu 1:1, která bude mít přiděleno 6mbit. Parametr burst udává počet bajtů, které lze přenést nad rate.

Pod tuto třídu umístíme podřízené, které tak jsou omezeny vlastnostmi rodiče.U zbylých dvou tříd navíc udáváme parametr ceil, který udává maximální možnou šířku pásma, kterou si třída půjčí, pokud má její rodič nějakou volnou. To je zde zvlášť zajímavé u třídy 1:30, která tak má jen naprosto minimální šířku pásma, ale je-li nějaká volná, ,roztáhne` se do ní.

Na naše třídy pak pověsíme sfq qdiscy (ten už je beztřídní). Parametr perturb zde udává interval změny hašovací funkce (s).

Zbývá nám stále problém jak rozdělíme provoz do jednotlivých tříd. Můžeme zvolit dvě řešní, tc filter a značkování (mangling) pomocí iptables.

Filtry mohou vypadat například takto: tc filter add dev eth0 protocol ip parent 1:0 u32 match ip dport 22 0xffff flowid 1:10, tento příklad říká, že provoz směrovaný na port 22 se přiřadí do třídy 1:10.

Třídění pomocí iptables může vypadat takto:

iptables -t mangle -A POSTROUTING -d 192.168.0.1 -j MARK --set-mark 1
tc filter add dev eth0 parent 1:0 protocol ip handle 1 fw flowid 1:10
zde paket vyhovující danému pravidlu (cíl) označíme značkou jedna. Filtr vytvořený druhým příkazem ho pak zařadí do třídy 1:10.

IMQ

IMQ je patch pro jádro se kterým můžete jednak dělat trochu lepší policing (použití běžných egress qdisců na příchozí provoz) a dále vám dovolí shapovat přes více rozhraní (qdiscy přirazujete jednotlivým zařízením) tak, že nabízí virtuální rozhraní imq na které lze qdiscy připojovat.

Rozdělení zátěže na více rozhraní

Máme-li dvě různé linky mezi dvěma routery, můžeme chtít nějakým způsobem na nich rozdělovat zátěž.

Jednou možností je použít TEQL (trivial link equalizer). Příklad:

                 +-------+   eth1   +-------+
                 |       |==========|       |
 'network 1' ----|   A   |          |   B   |---- 'network 2'
                 |       |==========|       |
                 +-------+   eth2   +-------+

tc qdisc add dev eth1 root teql0
tc qdisc add dev eth2 root teql0
ip link set dev teql0 up

(A)
ip addr add dev eth1 10.0.0.0/31
ip addr add dev eth2 10.0.0.2/31
ip addr add dev teql0 10.0.0.4/31
(B)
ip addr add dev eth1 10.0.0.1/31
ip addr add dev eth2 10.0.0.3/31
ip addr add dev teql0 10.0.0.5/31

A to je vše, nyní byste měli mít tři linky (dvě fyzické, jednu teql rozloženou) mezi vašimi počítači.

Další možnost je použít bonding, spojení více rozhraní do jednoho.

Sledování provozu

Sledování sítě můžete dělat např. pomocí programu tcpdump, tím ale nezískáte dobrou představu o využití šířky pásma.

Nástroj iptraf (curses) ukazuje aktuální zátížení, spojení, statistiky paketů podle velikosti a další možnosti. (jen Linux)

Zdroje, odkazy