QoS - linux

Z HKfree wiki
Verze z 23. 11. 2021, 11:23, kterou vytvořil Bkralik (diskuse | příspěvky) (Bkralik přesunul stránku QoS na QoS - linux bez založení přesměrování)
(rozdíl) ← Starší verze | zobrazit aktuální verzi (rozdíl) | Novější verze → (rozdíl)
Skočit na navigaci Skočit na vyhledávání

Řízení provozu na linuxu

V tomto mini-HOWTO jsem se snažím srozumitelně vysvětlit problematiku řízení provozu na linuxu a uvést dostatek názorných příkladů. Všechno co je tu popsáno si lze přečíst v angličtině v Advanced routing and traffic controlling HOWTO a na docum.org. Dalším dobrým zdrojem se zdá být Differentiated Service on Linux HOWTO.

Queuing disciplines (režimy front)

Ovlivňují způsob, jakým linux zachází s pakety. Pakety může linux obecně přijmout, pozdržet nebo zahodit. Pokud je paket zahozen, pak závisí na protokolu, jak se s tím vyrovná. Protokol TCP při ztrátě paketu zpomalí a nepotvrzené pakety znovu odešle (narozdíl například od UDP). Efektivně omezovat lze jen odchozí provoz (pokud použijeme IMQ, pak lze stejnými metodami omezovat i příchozí provoz) používající protokol TCP. Je otázkou, zda omezovat i ostatní protokoly. Myslím si, že je to nutné, jelikož i protokol UDP je celkem běžně používaný a taktéž dokáže zahltit linku (například program brutalcopy od Clocka).

Když může síťová karta vysílat, pak požádá qdisc (nainstalovaný na příslušném rozhraní), aby jí dodal data. Jejich výběr je proto v jeho kompetenci. V nejjednodušším případě vybere z fronty nejdéle čekající, nebo použije nějakou sofistikovanější metodu.

Přehled

Rozlišujeme dva druhy qdisců podle toho, jestli obsahují třídy nebo ne. Qdiscy bez tříd jsou jednodušší, vyberu pár nejužitečnějších:

pfifo_fast 
Nejjednodušší qdisc, který je implicitně nainstalován. Má tři pásma, která fungují jako qdisc prio. V každém pásmu je fronta. Z méně prioritních front se odešlou pakety až poté co prioritnější fronty jsou prázdné (priorita se určuje pomocí ToS příznaku ip paketu). Délka front je konečná (při přeplnění jsou pakety zahazovány), ale dá se změnit.
tbf - token bucket filter 
Přesný omezovací qdisc. Princip na kterém je založen používá taktéž htb. Omezuje provoz na určitou rychlost.
(e)sfq - (extended) stochastic fairness queueing 
Už podle názvu by tento qdisc měl zaručovat férovost. Princip je takový, že obsahuje několik front a ty cyklicky obsluhuje. Do těchto front jsou podle hash funkce zařazovány TCP sezení případně toky dat protokolu UDP. Stochastický je protože, to do které fronty je paket zařazen závisí na hash funkci. Hash funkce se po několika sekundách mění (nastavuje se pomocí parametru perturb). Tento qdisc má význam na přeplněné lince. Existuje modifikace esfq, která pásma přiděluje podle zdrojové/cílové adresy a umožňuje nastavit další interní proměnné sfq (limit - délka fronty s pakety, depth - maximální počet současně obsluhovaných front, divisor - 2 umocněná na toto číslo nám udává maximální počet front (neboli počet bitů pro hash funkci; maximum 12)).

Qdiscy které mají třídy umožňují více kontrolovat tok dat. Tyto qdiscy můžou obsahovat další qdiscy. Pokud omezují (htb, cbq), pak to dělají právě třídy. Například qdisc cbq má parametr bandwidth, který slouží pouze pro informaci o kapacitě linky a nikoliv pro omezení toku. Pakety z konkrétní třídy jsou vždy předány qdiscu, který je v ní nainstalován (implicitně pfifo_fast). Přehled základních qdisců s třídami:

prio 
Nejjednodušší qdisc s třídami. Ve výchozím nastavení funguje jako pfifo_fast, vytváří tři třídy (pro prioritní :1, normální :2 a neprioritní provoz :3). Do každé této třídy můžeme nainstalovat libovolný qdisc. Lze změnit počet tříd, o vytváření tříd se stará prio sám (příklad změny počtu tříd je ve skriptu prio_web.sh - při změně parametru bands je nutné uvést parametr priomap). Prio neomezuje nijak provoz.
cbq 
Nejznámější a také nejméně pochopený qdisc. Pracuje na základě vytíženosti linky. Pokud má omezit provoz na 10Mbit lince na 1Mbit, pak tato linka musí být z 90% volná. Tento předpoklad teoreticky drží, ale v praxi cbq často neomezuje správně provoz. Má mnoho parametrů, některé jsou málo dokumentovány a je proto těžké ho správně nastavit. U každé třídy lze nastavit, zda si může půjčovat a zda půjčuje ostatním třídám. Narozdíl od htb nelze nastavit kolik si lze maximálně půjčit.
htb 
Pracuje na stejném principu jako tbf, proto je celkem přesný. Lze nastavit kolik si každá třída může maximálně vypůjčit. O htb si můžete také přečíst článek na root.cz.

Qdiscy tbf, cbq, htb mají společné parametry:

rate 
Rychlost (např: 20kbit, 1Mbit, 20k /20k = 160kbit !/)
burst 
Maximální povolená výchylka.
prio 
Priorita. Třídy s číselně menší prioritou jdou dříve.

Qdisc htb má navíc ceil a cburst, které nastavují maximální rychlost (kolik si třída může maximálně půjčit) a výchylku u půjčené rychlosti.

Qdisc htb i cbq nemusí (a občas je to výhodné) všechny pakety přiřazovat do tříd a tím pádem omezovat. U cbq jsou to všechny nezařazené pakety (často chyba v konfiguraci filtrů), u htb jsou to ty, které jsou směřovány do MAJOR:0 (ve výpisu jsou vidět jako direct_packets_stat).

Každý qdisc má tzv. handle (major). To je 16-bitové číslo. Kořenový qdisc má vždy číslo 1. Třídy mají tzv. classid (minor), což je také 16-bitové číslo. Volba těchto čísel je pouze na Vás. Dvojice MAJOR:MINOR jednoznačně identifikuje třídu (qdisc pouze v případě, že MINOR=0). Není rozdíl mezi zápisem 1: a 1:0. Každá třída může mít ještě podtřídy.

Příklady

Příklady (některé jsou vzaty z lartc a odzkoušeny).

pfifo_fast, pfifo, tbf, (e)sfq, prio

## PFIFO_FAST - kratší fronta
# ifconfig wlan0 txqueuelen 64

## PFIFO - kratší fronta (BFIFO - limit je v bytech)
# tc qdisc add dev wlan0 root pfifo limit 64

## TBF - omezení na 220kbit, pakety se v qdiscu zdrží nejdéle 50ms
# tc qdisc add dev wlan0 root tbf rate 220kbit latency 50ms burst 1540

## SFQ - každých 10 sekund změna hash
# tc qdisc add dev wlan0 root sfq perturb 10

## ESFQ - totožné jako SFQ výše (použity přednastavené hodnoty SFQ pro limit,depth,divisor)
# tc qdisc add dev wlan0 root esfq perturb 10 \
limit 128 depth 128 hash classic divisor 11

## ESFQ - kratší fronta = lepší odezvy
# tc qdisc add dev wlan0 root esfq perturb 10 \
limit 64 depth 64 hash src divisor 10

## PRIO
# tc qdisc add dev wlan0 root handle 1: prio
## Prio vytvoří třídy 1:1, 1:2, 1:3

## Do nejprioritnější třídy dáme sfq (tudy jede například ssh,telnet)
# tc qdisc add dev wlan0 parent 1:1 handle 10: sfq
## Normální provoz omezíme na 20kbit
# tc qdisc add dev wlan0 parent 1:2 handle 20: tbf rate 20kbit buffer 1600 limit 3000
## Do nejméně prioritní třídy nainstalujeme sfq (tudy jede scp, ftp-data)
# tc qdisc add dev wlan0 parent 1:3 handle 30: sfq

cbq

## CBQ
## Nainstalujeme kořenový qdisc
# tc qdisc add dev wlan0 root handle 1:0 cbq bandwidth 10Mbit         \
avpkt 1000 cell 8

## Nyní již vytváříme třídy, proto tc class. Toto je hlavní třída,
## pomocí které omezujeme provoz na určitou hodnotu. Tato třída si nesmí
## půjčovat, jelikož není nijak omezená (qdisc neomezuje).
# tc class add dev wlan0 parent 1:0 classid 1:1 cbq bandwidth 10Mbit  \
  rate 4Mbit weight 0.4Mbit prio 1 allot 1514 cell 8 maxburst 20      \
  avpkt 1000 bounded

## Nainstalujeme podtřídy. weight určuje nepřímo kolik dat může třída
## najednou vyslat (1/10 funguje celkem dobře). Detailněji jsou parametry popsané
## na lartc (osobně preferuji htb).
# tc class add dev wlan0 parent 1:1 classid 1:3 cbq bandwidth 10Mbit  \
  rate 3Mbit weight 0.3Mbit prio 5 allot 1514 cell 8 maxburst 20      \
  avpkt 1000
# tc class add dev wlan0 parent 1:1 classid 1:4 cbq bandwidth 10Mbit  \
  rate 1Mbit weight 0.1Mbit prio 5 allot 1514 cell 8 maxburst 20      \
  avpkt 1000

## Nainstalujeme do těchto tříd sfq
# tc qdisc add dev wlan0 parent 1:3 handle 30: sfq
# tc qdisc add dev wlan0 parent 1:4 handle 40: sfq

htb

## Nainstalujeme kořenový qdisc htb. Všechen provoz půjde do třídy 1:10
## pokud nebude filtry určeno jinak
# tc qdisc add dev wlan0 root handle 1: htb default 10

## Vytvoříme kořenovou třídu. Stejně jako u cbq tato třída omezuje provoz.
## Ceil u této třídy nemá smysl, jelikož nad ní je pouze qdisc, který neomezuje.
## Pokud by zde byl uveden ceil vyšší než rate, pak by tato třída neomezovala na
## rate, ale na ceil.
# tc class add dev wlan0 parent 1: classid 1:1 htb \
  rate 1792kbit burst 17kbit

## Potomci výše uvedené třídy. Součet rychlostí přímých potomků dané třídy
## nesmí být vyšší než rychlost rodiče (rate). U ceil by mělo platit, že žádný
## potomek nemá vyšší maximální rychlost než jeho rodič (není to tak vážná chyba
## jako porušení předešlého pravidla).

## Tato třída má garantován 1Mbit, ale může získat celou kapacitu od 1:1
# tc class add dev wlan0 parent 1:1 classid 1:10 htb \
  rate 1024kbit ceil 1792kbit burst 10kbit prio 1

## Třída s nižší prioritou, rychlostí, ale maximum stejné jako u předchozí
# tc class add dev wlan0 parent 1:1 classid 1:20 htb \
  rate 512kbit ceil 1792kbit burst 5kbit prio 2

## Nejméně prioritní třída s nejmenší rychlostí
# tc class add dev wlan0 parent 1:1 classid 1:30 htb \
  rate 256kbit ceil 512kbit burst 2kbit prio 3

## Vytvoříme podtřídu poslední třídy (je to méně náročnější než instalovat qdisc
## htb do této třídy a vytvořit v něm třídy). Takto může vzniknout celkem
## složitá hierarchie tříd. Třída si může půjčovat pouze od své rodičovské
## třídy. Pokud má třída 1:1 volný 1Mbit, pak přidělí 1:30 maximálně pouze
## 512kbit. Tolik rozdělí maximálně mezi podtřídy 1:31 a 1:32.
# tc class add dev wlan0 parent 1:30 classid 1:31 htb \
  rate 128kbit ceil 512kbit burst 1kbit prio 4
# tc class add dev wlan0 parent 1:30 classid 1:32 htb \
  rate 128kbit ceil 512kbit burst 1kbit prio 5

## Nainstalujeme do 1:10 a 1:20 prio
# tc qdisc add dev wlan0 parent 1:10 handle 10: prio
# tc qdisc add dev wlan0 parent 1:20 handle 20: prio

## Do 1:31 a 1:32 dame sfq
# tc qdisc add dev wlan0 parent 1:31 handle 31: sfq
# tc qdisc add dev wlan0 parent 1:32 handle 32: sfq

## Do podtříd qdiscu prio nainstalujeme taktéž sfq
# tc qdisc add dev wlan0 parent 10:1 handle 11: sfq
# tc qdisc add dev wlan0 parent 10:2 handle 12: sfq
# tc qdisc add dev wlan0 parent 10:3 handle 13: sfq
# tc qdisc add dev wlan0 parent 20:1 handle 21: sfq
# tc qdisc add dev wlan0 parent 20:2 handle 22: sfq
# tc qdisc add dev wlan0 parent 20:3 handle 23: sfq

Shrnutí

Qdiscy jsou užitečné, ale ne všemocné. Každý je vhodný na něco jiného. Jaké jsou tedy jejich výhody/nevýhody?

tbf přesně omezuje, ale nerozlišuje co omezuje. Když například uživatel stahuje z dc a zároveň prohlíží www stránky, pak přenosy z dc jedou rychlostí, na jakou byly omezeny pomocí tbf, ale pakety HTTP jsou často nadlimitní a proto se stránky načítají dlouho.

Pokud u qdiscu prio není omezena rychlost uvnitř třídy, pak se méně prioritní třídy nemusejí dostat vůbec ke slovu.

Pokud je třída u htb, cbq přeplněná, pak neovlivní ostatní třídy. Pakety v nich se dostanou postupně na řadu a odešlou se bez zpoždění. Pakety v přeplněné třídě na tom již tak dobře nejsou. Jelikož je tato třída přeplněná jsou některé pakety pozdrženy/zahozeny. Je lepší proto třídy naddimenzovávat.

Filtry

Když už máme vytvořené třídy, pak je potřeba je naplnit. O to aby skrz ně procházeli správné pakety se starají filtry. Filtry jsou vlastně pravidla. Filtrovat lze pouze v rámci jednoho qdiscu. Například v příkladu pro htb lze filtry směrovat data z 1:0 do 1:31 a nikoliv do 31: a 10:1. Pokud bychom chtěli směrovat data z 1:0 do 10:1 musíme to udělat postupně z 1:0 do 1:10 a z 10:0 do 10:1. Priorita u pravidel určuje pořadí v jakém se vykonávají. Filtry s číselně nižší prioritou se vykonají dříve, a proto je výhodné zde mít nejspecifičtější pravidla. Filtry se nemusejí mazat, stačí smazat příslušný qdisc. Filtrovat lze podle:

  • zdrojové/cílové adresy
  • zdrojového a cílového portu
  • ip protokolu (tcp, udp, icmp, ...)
  • značky z firewallu
  • podle pole ToS
  • podle různých položek hlavičky IP,TCP,UDP datagramu

Klasifikátor u32

## Výběr pomocí zdrojové adresy
# tc filter add dev wlan0 parent 1: prio 11 protocol ip u32 \
  match ip src 10.107.0.0/16 \
  flowid 1:20

## Výběr pomocí cílové adresy je obdobný
# tc filter add dev wlan0 parent 1: prio 11 protocol ip u32 \
  match ip dst 10.107.0.0/16 \
  flowid 1:20

## Výběr protokolu TCP (6 viz /etc/protocols)
# tc filter add dev wlan0 parent 1: prio 11 protocol ip u32 \
  match ip protocol 6 0xff \
  flowid 1:20

## Výběr podle protokolu pomocí obecného kvalifikátoru u8 (na 9 bajtu IP
## datagramu je číslo protokol vyšší vrstvy). u8 vybere devátý bajt provede
bitové AND s 0xff a porovná s hodnotou 6.
# tc filter add dev wlan0 parent 1: prio 11 protocol ip u32 \
  match u8 6 0xff at 9 \
  flowid 1:20

## Vybrat TCP ACK pakety menší než 64 - kombinace pravidel. První vybírá
## protokol TCP. Další zajišťuje, že paket nemá volitelné položky záhlaví (velikost
## hlavičky ip datagramu ve čtyřbajtech je rovna 5). Třetí zajišťuje, že
## velikost paketu bude menší než 64 a nakonec je test na ACK bit TCP paketu.
# tc filter add dev wlan0 parent 1:0 protocol ip prio 10 u32 \
  match ip protocol 6 0xff \
  match u8 0x05 0x0f at 0 \
  match u16 0x0000 0xffc0 at 2 \
  match u8 0x10 0xff at 33 \
  flowid 1:10

## Výběr pomocí zdrojového portu ( protokol TCP; služba ftp-data)
# tc filter add dev wlan0 parent 1: prio 10 protocol ip u32 \
  match ip protocol 6 0xff \
  match ip sport 20 0xffff \
  flowid 1:30

## Výběr pomocí cílového portu (protokolu UDP; služba DNS)
# tc filter add dev wlan0 parent 1: prio 10 protocol ip u32 \
  match ip protocol 17 0xff \
  match ip dport 53 0xffff \
  flowid 1:10

## Výběr podle ToS pole IP paketu (hodnota Minimize-Delay; například ssh, telnet)
# tc filter add dev wlan0 parent 1:0 protocol ip prio 10 u32 \
  match ip tos 0x10 0xff \
  flowid 1:10

Klasifikátor fwmark

Pokud nám nestačí klasifikátor u32, pak máme ještě k dispozici fwmark. Ten umožňuje vybrat pakety podle značky, kterou získají od firewalu. To je nutné například pokud chceme filtrovat podle zdrojové adresy na rozhraní, kde probíhá SNAT (skutečné zdrojové adresy se k nám nedostanou). Tato značka není součástí IP paketu, čili ji nemůžou vidět ostatní počítače narozdíl od ToS. Na značení paketů se používá tabulka mangle.

## Označení paketu pomocí iptables (podle MAC počítače)
# iptables -t mangle -A PREROUTING -p tcp -m mac --mac-source 12:34:56:78:90:ab -j MARK --set-mark 1

## Následně filtrujeme pomocí fwmarku (handle 1 = značka 1, fw = fwmark)
# tc filter add dev wlan0 parent 1: prio 10 protocol ip handle 1 fw \
  flowid 1:30

Další použití fwmarku závisí pouze na pravidlech pro iptables. U filtru se nastavuje pouze handle.

Klasifikujeme IPv6

Jelikož IPv6 nám klepe na dveře našel jsem na internetu pár příkladů, jak ho filtrovat (příklady jsem v praxi nezkoušel, je možné, že ještě pokulhává podpora - možná někdy vyzkouším).

## Označíme je pomocí fwmarku
# ip6tables -A PREROUTING -i eth0 -t mangle -p tcp -j MARK --mark 1

## Klasicky pomocí filtru
# tc filter add dev eth1 parent 1:0 protocol ipv6 prio 2 u32 match ip6 src
2001:6a8:802:7::2 classid 1:2
# tc filter add dev eth1 parent 1:0 protocol ipv6 prio 4 u32 match ip6 src
2001:6a8:802:6::2 classid 1:3

IMQ, IPP2P, CONNMARK - věci, které ve vanilla jádru nejsou

IMQ

IMQ nám umožňuje na příchozí provoz aplikovat stejné prostředky jako na odchozí. Bez něj bychom mohli použít pouze tzv. ingress qdisc, který je velice omezený vzhledem egressu. Dále můžeme omezovat provoz na více rozhraních společně. Například mějme příchozí linku 1Mbit, kterou chceme spravedlivě rozdělit mezi lokální uživatele (eth0) a wi-fi uživatele (wlan1). Bez IMQ to můžeme nechat neregulované (to asi nebude 100% spravedlivé) nebo oběma rozhraním přidělit 512kbit bez možnosti půjčovat si. Elegantnější cesta spočívá v použití IMQ.

## Zavedu modul pro imq a nastavím mu maximální počet zařízení
# modprobe imq numdevs=6

## Tímto nahodíme rozhraní imq0
# ip link set imq0 up

## Pomocí pravidla v iptables přesměrujeme všechny pakety přicházející na
## wlan0 do imq0 (pro imqN by bylo --todev N)
# iptables -t mangle -A PREROUTING -i wlan0 -j IMQ --todev 0

## A teč již můžeme omezovat ...
# tc qdisc add dev imq0 root handle 1: htb default 10
# tc class add dev imq0 parent 1: classid 1:1 htb rate 2304kbit burst 23kbit
...

IPP2P a CONNMARK

Pomocí ipp2p lze rozpoznat pakety patřící p2p sítím. Není to sice 100%, ale je to lepší než nic. Lze je tedy zakázat, nebo regulovat. Ipp2p rozezná již celkem dost protokolů:

  • eDonkey
  • Gnutella
  • FastTrack (Kazaa)
  • Direct Connect
  • Bittorent

Lze vybrat všechny pakety nebo pouze datové přenosy. Pokud chcete vybrat všechny pakety patřící DC, pak použijete --dc. Pro data --dc-data. Pokud chcete jedním pravidlem pokrýt všechny protokoly, pak použijte --ipp2p/--ipp2p-data (kromě Bittorentu pro něj musíte použít --bit). Ipp2p funguje pouze na TCP paketech. Pokud nechcete pouze zakazovat p2p provoz, pak budete muset použít CONNMARK. CONNMARK umožňuje označkovat celé TCP sezení.

## Vsude je -p tcp! Bez toho by ipp2p vypisoval chyby.
## Pokud byla tomuto TCP sezení nastavena značka, pak ji CONNMARK obnoví
# iptables -t mangle -A PREROUTING -p tcp -j CONNMARK --restore-mark

## Pokud je paket označen nastav mu do pole ToS, že není prioritní
# iptables -t mangle -A PREROUTING -p tcp -m mark --mark 1 -j TOS --set-tos Maximize-Throughput

## Neprováděj další pravidla pokud je paket již označen
# iptables -t mangle -A PREROUTING -p tcp -m mark ! --mark 0 -j ACCEPT

## Označí všechny datové přenosy p2p sítí, které ipp2p detekuje
# iptables -t mangle -A PREROUTING -p tcp -m ipp2p --ipp2p-data -j MARK --set-mark 1

## Uloží značku pokud je nastavena, aby mohla být obnovena
# iptables -t mangle -A PREROUTING -p tcp -m mark --mark 1 -j CONNMARK --save-mark

Takto označené pakety se již lehce zařadí pomocí fwmarku do správné (omezené) třídy.

Odstraňujeme qdisc a kontrolujeme

Mazání qdiscu

## Toto smaže qdisc z rozhraní wlan0 (včetně všech tříd, qdisců a filtrů)
## wlan0 bude nyní obsluhovat pfifo_fast (ten se smazat nedá)
# tc qdisc del dev wlan0 root

Kontrolujeme funkčnost omezování

Iptables

## Prohlédneme počitadla u pravidel. Pokud je někde 0, pak máte zřejmě problém.
# iptables -t mangle -L -n -v
Chain PREROUTING (policy ACCEPT 15M packets, 7252M bytes)
 pkts bytes target     prot opt in     out     source               destination                                                                                                     
 257K  119M IMQ        all  --  wlan0  *       0.0.0.0/0            0.0.0.0/0    IMQ: todev 0 
 481K  235M CONNMARK   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0    CONNMARK restore 
98426   79M ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0    MARK match !0x0 
    9  6250 MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0    ipp2p v0.6 --ipp2p-data MARK set 0x1 
    9  6250 TOS        tcp  --  *      *       0.0.0.0/0            0.0.0.0/0    ipp2p v0.6 --ipp2p-data TOS set 0x08 
    9  6250 CONNMARK   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0    MARK match 0x1 CONNMARK save  

Chain INPUT (policy ACCEPT 476K packets, 34M bytes)
 pkts bytes target     prot opt in     out     source               destination                                                                                                     

Chain FORWARD (policy ACCEPT 25M packets, 15G bytes)
 pkts bytes target     prot opt in     out     source               destination                                                                                                     

Chain OUTPUT (policy ACCEPT 640K packets, 72M bytes)
 pkts bytes target     prot opt in     out     source               destination                                                                                                     

Chain POSTROUTING (policy ACCEPT 25M packets, 15G bytes)
 pkts bytes target     prot opt in     out     source               destination

Qdisc

## Podobné jako u iptables. Pokud Vám nějakým qdiscem neprotékají data, pak
## je něco špatně, nebo máte smůlu, že nikdo ještě příslušné spojení nevytvořil.
## V tomto případě přes sfq 23: (prio - ToS neprioritní) a 21: (prio - ToS
## prioritní) neprošly zatím žádné pakety.
## V tomto přehledu není pfifo_fast. Pokud by jste chtěli vidět statistiku i u
## něj, pak místo něho nainstalujte jednodušší pfifo.
# tc -s qdisc show dev wlan0
qdisc sfq 23: limit 128p quantum 1514b 
 Sent 0 bytes 0 pkts (dropped 0, overlimits 0) 
qdisc sfq 22: limit 128p quantum 1514b 
 Sent 690749 bytes 6594 pkts (dropped 0, overlimits 0) 
qdisc sfq 21: limit 128p quantum 1514b 
 Sent 0 bytes 0 pkts (dropped 0, overlimits 0) 
qdisc sfq 13: limit 128p quantum 1514b 
 Sent 5681 bytes 24 pkts (dropped 0, overlimits 0) 
qdisc sfq 12: limit 128p quantum 1514b 
 Sent 82019598 bytes 116223 pkts (dropped 0, overlimits 0) 
qdisc sfq 11: limit 128p quantum 1514b 
 Sent 8638082 bytes 155069 pkts (dropped 0, overlimits 0) 
qdisc sfq 32: limit 128p quantum 1514b 
 Sent 7530988 bytes 4982 pkts (dropped 0, overlimits 0) 
qdisc sfq 31: limit 128p quantum 1514b 
 Sent 33633304 bytes 22338 pkts (dropped 0, overlimits 0) 
qdisc prio 20: bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
 Sent 690749 bytes 6594 pkts (dropped 0, overlimits 0) 
qdisc prio 10: bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
 Sent 90669849 bytes 271328 pkts (dropped 0, overlimits 0) 
qdisc htb 1: r2q 10 default 10 direct_packets_stat 7
 Sent 132546356 bytes 305261 pkts (dropped 0, overlimits 57139) 

Třídy

## Stejné jako u qdiscu, ale pro třídy
# tc -s class show dev wlan0
class prio 20:1 parent 20: leaf 21: 
class prio 20:2 parent 20: leaf 22: 
class prio 20:3 parent 20: leaf 23: 
class prio 10:1 parent 10: leaf 11: 
class prio 10:2 parent 10: leaf 12: 
class prio 10:3 parent 10: leaf 13: 
class htb 1:1 root rate 1792Kbit ceil 1792Kbit burst 2175b cburst 1823b 
 Sent 138635160 bytes 338066 pkts (dropped 0, overlimits 0) 
 rate 17738bit 70pps 
 lended: 18296 borrowed: 0 giants: 0
 tokens: 9582 ctokens: 7972

class htb 1:10 parent 1:1 leaf 10: prio 1 rate 1024Kbit ceil 1792Kbit burst 1279b cburst 1823b 
 Sent 95075747 bytes 302437 pkts (dropped 0, overlimits 0) 
 rate 12828bit 66pps 
 lended: 292524 borrowed: 9913 giants: 0
 tokens: 9600 ctokens: 7972

class htb 1:32 parent 1:30 leaf 32: prio 5 rate 128Kbit ceil 256Kbit burst 127b cburst 1631b 
 Sent 7841358 bytes 5187 pkts (dropped 0, overlimits 0) 
 rate 16bit 
 lended: 3889 borrowed: 1298 giants: 0
 tokens: -88578 ctokens: 3840

class htb 1:20 parent 1:1 leaf 20: prio 2 rate 512Kbit ceil 1792Kbit burst 639b cburst 1823b 
 Sent 745351 bytes 7210 pkts (dropped 0, overlimits 0) 
 rate 156bit 1pps 
 lended: 7152 borrowed: 58 giants: 0
 tokens: 8704 ctokens: 7899

class htb 1:31 parent 1:30 leaf 31: prio 4 rate 128Kbit ceil 256Kbit burst 127b cburst 1631b 
 Sent 34972704 bytes 23232 pkts (dropped 0, overlimits 0) 
 rate 5018bit 3pps 
 lended: 12236 borrowed: 10996 giants: 0
 tokens: -88578 ctokens: 3840

class htb 1:30 parent 1:1 rate 256Kbit ceil 256Kbit burst 255b cburst 1631b 
 Sent 42814062 bytes 28419 pkts (dropped 0, overlimits 0) 
 rate 5173bit 3pps 
 lended: 3969 borrowed: 8325 giants: 0
 tokens: -40194 ctokens: 3840

Kdo to dočetl až sem je fakt machr ;-).

ToS

Typ služby (Type of Service) je druhý byte v ip paketu. Je určen pro označování paketů, jež mají být doručeny přednostně (s minimální odezvou), či pro označování neprioritního provozu. Tento byte může být využit různě. Jeden způsob využívá bitů 4-7 (počítáno zprava od 1):

Binárně Decimálně Význam pásmo v pfifo_fast/třída v prio 0-2 iptables --set-tos
1000 8 Minimální odezvy 0 Minimize-Delay
0100 4 Maximální propustnost 2 Maximize-Throughput
0010 2 Maximální spolehlivost 1 Maximize-Reliability
0001 1 Minimální náklady 2 Minimize-Cost
0000 0 Normální služba 1 Normal-Service

Podle IPCHAINS-HOWTO smí být nastaven pouze jeden z těchto bitů. Lartc se k tomu nevyjadřuje, ale nalezneme zde mapování všech 16 možností na pásma pfifo_fast.

Další způsob využití tohoto byte poskytují tzv. Diferencované služby. Využívají prvních 6 bitů. Jak fungují si můžete přečíst na lartc.org. (osobně jsem do tímto ještě nezabýval).


Binary Decimcal  Meaning
-----------------------------------------
1000   8         Minimize delay (md)
0100   4         Maximize throughput (mt)
0010   2         Maximize reliability (mr)
0001   1         Minimize monetary cost (mmc)
0000   0         Normal Service

          As there is 1 bit to the right of these four bits, the actual
          value of the TOS field is double the value of the TOS bits.
          Tcpdump -v -v shows you the value of the entire TOS field, not
          just the four bits. It is the value you see in the first column
          of this table:

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

Skripty

  • prio_wlan0.sh - skript omezující pouze p2p provoz a využívající prio. Na dobré lince podává výborné výsledky.
  • shape_bad_users.sh - kladivo na neukázněné uživatele.
  • htb.sh - skript od Ládi z JNetu. Omezuje upload a rozděluje linku stejným způsobem jako shape_iface_per_user.sh (je srozumitelnější, ale musíte ho upravit na "míru").
  • shape_iface_per_user.sh - skript využívající pouze htb na omezení a "spravedlivé" rozdělení linky mezi uživatele. Jelikož není použito IMQ, tak omezuje pouze v jednom směru. Uživatel s nevytíženou rourou má dobré odezvy na dobré lince.
  • shape_wlan0.sh - omezovací skript z něhož jsou tu občas příklady. Je komentovaný a lze v něm nastavovat celou řadu parametrů.
  • prio_web.sh - jednoduchý omezovací skript. Upřednostňuje prioritní provoz, web a dns, zbytek omezuje. Založen na skriptu od Pavkrize.
  • tc_traffic.pl - skript, který dokáže číst data z výstupu tc a ukládat údaje do rrd.