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).
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.
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).
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).
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.
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
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
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)
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.
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.
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.
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.
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:10zde 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 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.
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í 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)