Referát z 36MPS

QoS / Traffic shaping na linuxu / v klfree.net

Jan Sechovec

Úvod

Obsah referátu

V tomto referátu bych se chtěl věnovat především možnostem řízení toku dat na linuxových routerech a v druhé části konkrétní implementaci v síti občanského sdružení Klfree.Net.

Vymezení pojmů

Začal bych vysvětlením dvou hodně frekventovaných zkratek, které je důležité chápat, než se pustím do vlastních podrobností.

QoS

Velice často užívaná zkratka QoS znamená Quality of Service. Jedná se spíše o obecný pojem, který ve své podstatě definuje jen to, že na různé služby máme různé požadavky. Často ale když hovoříme o QoSu, máme na mysli konkrétní řešení řízení toku dat (Traffic Shaping - viz dále), kterým ony požadavky plníme (nebo se alespoň pokoušíme plnit). Příkladem těchto požadavků na služby jsou například:
  • IP telefonie (VoIP) - požaduje co nejmenší latence na přenášená data
  • streamovaná hudba či video - požaduje garantovanou propustnost linky
  • počítačové hry hrané po síti - opět potřebná nízká latence
  • interaktivní služby - protokoly pro vzdálený přístup (ssh) - nízká latence
  • www stránky - rozumná latence, rozumná propustnost. (zhoršení některého z faktorů negativně ovlivňuje výsledek).
  • P2P? sítě - z pohledu uživatele co největší propustnost, pohledy správců sítě bývají různé

Traffic Shaping

Traffic Shaping znamená ono řízení toku dat, tzn. aplikace různých metod pro dosažení kýženého průtoku dat a tím splnění požadavků na QoS.

Proč toto vůbec řešíme?

Důležitá otázka, na kterou je velice jednoduchá odpověď. Vždy když se přenáší data, tak máme nějakou linku (linky) o omezené kapacitě. Kapacitu mohou limitovat buď technické možnosti (například po telefonním vedení před pár lety nešlo protlačit víc než nějakých 56kbit/s, přes ethernet 10,100,1000Mbit,...), nebo například i smluvní vztahy (pronajmeme si od firmy přípojku do internetu o určité kapacitě).

Dokud přenášíme méně než je tato kapacita, tak není co řešit. Data protékají tak jak přijdou a nejsou žádné problémy. Problémy nastávají jakmile chceme přenášet více, než máme k dispozici. Přes 1Mbit linku prostě 2Mbit dat procpat nejde smile Následkem tohoto zahlcení linky je nejprve nárůst latence (negativně se projeví právě na telefonii, hrách, interaktivních službách) a následně i ztrátovost paketů. Způsobeno je to tím, že paket který není možné okamžitě odeslat je za běžných podmínek zařazen do fronty (čekáním na odeslání narůstají latence) a paket který se ani do fronty nevejde (fronty nebývají nekonečné) je zahozen.

ape.JPG

Řešení jsou obecně dvě. Buďto zvětšit propustnost linky (např. nahradíme stávající 10Mbit prvky 100Mbitovými - jednoduché, ale většinou dosti drahé řešení) nebo lépe hospodařit se stávající kapacitou linky tak, abychom co nejlépe uspokojily naše požadavky (nebývá jednoduché, vždy je to o kompromisech, ale zas nás to nic nestojí).

Lépe hospodařit znamená v našem případě podle nějakých pravidel začít upřednostňovat data. Jinými slovy zavést sofistikovanější metody pro odesílání paketů než obyčejnou FIFO frontu před fyzickým odesláním dat linkou.

Jak tedy na to

Kdejaké zařízení (mikrovlnné pojítko, HW router, ...) se holedbá tím, že podporuje jakýsi QoS. Vysvětleno co se ale pod tím skrývá už bývá málokdy. Výsledky bývají různé - většinou tuto funkci lze je povolit či zakázat.

Jedním z dalších možných přístupů je použití údaje ToS (type of service) v hlavičce paketu. Původně jednotlivé bity znamenaly např. požadavek na nejmenší zpoždění, největší šířku pásma či nejlevnější dopravu. Existují reálné aplikace (využívající dalších bitů v hlavičce paketů), které na tomto principu fungují. Paket je při vstupu do sítě označen a při dalším průchodu sítí je tato informace využívána. Příkladem tohoto přístupu je například využití DSCP (differentiated services code point) u výrobků společnosti CISCO.

Pokud ale nepoužíváme na síti zařízení, kterým tento úkol svěříme (routery CISCO s DSCP, či "pochybné QoSy" implementované přímo do zařízení), nezbývá nám nic jiného, než se touto problematikou začít zajímat více dopodrobna a například využít možnosti které nám v tomto směru dá router postavený na linuxu.

Traffic Shaping na linuxu

Požadavky na SW

Kernel

Možnosti pro řízení toku jsou přímo v jádru (kernelu) linuxu. Pokud využíváme jádro obsažené v distribuci, je potřeba zkontrolovat, zda obsahuje podporu pro disciplíny (viz dále v textu), které pro shaping budeme používat. Pokud ne, je nutná kompilace vlastního jádra s příslušnou podporou. Další "komplikací" může být, když se rozhodneme pro záležitost, která není součástí zdrojového kódu jádra (např. využití IMQ -- opět viz dále), potom je nutné na zdrojový kód jádra navíc aplikovat vyžadované patche.

balík iproute2

Balík iproute2 (někdy označovaný pouze iproute) obsahuje velké množství praktických utilit (podrobně viz Lartc). Jednou z nich je i příkaz tc, pomocí kterého se ovládají funkce traffic shapingu z jádra.

iptables

Pokud budeme používat vazbu na iptables, je nutné mít i v balíku iptables příslušnou podporu (pokud není - je nutné opatchovat + zkompilovat).

Egress a ingress shaping

Pod těmito pojmy se skrýva základní omezení, kterého si musíme být vždy vědomi. Bez použití speciálních metod (IMQ), lze vždy řídit POUZE odchozí data (egress shaping). Nemáme žádnou kontrolu nad tím, co přijímáme (ingress shaping). To co nám linkou přijde ovlivňuje druhá strana (u p2p spoje .. nebo i více koncových stanic - v závislosti na topologii). Pokud je na druhé straně stroj, který máme pod kontrolou, tak samozřejmě můžeme řídit provoz v obou směrech. Ale ne vždy je tomu tak. Například na routeru, který je připojen dále do internetu, tak v drtivé většině případů druhou stranu spoje realizuje ISP, takže nemáme žádnou možnost ovlivnit to, co nám pošle.

Toto je jedna z nejdůležitějšich věci co je potřeba chápat. Často to také bývá právě kámen úrazu - nejsme moc dobře schopni ovlivnit to co přijímáme (velký problém například u wifi, či u zmiňovaného připojení do internetu).

Queue disciplíny

To v jakém pořadí odesíláme data mají na svědomí queue disciplíny. Jsou vždy vázané na příslušný interface. Zjistit aktuální používanou disciplínu pro jednotlivé interfacy lze například pomocí příkazu ip a (příkaz ip je součástí balíku iproute, elegantně nahrazuje příkazy jako ifconfig, route, arp - použitá varianta "ip a" je krátká verze pro ip address show)

výstup může vypadat napřiklad následovně:

[root@svetlusak ~]# ip a
1: eth0:  mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:c0:4f:40:0f:9f brd ff:ff:ff:ff:ff:ff
    inet 10.102.84.209/29 brd 10.102.84.215 scope global eth0
    inet6 fe80::2c0:4fff:fe40:f9f/64 scope link
       valid_lft forever preferred_lft forever
2: lo:  mtu 16436 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
3: wifi0:  mtu 1500 qdisc pfifo_fast qlen 1000
    link/ieee802.11 00:60:b3:64:c1:fe brd ff:ff:ff:ff:ff:ff
4: wlan0:  mtu 1500 qdisc htb
    link/ether 00:60:b3:64:c1:fe brd ff:ff:ff:ff:ff:ff
    inet 10.102.84.129/26 brd 10.102.84.191 scope global wlan0
    inet6 fe80::260:b3ff:fe64:c1fe/64 scope link
       valid_lft forever preferred_lft forever
5: wifi1:  mtu 1500 qdisc pfifo_fast qlen 1000
    link/ieee802.11 00:60:b3:6d:5e:5c brd ff:ff:ff:ff:ff:ff
6: wlan1:  mtu 1500 qdisc noqueue
    link/ether 00:60:b3:6d:5e:5c brd ff:ff:ff:ff:ff:ff
7: ath0:  mtu 1500 qdisc htb qlen 200
    link/ether 00:0b:6b:35:4f:3b brd ff:ff:ff:ff:ff:ff
    inet 10.102.26.194/29 brd 10.102.26.199 scope global ath0
    inet6 fe80::20b:6bff:fe35:4f3b/64 scope link
       valid_lft forever preferred_lft forever
8: dummy0:  mtu 1500 qdisc noqueue
    link/ether b2:71:04:b6:93:67 brd ff:ff:ff:ff:ff:ff
    inet 10.102.0.252/32 brd 10.102.0.252 scope global dummy0
    inet6 fe80::b071:4ff:feb6:9367/64 scope link
       valid_lft forever preferred_lft forever
9: imq0:  mtu 1500 qdisc htb qlen 30
    link/void
10: imq1:  mtu 1500 qdisc pfifo_fast qlen 30
    link/void
Pro nás jsou v tomto výpise zajímavé zejména údaje na konci prvního řádku u každého interface - tudíž pro eth0 qdisc pfifo_fast. Toto znamená, že pro data odcházející přes interface eth0 bude použita disciplína pfifo_fast (jak název napovídá fifo fronta).

Další z možností jak získat informace by byl příkaz tc qdisc show.

Classless a classful disciplíny

Než se pustíme do popisu jednotlivých disciplín, rozdělíme si je na dvě základní skupiny. Classless - česky doslova (ošklivě) přeloženo jako beztřídé. Jedná se o skupinu disciplín, které pouze nějakým způsobem volí co odesílat dříve bez dalšího dělení dat na jednotlivé třídy (classy). Podstatně komplexnějším řešením je použití některé z classful disciplíny, čili disciplín, které obsahují třídy (classy). Jedná ze především o PRIO, CBQ a HTB. Máme k dispozici stromovou strukturu jednotlivých tříd, paket nejprve klasifikujeme = zařadíme do příslušné classy. V závislosti na použití disciplíny pak odesíláme pakety daných tříd.

classless disciplíny

Nejčastěji používané jsou zejména:

pfifo_fast

Defaultní queue disciplína. Co první přijde to také první odejde .. tedy téměř. Kernel zde bere v potaz ToS údaj z paketu. Jsou k dispozici 3 fronty, které mají snižující se priority (fronta 0 má přednost před 1,2, fronta 1 před frontou 2). Pakety jsou zařazeny do příslušné fronty podle příznaků v ToS. Takže například paket s příznakem "minimum_delay" muže být zařazen do nejvíce priorizované fronty. Přiřazení jednotlivých ToS do tříd lze měnit. Lze také nastavit velikost této fronty.

SFQ - Stochastic Fairness Queueing

Do kruhové fronty se ukládá kombinace IP a portu pro buď zdroj nebo cíl paketu. Pakety jsou pak odesílány algoritmem round-robin nad touto frontou. Znamená to, že dostupná kapacita by se měla rovnoměrně rozdělit právě podle kombinace IP-port.

Nevýhodou této metody je to, že pokud někdo využívá velké množství spojení (zejména P2P? programy), tak každé spojení vytvořené s různým portem je bráno jako samostatná entita pro dělení kapacity linky. Tento problém řeší disciplína ESFQ, která bere v potaz pouze IP adresu nikoli již port.

Tato metoda je často užívána, pokud je potřeba linka rozdělit rovnoměrně mezi jednotlivé uživatele - identifikované podle jejich IP adresy.

classful disciplíny

PRIO

Nejprve popíši PRIO disciplínu, protože je jednoduchá a dobře se na ní pochopí podstata rozdělení do tříd. Prio - jak název napovídá je o priorizaci jednotlivých tříd. Mateřskou třídu (pokud je vázaná přímo na interface, tak jí označíme jako root třídu), můžeme rozdělit na několik podtříd s různou prioritou. Podobný princip funguje i u pfifo_fast, s tím rozdílem, že nyní máme možnost sami rozhodnout, které pakety zařadíme do jednotlivých tříd (viz dále). Dále máme možnost listům grafu (v tomto případě jednotlivým prioritním podtřídám přiřadit jakoukoli další disciplínu, která bude dále řídit zpracování uvnitř této třídy - například výše zmiňované pfifo_fast nebo SFQ).

HTB (Hierarchical Token Bucket)

Disciplína vzniklá na základě CBQ (Class Based Queueing), má jednodušší a více intuitivní nastavení. Pro jednotlivé třídy mame možnost nastavení především dvou parametrů - rate a ceil. Ceil je celkové maximum - HTB neumožní odesílat pakety dané třídy rychleji než je nastaveno. Takže například můžeme vytvořit třídu určenou pro smtp protokol, které omezíme ceil na 256kbit/s. Náš poštovní server pak nikdy nebude moct odesílat rychleji, než touto rychostí.

Parametr rate můžeme zjednodušeně označit jako jakousi garantovanou rychlost. Nejprve jsou odeslány pakety v rámci rate jednotlivých tříd a poté když nám něco zbyde, rozdělí se zbytek mezi třídy, co chtějí přenášet data větší rychlostí, než je jejich rate.

HTB příklad

Jak to celé funguje bude nejlepší vysvětlit na jednoduchém příkladu. Představme si situaci, kdy máme k dispozici linku o kapacitě 1Mbit. Běží nám přes ní www server, mail server a ftp server. Našim cílem je zajistit jednotlivým serverům dobré podmínky pro chod.

Nejprve definujeme mateřskou třídu o celkové dostupné kapacitě (1Mbit). V ní vytvoříme 3 podtřídy pro data jednotlivých serverů. Ceil všech třech bude opět 1Mbit - zajistíme tak, že v době, kdy bude některý ze serverů neaktivní, budou ostatní moct využít veškerou dostupnou kapacitu linky. Rate nastavíme řekněme 300kbit pro www, 200kbit pro smtp, a 500kbit pro ftp server.

Takže v případě že všchny 3 severy chtějí současně odesílat data, linka se rozdělí právě v poměru rate, pokud některý ze serverů nebude využívat celého svého pásma, tak se zbytek rozdělí mezí ostatní a linka se tak využívá optimálně.

Klasifikátory

Z předchozího výkladu máme tedy jisté povědomí o třídách podle kterých je rozdělena dostupná kapacita. Zbývá tedy pohovořit o tom, jak pakety do jednotlivých tříd vůbec rozdělit. K tomuto účelu slouží několik tzv. klasifikátorů neboli filterů. Nejčastěji používané jsou zejména u32, který umožňuje zařazení paketu do třídy podle údajů uvedených v hlavičce paketu (zdrojová/cílová IP aresa, port, velikost paketu, ...) a dále fw, což je filtr který využívá označování paketů přes MARK v iptables. Máme tak možnost ke třídění používat i pravidla iptables. Podrobnější popis viz odkazy - zejména LARTC.

Velice silnou zbraní v kombinaci s iptables je potom například L7 filter. Jedná se o modul do iptables, který je schopný podle obsahu paketu (nikoli pouze hlavičky, ale analýzou dat) rozpoznat nejčastěji používané protokoly. Zejména detekci P2P? protokolů využívá velké množství ISP. Velice efektivně lze pak omezit/zakázat tyto požírače konektivity.

IMQ

Poslední věcí kterou bych chtěl zmínit je IMQ (The Intermediate queueing device). Je to jedna z možností jak například alespoň částečně řídit příchozí datový tok. Trik spočívá ve vytvoření speciálního zařízení (realizované přes modul jádra), do kterého můžeme přes mangle tabulku iptables "poslat" data. Toto zařízení se z pohledu shapingu chová jako klasické fyzické zařízení (eth0,..) a máme tedy možnost mu přiřadit některou z předchozích disciplín.

Přestože nemůžeme nijak ovlivnit to co nám druhá strana pošle, máme možnost regulovat (také často v tomto případě mluvíme spíše o policingu než shapingu) příchozí průtok - a to díky vlastnostem TCP protokolu. TCP automaticky snižuje rychlost odesílaných dat v případě že nedostane včas potvrzení o přijetí. Tím, že uměle omezíme průtok na cestě paketu, tak vysílač automaticky sníží rychlost a v důsledku nám tím poklesne i rychlost přijímaných dat na rozhraní, které jinak nedokážeme přímo regulovat.

Bohužel toto nefunguje u nepotvrzovaných protokolů (např. UDP, ICMP). Zde neexistuje zpětná vazba na průchodnost paketů. Proto také jsou tyto protokoly často zneužívány k tzv. floodům. Útočník v tomto případě zaplavuje oběť velkým množstvím těchto paketů. Pokud má oběť k dispozici pomalejší linku, může dojít k jejímu úplnému zahlcení. Proti podobným útokům nemáme možnost se nijak bránit na úrovni shapingu - jediná cesta bývá upozornění poskytovatele internetu (který tento zdroj zakáže u sebe), případně fyzická eliminiace zdroje (může se například jednat o zavirovaný PC, takže řešením je odpojení od sítě, či u bezdrátových technologii zákaz na úrovni asociace k AP).

Implementace v Klfree.Net

Specifické problémy, které je potřeba řešit

Klfree.net je komunitní síť působící v Kladně a jeho okolí. Podílím se zde právě na traffic shapingu, který by měl umožnit členům využívat síť co nejlépe. S postupem času (a s nárůstem finančních zdrojů) zůstaly jako víceméně jediné problematické místo koncové wifi vysílače. Páteřní spoje a konektivitu do internetu totiž lze upgradovat při nedostatečné kapacitě na lepší technologie (viz úvod a rozprava o tom, proč vůbec traffic shaping). Bohužel koncové vysílače tímto způsobem vylepšovat úplně nejde, takže zde je hlavně místo, kde v současné chvílí problémy řeší právě traffic shaping.

Použité řešení

Na wifi obecně platí, že při větší zátěži narůstá doba odezvy (ping) a také většinou uživatelům s horším signálem se podstatně zhoršuje připojení. Je proto žádoucí najít limit, při kterém budou ještě rozumné pingy a zároveň poteče co nejvíc dat. S tímto spojená otázka vždy je, na jak velkou rychlost to omezit. Odpověď není moc jednoduchá není díky špatně popsatelnému chování wifi. Stanovení "stropu" je vždy o hledání kompromisů.

Jednak je wifi halfduplexní technologie To znamená, že nemůže současně jak vysílat, tak přijímat. Toto se projevuje tak, že celková přenosová kapacita linky se vždy musí nějak rozdělit mezi upload a download. Takže když máme celkovou kapacitu řekněme 5Mbit - tak už lze napřiklad jen 3Mbit použít pro download (stahovnání) a 2Mbity pro upload (odesílání dat od uživatele). Preferovaný je většinou download. Jednak kvůli zájmům členů, tak také z technického hlediska. Upload bývá více problémový, protože laicky řečeno víc lidí současně "svítí" na AP. Když uživatelé vysílají své data, dochází častěji k problémům (vzájemné rušení, kolize při současném vysílání více klientů jednoho AP).

Druhou věcí je dělení kapacity mezi víc připojených klientů na AP. V praxi když uživatel sám stahuje na AP, může při ideálním signálu dosáhnout i rychlosti kolem "neuvěřitelných" 5Mbit/s. Jenže pokud je uživatelů víc, už toto v drtivé většině případů neplatí. Lze považovat za úspěch, když se podaří zajistit rozumné pingy při celkovém reálném vytížení kolem 3Mbitu (2Mbit download, 1Mbit upload).

Předchozí čísla jsou ale opět jen teorie. Troufnu si tak trochu šarlatánsky přirovnat wifi k alchymii, kde to prostě "nějak" funguje, ale vzhledem k množství faktorů, které ovlivnějí přenosové vlastnosti, tak hledat v tom nějaké zákonitosti při větším množství připojených lidí bývá nemožné.

Trocha historie

Původní myšlenka byla samozřejmě co možná nejlépe využít dostupnou kapacitu linky. Již někdy před rokem se nasadil systém, který zvýhodňoval určitý druh přenosu dat. Členové byli omezeni pouze celkovým maximem pro damé AP. Teoreticky tak každý mohl využít celou kapacitu v případě, že by stahoval on sám.

Praxe však ukázala mnoho problémů spojených s tímto řešením. Všechny jsou víceméně způsobené faktem, že provoz na wifi je ovlivněn obrovským množstvím faktorů. Snažit se vysledovat například závislosti toho, jak přenos určitého člena ovlivňuje celkové chování daného AP bývá velmi problematické.

Často nastává situace, kdy při večerní špičce odezvy jdou do řádu stovek milisekund (pociťují hlavně ti, co hrají hry přes internet), případně členům s horším signálem narůstá ztrátovost paketů a "internet je nefunkční". Toto lze řešit hodinami strávenými hledáním viníka z našich řad (často stahovač, který svým signálem většinou zaruší celé AP). Bohužel většinou není jiná cesta, než metoda pokus-omyl, kdy jsou pokusně buď odpojováni nebo "banováni (=je jim snížena rychlost)" členové až do zlepšení situace. Což samozřejmě nemusí vést k úspěchu, protože problémy může často způsobovat provoz jiného wifi-subjektu díky rušení, nebo například i povětrnostní vlivy.

Po X hodinách strávených v hledání problémů jsem tak došel k závěru, že lepší než trávit čas jejich odstraňováním je lepší všemu samozřejmě předcházet. To aby se kapacita rozdělila pokudmožno rovnoměrně je právě úkol pro traffic shaping.

Jak to tedy vlastně funguje?

Každému členu je počítáno, kolik přenesl dat. Je brán součet pro všechny jeho IP adresy (tudíž ti co jich mají více nejsou nijak zvýhodněni). Při dosažení určitého množství dat za poslední hodinu je členovi omezena rychlost dle nastavení na daném AP.

Omezení podle přenesených dat je víceméně relikt. Stejnou funkci by mělo i to, kdyby omezení bylo aktivni stále - nezávisle na přenesených datech. Důvodem, proč zůstalo zachováno omezení až při určitém množství dat je například možnost otestovat kvalitu linky stažením testovacího souboru v době, kdy není člen omezen. Lze tak lépe diagnostikovat problémy dané špatným signálem, rušením a podobně.

Obecně tedy lze říci, že na wifi všesměrech bude mít každý člen definované maximum a rychleji to prostě nepoběží ani v případě, že linka není vytížena na maximum.Tímto na první pohled tupým omezení se ale dá předejít mnoha problémům a zároveň zachovat dostatečnou rychlost připojení pro každého.

Množství omezení závisí na daném AP. Tam kde problémy nejsou není moc potřeba cokoli omezovat. Pokud jsou členové k sobě vzájemně sami ohleduplní vše funguje dobře a není pořeba nic řešit. Tam kde to nejde, doufejme zabere toto systémové řešení. ...

Implemenace

Celý systém je postaven na HTB. Nejprve skript stáhne z centrálního serveru (IS) data o tom, kdo je na tomto rozhraní připojen. Společně s tímto seznamem získá IP adresy jednotlivých členů. Následně je každému členu vytvořena jeho vlastní třída, do které je pomocí filtrů zařazen provoz všech jeho IP adres. V periodických intervalech se potom nastavuje omezení (ceil hodnota) pro každého uživatele v závislosti na jeho provozu.

Výsledky

Systém zatím funguje celkem spolehlivě. Samozřejmě občas se objeví problémy, které musí řešit lidský administrátor, na které je shaping krátky. Zejména zavirovaná PC působí velké problémy. Také občas dochází k nepochopení z řad členů, kteří byli zvyklí bezohledně sosat na úkor ostatních a zavedením těchto omezení jim to neběží tak jako v dobách anarchie. Přesto myslím, že tento systém je použitelný a bráním se nasazení metod některých ISP, kteří jednoduše omezí P2P? a tím většinou vyřeší problémy přetížených linek stahovači.

Další rozvoj vidím ve více dynamickém chování v závislosti na zátěži - určitě je ještě co vylepšovat.

Odkazy

-- JanSechovec - 22 Oct 2006

Topic attachments
I Attachment Action Size Date Who Comment
jpgJPG ape.JPG manage 21.8 K 2006-10-22 - 12:20 JanSechovec obr1
Topic revision: r10 - 2006-10-27 - 09:40:19 - JanSechovec
 
This site is powered by the TWiki collaboration platformCopyright &Š by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback