Klasifikace provozu

Jan Barienčík, xbarienc(@)fi.muni.cz


Obsah


Úvod

Standartní komunikace v sítích typu IP probíha způsobem best effort. To znamená, že sýstém odesílá data bez záruky doručení. Při velkém vytížení sítě může být paket po cestě zahozen a musí být znovu vysílán. Mnohdy se stává, že později odeslaný paket dorazí dříve než ten, který byl odeslán jako první. IP protokol verze 4 nerozezná pakety, jejichž včasné doručení je pro nás důležité, a proto je potřeba definovat kvalitu služby (QoS). Cílem QoS je klasifikovat síťový provoz podle stanovených pravidel do tříd s rozdílnou prioritou. Pakety jsou následně z jednotlivých tříd postupně odesílány v požadovaném pořadí. Klasifikaci je možné s úspěchem použít i pro dělení šírky pásma mezi více uživatelů.

QoS Model integrované služby (IntServ)

Vyžaduje záruku QoS po celé trase mezi zdrojovou a cílovou stanicí. Všechny uzly na trase musí mít informace o parametrech datoveho toku a rezervované odpovídající zdroje. IntServ používá následující dvě třídy:

QoS Model diferencované služby (DiffServ)

Oproti svému předchůdci se jedná o jednodušší model. DiffServ disponuje lepší škalovatelností, což umožnuje garantovat kvalitu služby datového toku na větší vzdálenosti bez zbytečné zátěže výpočetního výkonu jednotlivých uzlů. V modelu DiffServ se rozlišují tři typy routerů:


Fronty paketů

Jednotlivé pakety se před vysíláním nebo po příjetí řádí do fronty. Pakety čekající ve frontě je možné ovlivňovat pomocí disciplín qdisc (queue discipline), což jsou vlastně implementace různých QoS algoritmů. Pakety je možné zahazovat, zpomalovat nebo měnit jejich pořadí. Jelikož není možné ovlivnit pakety, které přichází na vstup síťového adaptéru, je problematické uplatňovat QoS pro příchozí traffic. Jediný způsob jak regulovat rychlost příchozích dat, je prostým zahazováním paketů. Zahazování paketů je však účinné pouze u protokolu TCP, kde vyšší ztrátovost paketů způsobí snížení vysílací rychlosti.

Existují dva základní typy disciplín:


Classless qdisc


Classful qdisc


Podpora QoS v jádře Linuxu

Pro podporu QoS v Linuxu je nutné do konfigurace jádra přidat volby pro QoS.

    CONFIG_NET_SCHED=y
    CONFIG_NET_SCH_CLK_JIFFIES=y
  
Jednotlivé disciplíny (qdisc)
    CONFIG_NET_SCH_CBQ=m
    CONFIG_NET_SCH_HTB=m
    CONFIG_NET_SCH_PRIO=m
    CONFIG_NET_SCH_RED=m
    CONFIG_NET_SCH_SFQ=m
    CONFIG_NET_SCH_TBF=m
    CONFIG_NET_SCH_TEQL=m
    CONFIG_NET_SCH_DSMARK=m
  
Způsob klasifikace, značení paketů
    CONFIG_NET_CLS=y
    CONFIG_NET_CLS_FW=m
    CONFIG_NET_CLS_U32=m
    CONFIG_CLS_U32_MARK=y
  
Pokud je potřeba i virtuální rozhraní IMQ, je nutné jádro opatchovat pomocí patche http://www.linuximq.net/patches.html
    cd /usr/src/linux
    patch -p1 < /usr/src/imq/linux-2.6.16-imq2.diff
  
Dále do konfigurace jádra přidat volby CONFIG_IMQ a CONFIG_IP_NF_TARGET_IMQ.
Návod na instalaci IMQ je umístěn na http://wiki.nix.hu/cgi-bin/twiki/view/IMQ/HowToInstall


User-space programy pro QoS

Kolekce programů pro řízení provozu je poskytována pod souhrným názvem iproute.
Balíček je ke stažení na domácí stránce projektu http://linux-net.osdl.org/index.php/Iproute2.

V debianu iproute nainstalujeme následovně:

    apt-get install iproute
  

Pro používání IMQ je nutné patchnout iptables, jelikož standartně IMQ není podporován.
Zdrojové kódy iptablas http://www.netfilter.org, patch pro IMQ http://www.linuximq.net/patches.html

    cd /usr/src/iptables-x.x.x
    patch -p1 < iptables-x.x.x-imqx.diff
  


Konfigurace v Linuxu

Konfigurace se provádí pomocí utility tc (traffic control) z baličku iproute. Jednotlivé diciplíny se označují ve tvaru číslo:číslo, kde číslo před dvojtečkou udává číslo qdisku a číslo za dvojtečkou číslo třídy. Čísla mohou být libovolné, ale je dobré zachovat v číslování určitou logiku (pro přehlednost). Čísla slouží pro indentifikaci a proto musí být jedinečné.

Při tvoření stromové struktury je důležité dbát na to, aby součet průtoku dat listů nepřesáhl šířku pásma rodičovského uzlu. Stejně tak není dobré vytvářet velké množství listů s mnohonásobně nížší garantovanou propustností než propustností celkovou. Algoritmus pak špatně počítá a celé řízení toku dat se jeví jako nefunkční.

Příklad použití HTB

Představme si situaci, že máme k dispozici linku s downloadem 384kbps a chceme ji nasdílet třem uživatelům tak, aby každý uživatel měl garantováno minimálně 128kbps. Pokud nebude některý uživatel využívat svůj díl celý, bude jeho volná část pásma rozdělena mezi ostatní. Uživatelé mají IP adresy 10.0.0.10 - 10.0.0.12.

Nejprve připravíme jednotlivé třídy. Parametr rate udává garantovanou propustnost a ceil je maximální strop.

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

  tc class add dev eth0 parent 1: classid 1:1 htb rate 384kbit
  
  tc class add dev eth0 parent 1:1 classid 1:11 htb rate 128Kbit ceil 384kbit
  tc class add dev eth0 parent 1:1 classid 1:12 htb rate 128Kbit ceil 384kbit    
  tc class add dev eth0 parent 1:1 classid 1:13 htb rate 128Kbit ceil 384kbit

Standartně se na classful qdisc přidává fronta typu FIFO, která není moc spravedlivá a proto FIFO nahradíme disciplínou SFQ.

  tc qdisc add dev eth0 parent 1:11 handle 11: sfq perturb 10
  tc qdisc add dev eth0 parent 1:12 handle 12: sfq perturb 10   
  tc qdisc add dev eth0 parent 1:13 handle 13: sfq perturb 10 

Nyní už jen stačí rozhodit pakety do správných tříd. Provádí se to přídáním filtrů. Filtr pakety pro danou třídu může indentifikovat více způsoby. Může číst značku v TOS oktetu hlavičky paketu, filtrovat pomocí zdrojové/cílové IP adresy, zdrojového/cílového portu nebo využít značky vytvořené přes mangle tabulku v iptables.

Příklad klasifikace na základě cílové IP adresy

  tc filter add dev eth0 parent 1:1 protocol ip u32 match ip dst 10.0.0.10 flowid 1:11
  tc filter add dev eth0 parent 1:1 protocol ip u32 match ip dst 10.0.0.11 flowid 1:12
  tc filter add dev eth0 parent 1:1 protocol ip u32 match ip dst 10.0.0.12 flowid 1:13

Příklad klasifikace na základě označení přes iptables

  iptables -t mangle -A FORWARD -d 10.0.0.10 -j MARK --set-mark 10
  iptables -t mangle -A FORWARD -d 10.0.0.11 -j MARK --set-mark 11
  iptables -t mangle -A FORWARD -d 10.0.0.12 -j MARK --set-mark 12
 
  tc filter add dev eth0 parent 1:1 protocol ip handle 10 fw flowid 1:11
  tc filter add dev eth0 parent 1:1 protocol ip handle 11 fw flowid 1:12
  tc filter add dev eth0 parent 1:1 protocol ip handle 12 fw flowid 1:13

Použití značkování paketů přes iptables je výhodné tehdy, pokud je potřeba vytvořit složité pravidla jako na které nám samotný filtr nestačí. Příkladem může být klasifikace na základě MAC adres. Na druhou stranu je používání tabulky mangle o trochu pomalejší a někdy zbytečné.

Příklad použití IMQ

Máme obdobnou situaci jako v předcházejícím příkladě s tím rozdílem, že uživatelé se rozhodnou přikoupit další linku. Předpokládejme, že v routeru je připojení k internetu realizováno přes adaptéry wlan0, wlan1 a síťové rozhraní pro místní síť má označení eth0. Potřebujeme rodělit provoz mezi dvě linky.

vytvoříme virtuální rozhraní, které spojí naše dvě fyzické

  iptables -t mangle -A POSTROUTING -o wlan0 -j IMQ --todev 0
  iptables -t mangle -A POSTROUTING -o wlan1 -j IMQ --todev 0
  
  ifconfig imq0 up 

Aplikujeme obdobné QoS pravidla jako v předchozím příkladě

  tc qdisc del dev imq0 root
  tc qdisc add dev imq0 root handle 1: htb default 1

  tc class add dev imq0 parent 1: classid 1:1 htb rate 768kbit
  
  tc class add dev imq0 parent 1:1 classid 1:11 htb rate 256Kbit ceil 768kbit
  tc class add dev imq0 parent 1:1 classid 1:12 htb rate 256Kbit ceil 768kbit    
  tc class add dev imq0 parent 1:1 classid 1:13 htb rate 256Kbit ceil 768kbit

  tc qdisc add dev imq0 parent 1:11 handle 11: sfq perturb 10
  tc qdisc add dev imq0 parent 1:12 handle 12: sfq perturb 10   
  tc qdisc add dev imq0 parent 1:13 handle 13: sfq perturb 10 
  
  tc filter add dev imq0 parent 1:1 protocol ip u32 match ip dst 10.0.0.10 flowid 1:11
  tc filter add dev imq0 parent 1:1 protocol ip u32 match ip dst 10.0.0.11 flowid 1:12
  tc filter add dev imq0 parent 1:1 protocol ip u32 match ip dst 10.0.0.12 flowid 1:13

Rozdělení zátěže

Rozdělení zátěže mezi více síťových rozhraní se uplatňuje u routerů, které mají k dispozici více datových linek. Provoz můžeme triviálně rozdělit například pomocí routovací tabulky tak, že napevno nadefinujeme destinace a rozhraní, přes které budou pakety posílány. Není to však moc efektivní řešení v případě, kdy používání datových proudů není rovnoměrné, mění se v čase nebo když potřebujeme datové proudy detailněji třídit. V praxi je tedy toto řešení téměř nepoužitelné a proto je vhodné využít nějaký silnější nástroj.

Jednou z možností je použít qdisc TEQL (Trivial Link EQualizer). Celý mechanismus se chová trochu jako qdisc a trochu jako virtuální rozhraní. Utilitkou tc určíme fyzická rozhraní, která budou spojena do virtuálního rozhraní teql0. Qdisc TEQL pak rozděluje provoz mezi spojená rozhraní algoritmem round robin.

O zařazení paketů do správné třídy (klasifikaci) se stará filter.

Na obou strojích tedy spojíme fyzická rozhraní (řekněme wlan0 a wlan1).

    tc qdisc add dev wlan0 root teql0
    tc qdisc add dev wlan1 root teql0
    ip link set dev teql0 up
  


Monitorovací programy

Po nastavení pravidel kvality služby je dobré chování sytému otestovat. K tomu je možné použit některé z následujících programů pro monitorování okamžitého průtoku dat.


Odkazy

Linux Advanced Routing & Traffic Control HOWTO
IPROUTE2 Utility Suite Howto
Differentiated Service on Linux HOWTO
Seriál o HTB na serveru root.cz
Referát o QoS z podzimu2005