Sterowanie przepływem danych w linuksie





1 Wprowadzenie


Sterowanie przepływem danych (traffic control) jest kolejna nowoscia w Linuksie 2.2. Własciwie juz w kernelach 2.1 zaimplementowano prosty traffic shaper, ale posiadał on dosc powazne ograniczenia i słuzył wyłacznie do ograczania ruchu (stad nazwa shaping). Od tej pory Linux zyskał bardzo bogaty zespół procedur słuzacych nie tylko do ograniczania ruchu, ale – ogólniej – do sterowania przepływem danych. Ich zastosowanie to przede wszystkim optymalizacja wykorzystania łacz, oraz zapewnianie okreslonych parametrów łacza dla wybranych transmisji. Wszystko to wiaze sie z bardzo obszernymi i szeroko obecnie dyskutowanymi zagadnieniami usług o gwarantowanej jakosci (quality of service), o które bedziemy sie nieustannie ocierac podczas omawiania tego co Linux ma do zaoferowania w tej dziedzinie.
Na poczatek musimy poczynic kilka załozen. Po pierwsze, łacza maja ograniczona przepustowosc. Po drugie, przepustowosci łacz w Internecie sa bardzo zróznicowane. Router moze przyjmowac dane z Ethernetu z predkosciami rzedu megabitów na sekunde i wysyłac je łaczem szeregowym o przepustowosci o dwa rzedy wielkosci mniejszej. Wiekszosc omawianych ponizej procesów zachodzi na styku takiego szybkiego i wolnego łacza, co siła rzeczy prowadzi do sytuacji, gdy czesc pakietów nie moze zostac „wepchnieta” w waskie gardło i jest gubiona. Zastosowanie w tym miejscu sterowanie przepływem danych pozwala ograniczyc straty do minimum, poprawic wykorzystanie łacza, a takze – w razie potrzeby – zapewnic okreslonym rodzajom danych pierwszenstwo. I jeszcze uwaga na temat samego dokumentu. Stanowi on drugi z cyklu artykułów na temat nowosci w zakresie obsługi protokołu IP, jakie pojawiły sie w Linuxie 2.2. Jest przeznaczony dla srednio zaawansowanych administratorów sieci, chcacych lepiej wykorzystac dostepne im zasoby. Funkcjonalnie składa sie z dwóch czesci – teoretycznej (rozdziały 2–6) i praktycznej (rozdział 7). W pierwszej starałem sie przyblizyc podstawy sterowania przepływem danych w sieciach IP, ukierunkowane na implementacje linuxowa. Druga czesc słuzy jako podreczne kompendium do konfiguracji QoS w działajacych sieciach.

2 Droga pakietu przez ruter


Ponizszy schemat przedstawia działanie interesujacego nas fragmentu funkcjonalnego rutera. Dane przychodza z kilku interfejsów i sa przez ruter demultipleksowane. Demultipleksacja obejmuje usuniecie nagłówków warstwy łacza oraz przyporzadkowanie pakietu do danego protokołu warstwy sieciowej, a nastepnie transportowej – jesli jest on skierowany do tego hosta.
warstwa transportowa
(TCP, UDP)
przekazywanie
demultipleksacja
wejscia
obsluga
wyjscia


W przypadku rutera wiekszosc ruchu stanowia pakiety kierowane do innych hostów. Ich obsługa to czesc schematu opisana jako przekazywanie (forwarding) – obejmuje to przede wszystkim wyznaczenie adresu nastepnego rutera oraz interfejsu docelowego dla takiego pakietu. Dane przeznaczone do wysłania przez okreslony interfejs trafiaja do kolejki wyjsciowej (obsługa wyjscia), z której sa usuwane tak szybko jak to jest stanie zrealizowac dany interfejs.
Jak wspomnielismy wyzej, interesuja nas głównie przypadki gdy danych w kolejce wyjsciowej przybywa szybciej, niz interfejs jest w stanie je z niej pobierac i wysyłac do celu. Jesli kolejka ma wystarczajaco duza pojemnosc, a przeciazenie nie trwa zbyt długo, to istnieje mozliwosc ze pakiety zostana stopniowo wysłane przez interfejs. W przeciwnym razie czesc z nich zostanie zgubiona. O tym, które pakiety zostana zgubione decyduje algorytm obowiazujacy w danym buforze–kolejce. Istotna konsekwencja takiego modelu jest to, ze sterowanie przepustowoscia dotyczy wyłacznie ruchu wychodzacego z rutera. W kontekscie wykorzystania łacz jest to jednak całkowicie uzasadnione i wystarczajace – ruter otrzymujacy dane z przeciazonego łacza nie moze za pomoca kolejkowania zmniejszyc przeciazenia – moze to zrobic wyłacznie ruter po drugiej stronie, bedacy zródłem danych. Ograniczenie ruchu przychodzacego do wybranej grupy hostów w celach administracyjnych mozna natomiast osiagnac regulujac przydzielone tej grupie pasmo na interfejsie ich rutera.

3 Algorytmy kolejkowania


W nomenklaturze angielskiej okreslany jako queueing discipline termin ten ma troche szersze znaczenie niz wynika z polskiego tłumaczenia. Poniewaz okreslenie „algorytm kolejkowania” jest dosc nieporeczne, bedziemy go ponizej uzywac zamiennie z okresleniem „kolejka”. Ogólnie rzecz biorac, algorytm kolejkowania decyduje w jakiej kolejnosci przeznaczane sa do wysłania pakiety znajdujace sie aktualnie w kolejce. Istotne jest, ze moze on byc albo jednym z elementarnych algorytmów opisanych ponizej, albo stanowic złozona strukture, podzielona na klasy z przyporzadkowanymi wieloma algorytmami elementarnymi. Ponizsze schematy ilustruja oba te przypadki.

3.1 Prosta kolejka
Prosta kolejka z rysunku to zazwyczaj FIFO (patrz nizej). Taki algorytm jest uzywany domyslnie na interfejsach Ethernet, PPP i innych, obsługiwanych przez Linuxa. Równie dobrze moze to byc jednak jeden z algorytmów opisanych ponizej – TBF, SFQ itp.

3.2 Kolejka złozona
Kolejka złozona moze byc bardzo rozbudowana struktura, zawierajaca w sobie kolejki proste oraz inne elementy, takie jak filtry i klasy. Elementarny algorytm
kolejkowania
Klasa
Elementarny algorytm
kolejkowania
Klasa
Filtr
Filtr
Filtr
Algorytm kolejkowania
Składniki kolejki złozonej:
• Filtry, odpowiadajace za przyporzadkowanie pakietów do odpowiednich klas na podstawie wybranych parametrów, takich jak adres zródłowy, docelowy, protokół i wiele innych.
• Klasy, posiadajace rózne priorytety i stanowiace własciwe rozróznienie miedzy róznymi rodzajami ruchu.
• Elementarne algorytmy kolejkowania, decydujace o sposobie obsługi pakietów, które trafiły do danej klasy.

4 Filtry


Pakiet wchodzacy do złozonej kolejki jest klasyfikowany do okreslonej klasy przez filtr, kierujacy sie wybranymi parametrami pakietu. W zaleznosci od rodzaju filtra moga to byc: adres zródłowy i docelowy pakietu, port, protokół, TOS itp. W chwili obecnej w linuxowej implementacji QoS dostepne sa trzy podstawowe filtry – route, fw oraz u32.

4.1 route
Filtr oparty o tablice rutingu. Kazda trasa w tablicy rutingu moze miec przypisane oznaczenie kolejki, do której maja byc kierowane pakiety kierowane według tej trasy. Filtr route pozwala na klasyfikacje pakietów ze wzgledu na te same parametry, które sa uzywane podczas wybierania dla niego trasy w tablicy rutingu – a wiec adresu docelowego (lub zródłowego, przy zastosowaniu rutingu rozszerzonego). Jego najwieksza zaleta jest szybkosc oraz mały narzut czasowy podczas klasyfikacji, wynikajace z duzej efektywnosci operacji na tablicy rutingu.

4.2 fw
Filtr firewall. Opiera sie o zaznaczanie pakietów przez firewall wbudowany w kernel. W przypadku ipchains do konfiguracji regułki filtra nalezy dodac opcje -m, której parametrem jest liczba stanowiaca oznaczenie pakietu. Jesli przetwarzany przez firewall pakiet pasuje do danej regułki, to zostaje on oznaczony podana liczba. Faktycznie oznaczenie polega na ustawieniu pola skb->priority w pakiecie na podana wartosc. Warto zaznaczyc, ze pole to jest takze ustawiane przez jadro w zaleznosci od TOS pakietu. Istotna jest interpretacja oznaczenia. Jest ono liczba 32–bitowa, której starsze 16 bitów okresla kolejke do której ma byc skierowany pakiet, a młodsze – klase w obrebie tej kolejki. Przykładowo, chcac skierowac pakiet do klasy 1:3 powinnismy uzyc parametru -m 0x10003. Filtr fw pozwala na klasyfikacje pakietów według wszystkich parametrów rozpoznawanych przez firewall. W odróznieniu od filtra route sa to wiec takze informacje z protokołów wyzszych niz TCP i UDP – numery portów, typy pakietów ICMP itp.

4.3 u32
Najbardziej złozony z filtrów dostepnych w Linuxie. Jest w całosci oparty o tablice haszujace, co zapewnia wydajnosc nawet przy bardzo złozonych zbiorach regułek. Posiada najwieksze mozliwosci jesli chodzi o wybór kryteriów, które musza spełniac klasyfikowane pakiety. Filtr u32 jest opisany w rozdziale 10, strona 20.

5 Elementarne algorytmy kolejkowania


Kernel Linuxa obsługuje nastepujace elementarne algorytmy kolejkowania:

5.1 FIFO
Kolejka FIFO (First In, First Out, nazywana takze drop-tail). Najczesciej stosowana, nie tylko zreszta w ruterach. Prosta kolejka pakietów, przesuwajacych sie do wyjscia. Limitowana wyłacznie przez wydajnosc interfejsu wyjsciowego. Jedynym jej parametrem jest wielkosc, mierzona w bajtach dla bfifo (byte FIFO) lub pakietach dla pfifo (packet FIFO).

5.2 TBF
Algorytm TBF (Token Bucket Filter) to prosta kolejka wypuszczajaca wyłacznie pakiety ponizej ustalonego administracyjne natezenia przepływu, z mozliwoscia buforowania chwilowych przeciazen.
Implementacja TBF posiada bufor (kubełek, bucket), do którego wpadaja zetony z natezeniem (token rate) okreslonym parametrem rate. Rozmiar kubełka (ilosc zetonów, które moze pomiescic) jest okreslany parametrem buffer.
Kazdy zeton wypuszcza z kolejki okreslona ilosc danych i równoczesnie z jej wysłaniem jest on usuwany z kubełka. W ten sposób mozliwe sa nastepujace sytuacje:
• Dane wchodza do TBF z natezeniem przepływu równym natezeniu przepływu zetonów. Wówczas kazda porcja danych ma swój odpowiadajacy zeton i przechodzi przez filtr.
• Dane wchodza do TBF z natezeniem przepływu mniejszym niz zetony. Poniewaz tylko czesc zetonów jest „zabierana” przez wychodzace dane, kubełek wypełnia sie niewykorzystanymi zetonami (ale nie moze ich byc wiecej niz buffer). Moga zostac one wykorzystane w przyszłosci, w przypadku chwilowego przeciazenia (burst).
• Jesli natezenie danych jest wieksze niz ustalone natezenie zetonów, to mamy do czynienia z przeciazeniem filtra. W tej sytuacji dane moga byc wysyłane dopóki nie zostana zuzyte wszystkie zetony, które mogły sie tam nagromadzic w okresie poprzedzajacym przeciazenie. Jesli w kubełku nie ma juz zetonów, pakiety sa kasowane.
Jak wynika z powyzszego opisu, parametr buffer okresla, jak długo TBF bedzie w stanie buforowac dane przekraczajace parametr rate w wypadku przeciazenia. Drugi istotny parametr to limit, okreslajacy wielkosc kolejki w bajtach.
Algorytm TBF znajduje powszechne zastosowanie do ograniczania pasma oraz regulowania natezenia przepływu danych w protokołach typu RSVP i innych, słuzacych do gwarantowania przydziału zasobów sieciowych (patrz RFC 2215 [4]).

5.3 PRIO
PRIO (Simple Priority Queueing) to prosta kolejka umozliwiajaca preferowanie okreslonych pakietów. Składa sie z kilku kolejek, z których zawsze najpierw obsługiwane sa te o wyzszym priorytecie. W razie przekroczenia limitu wielkosci kolejek, pierwsze kasowane sa pakiety z kolejki o najnizszym priorytecie. Kazda nizsza kolejka jest obsługiwana dopiero wówczas, gdy pakiety z wyzszych kolejek zostana wysłane. Implementacja linuksowa została zaprojektowana w dosc interesujacy sposób, a mianowicie priorytety pakietów sa obliczane na podstawie pola TOS (Type of Service) kazdego przetwarzanego pakietu. Oznacza to, ze kolejka PRIO automatycznie bedzie preferowac oznaczone w TOS jako interaktywne (telnet, SSH) nad danymi masowymi. To czyni ja bardzo przydatna szczególnie na wolnych łaczach lub słabych sprzetowo routerach, gdzie zastosowanie bardziej zaawansowanych technik albo nie ma sensu, albo nie jest mozliwe z powodu wymagan odnosnie precyzji zegara.

5.4 SFQ
SFQ (Stochastic Fairness Queueing) to prosta i posiadajaca niewielkie wymagania obliczeniowe odmiana algorytmu „sprawiedliwego kolejkowania” (fair queueing). Kolejka jest w tym algorytmie rozpatrywana jako składajaca sie z ciagów pakietów zwanych konwersacjami (conversations) lub strumieniami (flows). Do jednej konwersacji naleza pakiety posiadajace takie same adresy zródłowe i docelowe oraz protokół w nagłówku IP. Przykładowo, do samodzielnych konwersacji nalezec beda połaczenie TCP, ciagły strumien danych UDP (NFS, Quake) miedzy dwoma hostami itp. Kazda z konwersacji jest obsługiwana sprawiedliwie i cyklicznie (round-robin), to znaczy w kazdym przebiegu wysyłane jest po jednym pakiecie z kazdego ciagu. Konsekwencja jest równiez to, ze najszybciej obsługiwane sa konwersacje „krótkie”, czyli stanowiace małe obciazenie dle sieci. W przypadku przepełniania natomiast gubione sa pakiety z konca kolejki (stad tail-drop).
SFQ nie potrafi jednak odróznic danych interaktywnych od masowych. Jesli zachodzi taka potrzeba, selekcje nalezy przeprowadzic wczesniej, uzywajac SFQ jako algorytmu kolejkowania dla podklas CBQ przeznaczonych dla ruchu masowego. SFQ zapewnia tylko sprawdziedliwe współdzielenie łacza przez kilka aplikacji, zwieksza przewidywalnosc czasów wedrówki pakietów konwersacji o duzym natezeniu i zapobiega przejeciu całego pasma przez jedna aplikacje generujaca duzy ruch (link takeover). Parametrami SFQ sa: czestosc przeliczania funkcji haszujacej (perturb) oraz jednostka kolejkowania (quantum).
Ta ostatnia wartosc powinna byc wieksza lub równa MTU obowiazujacemu na danym interfejsie. Regularne przeliczanie funkcji haszujacej jest konieczne ze wzgledu na jej prostote, która moze powodowac kolizje czyli identyczne wyniki dla róznych konwersacji. Parametr ten podaje sie w sekundach i powinien byc uzalezniony od natezenia oraz charakterystyki ruchu – im wiecej podobnych konwersacji przechodzi przez łacze, tym czesciej powinna byc przeliczana funkcja haszujaca. W praktyce stosuje sie czasy w przedziale 5–20 sekund.

5.5 RED
RED (Random Early Detection) to algorytm majacy na celu unikanie przeciazen przez wykorzystanie mechanizmów istniejacych juz w protokole TCP. RED „przewiduje” wystapienie przeciazenia łacza i gubi pakiety, sygnalizujac tym samym nadawcy, ze powinien ograniczyc transmisje. W przypadku protokołu TCP jest to załozenie jak najbardziej poprawne, a po zakonczeniu przeciazenia TCP potrafi automatycznie powrócic do optymalnej predkosci wysyłania pakietów. W zwiazku z tym RED znajduje zastosowanie jako algorytm w podklasach CBQ, przeznaczonych dla ruchu TCP. Charakterystyczna cecha RED jest to, ze – w odróznieniu od pozostałych algorytmów – próbuje on zapobiegac przeciazeniu zanim ono wystapi, a nie tylko zminimalizowac jego skutki w czasie jego trwania. Pierwszym krokiem po przyjeciu nowego pakietu przez RED jest obliczenie sredniego rozmiaru kolejki (w bajtach) bedacego funkcja poprzedniej sredniej oraz obecnego rozmiaru. Na tej podstawie – oraz dwóch administracyjnie ustalonych parametrów min i max – RED oblicza prawdopodobienstwo z jakim pakiet powinien zostac odrzucony. Prawodpodobienstwo to rosnie wraz ze wzrostem nasycenia łacza, az do porzucenia pakietu. Algorytm RED jest opisany m. in. w RFC 2309 [1].

5.6 CBQ
CBQ (Class Based Queueing) jest algorytmem, stanowiacym podstawe do podziału przepustowosci łacza (link sharing) oraz szkielet pozwalajacy na wykorzystanie wszystkich wyzej opisanych algorytmów elementarnych. WCBQ ruch jest dzielony na kilka kolejek, zwanych dalej klasami, charakteryzujacych sie priorytetem oraz przydzielona przepustowoscia. Siła CBQ jest to, ze pakiety moga byc rozdzielane do kolejek–klas na podstawie dowolnych kryteriów za pomoca opisanych wczesniej filtrów. Natomiast zamiast domyslnie ustawianych kolejek FIFO, składowymi CBQ moga byc dowolne z równiez opisanych wyzej algorytmów elemetarnych. Cechy te pozwalaja na osiagniecie nastepujacych efektów:
• Podział sumarycznej przepustowosci łacza na kilka czesci (klas), przydzielonych według potrzeb okreslonym rodzajom usług, adresom IP itp.
• Przesyłanie pakietów z róznym pierwszenstwem w zaleznosci od tych samych parametrów.
• Przydzielenie odpowiednim rodzajom ruchu własciwych algorytmów kolejkowania, np. dla ruchu masowego – algorytmu SFQ, dla ruchu TCP – algorytmu RED itp.
Przepustowosc 10 Mbit została podzielona na dwie czesci (klasy CBQ). Pierwszej z nich przydzielilismy 1 Mbit oraz wysoki priorytet (małe opóznienie w razie przeciazenia). Przez te klase przesyłane sa protokoły interaktywne typu TELNET lub SSH, które transportuja niewielkie ilosci danych, ale wymagaja bardzo małych opóznien na łaczu. Druga klasa – przeznaczona dla danych masowych – otrzymała 9 Mbit pasma, ale nizszy priorytet. W ten sposób, nawet jesli danym łaczem jeden uzytkownik bedzie sciagał przez FTP duzy plik, to drugi, wykorzystujacy w tym czasie przez TELNET, powienien móc dalej pracowac. Bez podziału pasma płynace z duzym natezeniem dane protokołu FTP prawdopodobnie nasyciłyby łacze w 100% i praktycznie uniemozliwiły prace uzytkownikowi TELNETa. Warto zaznaczyc, ze powyzej ruch do klas jest rozdzielany według protokołów. Mozliwe jest rozdzielanie (klasyfikacja) pakietów według praktycznie dowolnych kryteriów – takich jak adresy IP (przydział pasma dla okreslonych hostów), pole TOS (pozwala wykorzystac istniejacy mechanizm okreslania pierwszenstwa pakietów) i inne. Dodatkowo, CBQ umozliwia optymalne wykorzystanie łacza przez „pozyczanie” pasma przez aktualnie obciazona klase od innej, nieobciazonej. Zachowanie to mozna kontrolowac, zabraniajac okreslonej klasie pozyczania pasma (parametr bounded) lub uniemozliwiajac pozyczanie z okreslonej klasy (parametr isolated). Jak juz napisalismy, klasy sa kanałami logicznymi do których rozdzielany jest ruch wchodzacy do złozonej kolejki. Kazda klasa posiada przyporzadkowany elementarny algorytm kolejkowania, który odpowiada za wypuszczanie danych znajdujacych sie w danej klasie.
Klasy CBQ charakteryzuje kilka podstawowych parametrów, które sa ponizej opisane w składni stosowanej przez polecenie tc:
• parent – identyfikator kolejki macierzystej, do której dana klasa przynalezy. Podawany w postaci KOLEJKA:0.
• classid – identyfikator danej klasy podawany w postaci KOLEJKA:KLASA, gdzie KOLEJKA jest numerem kolejki do której dana klasa przynalezy, a KLASA – numerem deklarowanej klasy. Poniewaz kolejka macierzysta jest i tak podawana w parametrze parent, wystarczy podac sam numer klasy, np. classid :3. • prio – priorytet danej klasy, podawany jako liczba całkowita z przedziału 1. . . 10. Im mniejsza wartosc, tym wieksze pierwszenstwo bedzie miała dana klasa. Priorytet pozwala podzielic klasy według wzrastajacego pierwszenstwa w obsłudze danych przekazywanych przez dana klase. Przykładowo, klasom przenoszacym ruch interaktywny (TELNET, SSH) mozna ustawic wiekszy priorytet niz klasom z ruchem masowym (FTP). Oczywiscie, liczbowe wartosci priorytetów dla klas interaktywnych powinny byc mniejsze niz dla klas masowych.
• bandwidth – sumaryczna przepustowosc interfejsu, w którym konfigurowane sa klasy. Podawana jako liczba z przyrostkiem okreslajacym jednostke – np. dla Ethernetu 10Base-T 10mbit. Inne dopuszczalne jednostki to bps, kbps (odpowiednio bajty oraz kilobajty na sekunde, kbit oraz mbit (kilobity i megabity na sekunde).
• rate – przepustowosc pasma przydzielonego danej klasie, stanowiaca ułamek przepustowosci interfejsu. Jednostki sa identyczne jak w parametrze bandwidth. 11 Przykładowo, jesli wybranej klasie skonfigurowanej na interfejsie typu Ethernet chcemy przydzielic 40% pasma, parametr ten bedzie miał postac rate 4mbit.
• weight – wzgledna waga danej klasy, która dla wszystkich klas powinna byc wartoscia proporcjonalna do rate. W praktyce mozna przyjmowac wartosci dziesieciokrotnie mniejsze niz rate, ale parametr ten nie jest niezbedny i mozna zawsze uzywac wartosci 1.
• avpkt – srednia wielkosc pakietów przesyłanych w tej klasie, w bajtach. Wielkosc te mozna wyznaczyc eksperymentalnie, ale przewaznie bedzie ona stanowic 50-60% MTU danego interfejsu.
• mput – minimalna wielkosc pakietów, które beda przesyłane przez dana klase, w bajtach. Mniejsze pakiety nie beda podlegały klasyfikacji.
• allot – suma MTU oraz nagłówka warstwy łacza danego interfejsu w bajtach. Przykładowo, dla zwykłego Ethernetu (10Base-T) wartosc ta wynosi 1514 (1500 + 14 nagłówka Ethernet), a dla połaczenia PPP z MTU 576 – 580 (576 + 4 bajty nagłówka PPP).
• maxburst – parametr okreslajacy dopuszczalne chwilowe przeciazenie danej klasy (burstiness). Parametr ten jest scisle zwiazany z samym algorytmem CBQ i szczegółowo opisany w literaturze na ten temat [2], [3].
• est – dwa parametry miernika natezenia ruchu (rate estimator) pracujacego w danej klasie, podawane w postaci est X Y. Miernik okresla srednie natezenie przepływu danych w danej klasie przez okres X sekund ze stała czasowa Y sekund. W praktyce typowymi wartosciami jest 1 i 8 – est 1sec 8sec.

6 Rozdzielczosc zegara


Wszystkie wymienione powyzej algorytmy w znaczym stopniu polegaja na dokładnym odmierzaniu czasu przez jadro, od czego bezposrednio zaleza takie parametry jak maksymalne i minimalne natezenia przepływu mozliwe do obsłuzenia przez kolejki, dokładnosc przycinania pasma itp. Linux moze wykorzystywac trzy zródła czasu, konfigurowalne za pomoca deklaracji na poczatku pliku /usr/src/linux/include/net/ pkt sched.h:
• PSCHED_GETTIMEOFDAY – najprostsza metoda, opierajaca sie o wywołanie systemowe gettimeofday, przy tym najmniej doskonała. Nie zapewnia zbyt duzej dokładnosci oraz rozdzielczosci zegara.
• PSCHED_JIFFIES – zródłem taktu zegara sa jiffies, czyli podstawowe jednostki odmierzania czasu uzywane przez jadro. W praktyce wystarczajace do wiekszosci zastosowan, nie pozwalaja na osiagniecie zbyt duzej dokładnosci w przycinaniu pasma.
• PSCHED_CPU – zródłem taktu jest sam procesor, co daje najwieksza dokładnosc i rozdzielczosc zegara, ale wymaga wydajnego procesora – Alpha lub Pentium posiadajace instrukcje RTDSC. W chwili obecnej ma ja wiekszosc stosowanych procesorów, co mozna dodatkowo sprawdzic w /proc/cpuinfo, powinna byc ustawiona flaga tsc).

7 Proste przykłady zastosowania kolejek



7.1 Domyslne ustawienia
Przed eksperymentami z QoS warto zobaczyc jakie sa domyslne ustawienia interfejsów tworzonych przez jadro. Wykorzystamy do tego celu polecenie ip link show dev DEV, gdzie DEV jest nazwa interfejsu. Ponizej wyniki z kilku wybranych interfejsów naszego rutera:
2: eth0: mtu 1500 qdisc pfifo_fast qlen 100
30229: ppp1: mtu 1500 qdisc pfifo_fast qlen 10
30969: ppp11: mtu 576 qdisc pfifo_fast qlen 10
Jak widac, wszystkie interfejsy uzywaja algorytmu packet FIFO, rózniac sie przy tym wielkoscia MTU (wartosc ustawiana administracyjnie, domyslnie jest to 1500 bajtów dla Ethernetu oraz połaczen PPP) oraz długoscia kolejki. Ten ostatni parametr wynosi 100 pakietów dla szybkiego Ethernetu, oraz 10 dla relatywnie duzo wolniejszych łacz PPP.

7.2 Prosta kolejka PRIO
Najprostsza, prawie całkowicie automatycznie konfigurowana kolejka PRIO. Ponizszy przykład stworzy PRIO składajace sie z trzech kolejek:
$ tc qdisc add dev ppp0 root prio
$ tc -s qdisc
qdisc prio 8017: dev ppp0 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
Sent 7403354 bytes 82060 pkts (dropped 96, overlimits 0)
Parametr priomap oznacza jakie wartosci pola TOS sa przypisane do której z trzech kolejek oznaczonych 0 − 2. Przyporzadkowanie to odbywa sie na podstawie 16-to pozycyjnej tablicy, mapujacej wartosci TOS na numery kolejek. Tablica ta jest zaimplementowana na stałe (mozna ja znalezc w zródłach kernela), ale mozna układac własne mapowanie korzystajac własnie z parametru priomap.

7.3 Ograniczenie pasma (TBF)
Najprostszy przykład zastosowania filtra token bucket do ograniczenia przepustowosci interfejsu do okreslonej wartosci. W opisywanym przypadku ograniczenie do 128 kbit nałozymy na interfejs eth0.
$ tc qdisc add dev eth0 root handle 1: tbf buffer 10KB limit 10KB \
rate 128kbit
Parametry TBF zostały omówione juz wczesniej. Parametr root oznacza, ze dodawana kolejka jest główna dla tego interfejsu, z identyfikatorem 1:. Wykorzystajmy teraz polecenie tc do wyswietlenia parametrów kolejki obecnie obowiazujacej na tym interfejsie:
$ tc -s qdisc
qdisc tbf 1: dev eth0 rate 128Kbit burst 10Kb lat 0us
Sent 26386 bytes 180 pkts (dropped 0, overlimits 0)
Teraz, intensywnie obciazajac interfejs ruchem wychodzacym (sic!) mozemy obserwowac TBF w akcji:
$ tc -s qdisc
qdisc tbf 1: dev eth0 rate 128Kbit burst 10Kb lat 0us
Sent 621683 bytes 621 pkts (dropped 19, overlimits 2014)
backlog 7722b 7p
Powyzsze dane zostały wyswietlone w momencie, gdy łacze było nadal obciazone. Widac, ze 2014 pakietów przekroczyło narzucony limit 128 Kbit, ale do tej pory skasowanych zostało tylko 19 z nich. Reszta z nich została zbuforowana przez czas trwania przeciazenia (w tym wypadku krótkotrwałego). Pakiety aktualnie przechowywane w buforze pokazuje parametr backlog. Do obciazania łacza uzywałem programu ttcp [5], który działa w trybie klient–serwer i wyswietla zmierzona srednia przepustowosc łacza. W tym wypadku ttcp pokazało wynik 113.42 Kbit, co mniej wiecej odpowiada ustawionemu limitowi. Na koniec pozostaje juz tylko posprzatac po sobie poleceniem tc qdisc del root dev eth0. Spowoduje to usuniecie modułu TBF z interfejsu i przywrócenie domyslnego FIFO.

7.4 Automatyczne współdzielenie łacza (SFQ)
Poprzedni przykład narzucał na interfejs sztuczny limit przepustowosci. W tym wypadku cel bedzie dokładnie przeciwny – poprawienie pracy łacza przez wykorzystanie algorytmu SFQ, opisanego szczegółowo wczesniej. Tak jak poprzednio, SFQ bedzie głównym algorytmem kolejkujacym danego interfejsu
14
$ tc qdisc add dev eth0 root handle 1: sfq perturb 5 quantum 1500b
$ tc -s qdisc
qdisc sfq 1: dev eth0 quantum 1500b perturb 5sec
Sent 11498 bytes 74 pkts (dropped 0, overlimits 0)
Tym razem uzyskanie zauwazalnych wyników byłoby duzo trudniejsze, bo działanie SFQ polega na wyrównywaniu wykorzystania łacza przez kilka równoległych połaczen, a nie na przykład preferowanie jednego z nich. SFQ bardzo dobrze nadaje sie na algorytm ogólnego przeznaczenia, poprawiajacy współdzielenie łacza przez wielu uzytkowników lub aplikacji i zapobiegajacy przejeciu pasma przez jedna transmisje. Dodatkowa zaleta jest prosta konfiguracja, nie wymagajaca dokładnego zaplanowania podziału pasma miedzy poszczególnych uzytkowników.

8 Podział łacza na klasy za pomoca CBQ


W wielu przypadkach zachodzi potrzeba dokładniejszego okreslenia, w jaki sposób ma byc podzielona sumaryczna przepustowosc łacza, jakie usługi potrzebuja zarezerwowanej czesci pasma, które z nim maja byc obsługiwane z wyzszym, a które z nizszym pierwszenstwem. W tym wypadku automatyczne segregowanie ruchu zapewniane przez SFQ nie wystarcza i konieczne jest zbudowanie struktury klas CBQ. Tym razem przykład dotyczy łacza asynchronicznego PPP, o przepustowosci 115.2 kbit/sek i MTU ustawionym na 1500 bajtów. Parametry ponizszych polecen zostały dobrane eksperymentalnie, na podstawie eksperymentów na działajacym łaczu. W pierwszym kroku tworzymy złozona kolejke o identyfikatorze 1:0, na interfejsie ppp0. Srednia wielkosc pakietu avpkt to 1000 bajtów. Na tym poziomie wielkosc ta nie ma az takiego znaczenia, wazne jest by była mniejsza od MTU łacza. $ tc qdisc add dev ppp0 root handle 1:0 cbq bandwidth 115200 avpkt \ 1000 mpu 64 Tworzymy klase 1:1 dla ruchu interaktywnego i wymagajacego małych opóznien. Klasie tej przydzielamy 28700 bit/sek przepustowosci oraz wysoki priorytet 2. Ustawiamy jej takze troche wieksza tolerancje na chwilowe przeciazenia (maxburst) oraz mniejszy sredni pakiet (avpkt). Do klasy tej równiez podpinamy algorytm SFQ.
$ tc class add dev ppp0 parent 1:0 classid 1:1 est 2sec 16sec cbq \
bandwidth 115200 rate 28700 allot 1504b weight 1 prio 2 \
maxburst 10 avpkt 512
$ tc qdisc add dev ppp0 parent 1:1 sfq quantum 1500b perturb 5
Tworzymy klase 1:2 przeznaczona dla ruchu masowego TCP, przydzielajac jej 69110 bit/sek z sumarycznej przepustowosci łacza oraz priorytet 6 – czyli dosc niski. Parametr avpkt jest ustawiony na 1000 bajtów, poniewaz w ruchu masowym dominowac beda prawdopodobnie wieksze pakiety. Do klasy tej podpinamy algorytm RED, zaprojektowany do protokołu TCP.
$ tc class add dev ppp0 parent 1:0 classid 1:2 est 1sec 8sec cbq \
bandwidth 115200 rate 69110 allot 1504b weight 1 prio 6 \
maxburst 5 avpkt 1000
$ tc qdisc add dev ppp0 parent 1:2 red limit 20KB min 5KB max 15KB \
burst 20 avpkt 1000 bandwidth 115200 probability 0.4
Tworzymy klase 1:3, do której trafiac maja pakiety z protokołów innych niz TCP, ale nie przenoszace usług interaktywnych. Przydzielamy jej pasmo 17270 bit/sek oraz priorytet 7 – jeszcze nizszy niz dla klasy 1:1. Istotny jest parametr defmap, stanowiacy maske dla priorytetów logicznych pakietów, ustawianych przez jadro.Wtym wypadku oznacza on, ze dana klasa jest klasa domyslna i do niej trafia pakiety nie skierowane przez filtry do innych klas. Do klasy 1:3 podpinamy algorytm SFQ.
$ tc class add dev ppp0 parent 1:0 classid 1:3 est 1sec 8sec cbq \
bandwidth 115200 rate 17270 allot 1504b weight 1 prio 7 \
maxburst 5 avpkt 1000 defmap 3f
$ tc qdisc add dev ppp0 parent 1:3 sfq quantum 1500b perturb 5
Podsumowujac, mamy teraz nastepujace klasy:
1:3
interaktywny
algorytm SFQ
28700 bps 1:1
masowy TCP
69110 bps
algorytm RED
1:2
masowy nie-TCP
algorytm SFQ
17270 bps
Od tej pory ruch wychodzacy przez dany interfejs jest obsługiwany przez algorytm CBQ, ale wykorzystywana jest wyłaczenia jedna klasa, oznaczona jako domyslna – czyli 1:3. Zeby wykorzystac pozostałe klasy, musimy skierowac do nich pakiety wyselekcjonowane za pomoca filtrów. Ponizej przedstawimy trzy – funkcjonalnie identyczne – konfiguracje wykonane za pomoca róznych filtrów. Konfiguracja jest nastepujaca: 1:1 Klasa przeznaczona dla ruchu interaktywnego. Przydzielamy do niej protokoły TELNET, SSH oraz wszystkie posiadajace pole TOS ustawione na 0x10 (małe opóznienie). Dodatkowo do tej klasy przydzielamy ruch wysyłany do sieci 192.168.1.0/24 – dla wiekszego realizmu mozna przyjac, ze jest to podsiec, w której znajduja sie komputery dyrekcji, a tak na prawde chodzi tylko o okazje do pokazania mozliwosci filtra route. 1:2 Klasa przeznaczona dla ruchu masowego TCP. Do tej klasy przydzielamy cały ruch TCP/IP, który nie został zakwalifikowany do klasy interaktywnej. 1:3 Klasa przeznaczona dla ruchu masowego innego niz TCP. Do tej klasy nic specjalnie nie przydzielamy, bo automatycznie trafi do niej wszystko co nie zostanie zaklasyfikowane do klas 1:1 i 1:3.

8.1 Klasyfikacja filtrem fw
Do konfiguracji filtra fw słuzy poleceni ipchains. Tworzymy standardowe regułki filtra pakietów ipchains, z ta róznica ze do kazdej z nich dodajemy parametr -m 0x1000x okreslajacy klase do której ma byc skierowany pasujacy pakiet. Cyferka x oznacza numer klasy – 1:x. Zgodnie z powyzszymi załozeniami, powinnismy stworzyc nastepujace regułki:
# 1:1
$ ipchains -A output -p tcp -b -s 0.0.0.0/0 telnet -m 0x10001 -j ACCEP
T
$ ipchains -A output -p tcp -b -s 0.0.0.0/0 22 -m 0x10001 -j ACCEPT
$ ipchains -A output -p ip -d 192.168.1.0/24 -m 0x10001 -j ACCEPT
# 1:2
$ ipchains -A output -p tcp -m 0x10002 -j ACCEPT
$ tc filter add dev ppp0 parent 1:0 protocol ip prio 90 fw
Filtr ipchains nie pozwala na dopasowywanie pakietów po polu TOS, wiec ten parametr w tym wypadku pomijamy. Opcji -b uzywamy dla uproszczenia konfiguracji – zamiast pisac regułke dwukrotnie, dla pakietów pochodzacych z portu TELNET i do niego skierowanych.

8.2 Klasyfikacja filtrem router
W przypadku filtra route nie ma w ogóle mowy o rozdzielaniu ruchu według protokołów warstwy transportowej (TCP, UDP). Filtr ten umozliwia klasyfikacje pakietów według parametrów nagłówka IP, takich jak adres zródłowy, adres docelowy oraz pole TOS. Tym razem pominiemy wiec klasyfikacje protokołów TELNET i SSH, klasyfikujac pakiety przeznaczone dla podsieci 192.168.1.0/24 oraz według pola TOS:
$ ip rule add to 192.168.1/24 realms dyrekcja
$ ip rule add tos 0x10 realms dyrekcja
$ tc filter add dev ppp0 parent 1:0 protocol ip prio 100 route \
to dyrekcja flowid 1:1
Konfiguracja filtra route zmieniła sie od wczesnych wersji jader 2.2 o tyle, ze przyporzadkowanie numeru klasy nie odbywa sie od razu na poziomie regułek ip rule (jak było kiedys). Zamiast tego w regułkach tych okreslamy królestwo (realm), do którego przynalezy okreslony ruch. Przyporzadkowanie klasy do królestwa odbywa sie na etapie konfiguracji samego filtra (ostatnia linijka). Warto zaznaczyc, ze mozliwe jest połaczenie filtra fw z filtrem route w taki sposób, ze najpierw filtr pakietów znakuje pakiety a nastepnie filtr route przyporzadkowuje pakiety z okreslonym oznaczeniem do poszczególnych królestw (parametr fwmark polecenia ip rule). Z drugiej strony, bezposrednie wykorzystanie filtra fw do tego celu jest prostsze.

8.3 Klasyfikacja filtrem u32
Filtr u32 łaczy w sobie funkcje filtrów route i fw, umozliwiajac klasyfikacje pakietów według wiekszosci informacji, jakie tylko da sie wyciagnac z nagłówka pakietu IP, TCP oraz UDP. Konfiguracja tego filtra dla naszej przykładowej kolejki CBQ jest pozbawiona ograniczen, które posiadały poprzednie filtry.
Na poczatku inicjalizujemy filtr z szesnastoma pozycjami w tablicy haszujacej:
$ tc filter add dev ppp0 parent 1:0 prio 10 protocol ip u32 divisor 16
Dodajemy regułke dla pakietów IP posiadajacych pole TOS ustawione na 0x10
(minializacja opóznienia):
$ tc filter add dev ppp0 parent 1:0 prio 10 u32 \
match ip tos 0x10 0xff \
flowid 1:1
Dodajemy regułki klasyfikujace pakiety TCP nalezace do protokołów TELNET
(port zródłowy lub docelowy 0x17) oraz SSH (port 0x16):
$ tc filter add dev ppp0 parent 1:0 prio 10 u32 \
match tcp dst 0x17 0xffff \
flowid 1:1
$ tc filter add dev ppp0 parent 1:0 prio 10 u32 \
match tcp src 0x17 0xffff \
flowid 1:1
$ tc filter add dev ppp0 parent 1:0 prio 10 u32 \
match tcp dst 0x16 0xffff \
flowid 1:1
$ tc filter add dev ppp0 parent 1:0 prio 10 u32 \
match tcp src 0x16 0xffff \
flowid 1:1
Dodajemy regułke klasyfikujaca pakiety IP skierowane do sieci 192.168.1.0/24:
$ tc filter add dev ppp0 parent 1:0 prio 10 u32 \
match ip dst 192.168.1/24 \
flowid 1:1
Na koncu dodajemy regułke klasyfikujaca ruch IP, który nie został dopasowany do poprzednich regułek:
$ tc filter add dev ppp0 parent 1:0 prio 10 u32 \
match ip protocol 0x6 0xff \
flowid 1:2
Konfiguracja jest, jak widac, bardziej skomplikowana niz dla poprzednio omawianych filtrów, ale wynika to z przyjetej na etapie projektowania elastycznosci filtra u32.

9 Dodatki



9.1 Jednostki przepustowosci łacz
Wewnetrzna jednostka przepustowosci łacza oraz natezenia ruchu, stosowana przez algorytmy kolejkowania w Linuxie jest bps – bajt na sekunde. Program tc umozliwia jednak podawanie wartosci w innych, powszechnie stosowanych jednostkach, wymienionych ponizej. Wszystkie one sa przeliczane na bps zgodnie z podanym współczynnikiem:
Jednostka Pełna nazwa Przelicznik do bps
(brak) bity na sekunde 1
bps bajty na sekunde 1
kbps kilobajty na sekunde 1024
mbps megabajty na sekunde 1024 • 1024
kbit kilobity na sekunde 1024 • 1
mbit megabity na sekunde 1024 • 1024 • 1
Do wyswietlania tych wartosci, program tc wykorzystuje natomiast wyłaczenie jednostki mbit, kbit oraz bps wybierane dla róznych przedziałów przepustowosci. Przykładowo, w ponizszym przykładzie predkosc ustawiamy w bitach na sekunde (57600 bit/sek), ale wyswietlona zostanie w bajtach na sekunde (7200 bajtów/sek):
$ tc qdisc add dev eth0 root handle 1: tbf limit 10K burst 10K rate
57600
$ tc -s qdisc
qdisc tbf 1: rate 7200bps burst 10Kb lat 1us
Sent 145671 bytes 423 pkts (dropped 21, overlimits 2392)
backlog 4732b 14p

10 Filtr u32


Filtr u32 w najprostszej wersji jest lista, zawierajaca rekordy składajace sie z dwóch pól: selektora i akcji. Selektory, opisane ponizej sa dopasowywane kolejno do aktualnie przetwarzanego pakietu IP. Pasujacy selektor pociaga za soba wykonanie przypisanej do niego akcji. Najprostszym przypadkiem akcji jest skierowanie biezacego pakietu do okreslonej klasy CBQ.
Polecenie tc filter słuzace do konfiguracji filtra u32 składa sie z trzech czesci: specyfikacji filtra, selektora oraz akcji. We wszystkich zamieszczonych w tym dokumencie przykładów uzycia filtra u32 czesci te znajdowały sie w osobnych linijkach. Podstawowa specyfikacja filtra wyglada nastepujaco:
tc filter add dev INTERFEJS [ protocol PROTO ]
[ (preference|priority) PRIO ]
[ parent CBQ ]
Pole protocol okresla protokół, który bedzie przetwarzany przez filtr. Teoretycznie moze to byc kazdy protokół warstwy sieci, obsługiwany przez Linuxa, w praktyce stosuje sie jedynie protocol ip. Opcja preference okresla numer kolejny – a tym samym pierwszenstwo – filtra, jesli zdefiniowano ich kilka. Opcja parent okresla, do jakiej kolejki CBQ odnosi sie dany filtr. Jej parametrem jest identyfikator danej kolejki. Powyzej opisane parametry odnosza sie do wszystkich rodzajów filtrów, nie tylko u32.

10.1 Selektor u32
Selektor u32 zawiera informacje o tym, jakie pola w nagłówkach pakietów, o okreslonej długosci i przesunieciu, maja pasowac do podanego wzorca. Najprosciej unaocznic to na przykładzie. Spójrzmy na wynik polecenia tc filter ls dev ppp0 wydany dla juz skonfigurowanego, dosc skomplikowanego filtra:
filter parent 1: protocol ip pref 10 u32 fh 800::800 order 2048 key ht
800 bkt 0 flowid 1:3
match 00100000/00ff0000 at 0
Pierwsza z nich pasuje do pakietów IP, które w drugim bajcie maja liczbe 0x10, przy czym porównywane jest pole o długosci jednego bajta (0xff). Drugi bajt pakietu IP to pole TOS. Jest to wiec dokładny odpowiednik naszej regułki match ip tos 0x10 0xff przetworzony na wewnetrzny format filtra u32. Parametr at okresla przesuniecie wzgledem poczatku pakietu, wiec w tym wypadku wypadło na drugi bajt.
Przyjrzyjmy sie kolejnej regułce:
filter parent 1: protocol ip pref 10 u32 fh 800::803 order 2051 key ht
800 bkt 0 flowid 1:3
match 00000016/0000ffff at nexthdr+0
Opcja nexthdr oznacza kolejny nagłówek, enkapsulowany w przetwarzanym pakiecie IP. Tym razem równiez zaczynamy liczenie od poczatku pakietu (+0). Dopasowanie ma nastapic w drugim, 32-bitowym słowie nagłówka. W protokole TCP i UDP jest to pole zawierajace numer portu przeznaczenia pakietu. Poniewaz w obowiazujacym w Internecie formatem jest kolejnosc big--endian (starsze bity na poczatku), liczbe te nalezy czytac jako 0x0016, czyli 22 decymalnie. Regułka ta bedzie zatem pasowac do pakietów protokołu SSH (przesyłanych po SSH) oraz pakietów UDP wysyłanych do portu 22 (ten port UDP nie jest na razie obsadzony przez zadna popularna usługe). Dokładne wyjasnienie tego problemu znajduje sie ponizej, w opisie parametrów konfiguracyjnych filtra u32.
Ostatnia regułka odnosi sie znowu do samego nagłówka IP:
filter parent 1: protocol ip pref 10 u32 fh 800::807 order 2055 key ht
800 bkt 0 flowid 1:4
match c0a80100/ffffff00 at 16
Widzimy tutaj dopasowanie trzech bajtów, poczawszy od 16-tego bajtu nagłówka. Jest to pole zawierajace adres przeznaczenia pakietu IP. Jest to nasza poprzednia regułka klasyfikujaca pakiety IP po adresie – match ip dst 192.168.1/24.

10.2 Parametry ogólne
Parametry ogólne definiuja wzorzec, maske oraz pozycje, na której maja byc one dopasowywane do zawartosci datagramu IP. Składnia selektora u32 jest dla parametrów ogólnych nastepujaca:
match [ u32 | u16 | u8 ] WZÓR MASKA [ at OFF | nexthdr+OFF] Jeden z selektorów u32, u16 i u8 okresla długosc wzorca (odpowiedni 32, 16 i 8 bitów). Po tym nastepuja WZÓR oraz MASKA o długosci okreslonej przez selektor. Parametr at OFF oznacza przesuniecie w bajtach wzgledem poczatku pakietu, a nexthdr+OFF – analogiczne przesuniecie wzgledem poczatku pakietu wyzszej warstwy enkapsulowanego w przetwarzanym datagramie.
Przykłady:
$ tc filter add dev ppp14 parent 1:0 prio 10 u32 \
match u8 64 0xff at 8 \
flowid 1:4
Pakiet pasuje do powyzszej regułki, jesli jego czas zycia (TTL) wynosi 64. TTL
jest polem zaczynajacym sie po 8 bajcie nagłowka IP.
$ tc filter add dev ppp14 parent 1:0 prio 10 u32 \
match u8 0x10 0xff at nexthdr+13
protocol tcp
flowid 1:3
Ta z kolei regułka bedzie pasowała tylko do pakietów TCP z ustawionym bitem ACK. Komentarza wymaga pierwszy z uzytych selektorów – bit ACK jest drugim najstarszym bitem (0x10) w 14-tym bajcie nagłówka TCP (at nexthdr+13). Gdybysmy lubili utrudniac sobie zycie, zamiast prostego protocol tcp moglibysmy na przykład napisac match u8 0x06 0xff at 9, bo 6 jest numerem protokołu TCP, a numer ten jest umieszczony w nagłówku IP w 10-tym bajcie.

10.3 Parametry szczegółowe
Ponizsze parametry pozwalaja na tworzenie regułek filtra bez koniecznosci podawania w kazdej regułce wielkosci pola oraz pozycji w pakiecie. Ułatwia to konstruowanie filtrów i poprawia ich czytelnosc.
Selektor
protokołu
Selektor pola Parametrya Opis
src prefix/32 adres zródłowy pakietu
dst prefix/32 adres docelowy pakietu
tos
dsfield tos u8 pole TOS
precedence
ihl ihl u8 długosc nagłówka pakietu
protocol prot u8 numer protokołu enkapsulowanego
match ip nofrag nie jest fragmentowany
firstfrag zawiera pierwszy fragment pakietu
df ustawiona flaga „nie fragmentowac”
mf ustawiona flaga „wiecej fragmentów”
sport port u16 port zródłowy prot. wyzszej warstwy
dport port u16 port docelowy prot. wyzszej warstwy
icmp\_type typ u8 typ komunikatu ICMP
icmp\_code kod u8 kod komunikatu ICMP
src prefix/128 adres zródłowy pakietu
match ip6b dst prefix/128 adres docelowy pakietu
flowlabel flow u32 identyfikator przepływu IPv6
udp, tcp src src u16 port zródłowy
dst dst u16 port docelowy
icmp type typ u8 typ komunikatu ICMP
code kod u8 kod komunikatu ICMP
aParametry podajemy w postaci liczb dziesietnych, szesnastkowych lub adresów IPv4 i IPv6,
tam gdzie to jest wymagane. Jesli selektor przyjmuje dwa parametry, to pierwszy z nich okresla
wzorzec, a drugi maske o podanej długosci w bitach. Długosc wzorca musi byc taka sama jak
maski.
bPozostałe parametry sa identyczne jak dla IPv4: priority, protocol, dport, sport,
icmp type, icmp code
Przykład:
$ tc filter add dev ppp0 parent 1:0 prio 10 u32 \
match ip tos 0x10 0xff \
flowid 1:4
Powyzsza regułka pasuje do pakietów, które maja pole TOS ustawione na 0x10. Pole TOS zaczyna sie po pierwszym bajcie nagłówka IP i ma wielkosc jednego bajtu, wiec za pomoca parametrów ogólnych mozna te regułke zapisac tak:
$ tc filter add dev ppp0 parent 1:0 prio 10 u32 \
match u8 0x10 0xff at 1
flowid 1:4
Trzeba pamietac, ze parametry szczegółowe sa zawsze tłumaczone na parametry ogólne, i w takiej postaci przechowywane w jadrze. Oznacza to ni mniej ni wiecej to, ze parametry tcp src oraz udp src sa jednoznaczne, co wynika z faktu, ze zarówno w nagłówku TCP jak i UDP numer portu zródłowego jest 16–bitowy i znajduje sie na poczatku pakietu. Jak uniknac takiej dwuznacznosci? Filtr u32 moze posiadac kilka selektorów, połaczonych w domysle logicznym „i”:
tc filter add dev ppp0 parent 1:0 prio 10 u32 \
match tcp dst 22 0xffff \
match ip protocol 0x6 0xff \
flowid 1:2

11 Inne implementacje


Linuxowa implementacja algorytmów QoS nie jest, jak sie łatwo domyslic, jedyna w swiecie ruterów. Wiele innych systemów posiada zaimplementowane rózne algorytmy kolejkujace oraz mechanizmy QoS.
Cisco IOS posiada implementacje algorytmów WFQ (Weighted Fair Queueing), PQ (Priority Queueing), WRED (Weighted Random Early Detection) oraz CBQ, przy czym to ostatnie okreslane jest jako custom queueing. IOS posiada takze mozliwosc przycinania pasma (traffic-shaping) dostepnego dla danych, pasujacych do okreslonych regułek [9].
Dla rodziny systemów BSD (FreeBSD, OpenBSD oraz NetBSD) jest dostepny pakiet ALTQ [10], zawierajacy implementacje algorytmów CBQ, RED, WFQ i innych. Na stronach obu wymienionych implementacji mozna znalezc bardzo duzo ogólnych informacji na temat działania algorytmów QoS, przydatnych takze dla uzytkowników Linuxa.