Ruter - Linux 2.4 FIREWALL, KONTROLA PRZEPŁ YWU, ZLICZANIE RUCHU wersja dokumentu 0.9 Dubas Bartłomiej (dubcio@hoga.pl) AGH Kraków - Informatyka IV Administracja Systemami Komputerowymi 2002
O PRAWACH AUTORSKICH Niniejsze opracowanie powstało w głównej mierze w oparciu o materiał Kształtowanie Ruchu i Zaawansowany Ruting HOWTO w tłumaczeniu Łukasza Bromirskiego. Wykorzystano również inne dokumenty i opracowania o czym mowa jest w Bibliografi na końcu tego opracowania. Nie jest zabronione rozpowszechnianie tego dokumentu, z wyłączeniem sytuacji, w których naruszało by to w jakikolwiek sposób prawa autorskie opracowań źródłowych. Zabronione jest również czerpanie jakichkolwiek korzyści majątkowych z tytułu rozpowszechniania niniejszego opracowania. Grafika wykorzystana w dokumencie pochodzi ze strony www.wiretree.com. Bartłomiej Dubas
Spis Treści Spis Treści...1 Tytułem Wstępu...4 IP i TC - nowe narzędzie konfiguracji...5 Narzędzie IP...5 Narzędzie TC...6 Dyscypliny kolejkowania qdisc...6 Klasy class...7 Terminologia...8 Dyscypliny kolejkowania...10 Proste, bezklasowe dyscypliny kolejkowania...10 Kolejka pfifo_fast...10 Parametry kolejki...10 Opis pola ToS...11 TBF Tocken Bucket Filter...11 Parametry kolejki...12 Przykładowa konfiguracja...12 SFQ Stochastic Fairness Queueing...13 Parametry kolejki...13 Dyscypliny kolejkowania z klasami...14 HTB Hierarchical Token Bucket...15 Dzielenie połączenia...16 Wypożyczanie pasma...16 Opróżnianie kolejki...17 Priorytety ruchu...17 Parametry kolejki...17 Kolejka PRIO...17 Parametry kolejki...18 1
Przykłady użycia...18 CBQ Class Based Queue...19 Kolejka ruchu przychodzącego...19 Klasyfikowanie pakietów filtrami...21 Filtry i klasyfikowanie pakietów...21 Najczęściej używane filtry...22 Testy na adresach źródłowym i docelowym...22 Testy na portach źródłowym i docelowym...22 Testy na protokół (tcp, udp, icmp, gre, ipsec)...22 Testy na znacznik (fwmark)...22 Testy na polu ToS...22 Przygotowanie serwera...23 Kompilacja i instalacja jądra...23 Przygotowanie źródeł...23 Uzupełnienie jądra obsługą kolejki HTB...24 Konfiguracja jądra...24 Kompilacja...26 Instalacja...26 Instalacja iproute2...27 Jądro 2.2.x...27 Opis zadań...28 Jedna podsieć, łącze radiowe (serwer 1)...28 Dwie podsieci, łącze szeregowe (serwer 2)...28 Konfiguracje serwerów...29 Konfiguracja firewall a...29 Mechanizm kontroli użytkowników...30 Statystyki...31 Zliczanie ruchu IP...31 Statystyki klas...32 2
Serwer 1...33 Konfiguracja kolejek...34 Serwer 2...34 Konfiguracja kolejek...35 Interfejs ppp0...35 Interfejs eth1 i eth0...36 Zawartość CD...37 Bibliografia...38 Podstawowe materiały...38 Materiały pomocnicze...38 3
Tytułem Wstępu W ostatnim czasie znaczącą role w sieciach IP zaczęła odgrywać kontrola jakości usług. Aż do jądra Linuks a oznaczonego numerem 2.2 system ten nie gwarantował jakość przepływu. Alexey Kuznetsov przepisał znaczną część kodu jądra Linux a zajmującą się rutowaniem i kontrolą ruchu. Napisał również programy narzędziowe pozwalające na ustawianie parametrów rutingu w jądrze (ip), jak również pozwalające na sterowanie przepływem (tc), które pozwala na zarządzanie jakością usługi (ang. guality of serwice - QoS). W niniejszym dokumencie zostało przedstawione zagadnienia związane z tematem QoS, jak również przedstawiono przykłady wykorzystania nowych narzędzi, w oparciu o serwery w sieciach osiedlowych. Przy użyciu kolejkowania określamy, które dane są wysyłane. Ważne jest, aby zrozumieć, że możemy jedynie kontrolować dane, które wysyłamy. Z uwagi na budowę sieci IP, nie mamy bezpośredniej kontroli nad tym, co jest wysyłane do nas. TCP/IP nie zna przepustowości sieci pomiędzy dwoma komputerami, zaczyna więc od wysyłania danych za małą prędkością, a następnie szybciej i szybciej i kiedy zaczyna gubić pakiety, ponieważ nie ma już dla nich pasma, zwalnia (mechanizm ten nazwa się wolnym startem). Jeśli posiadamy ruter i chcemy zapobiec sytuacji, w której określone komputery ściągają dane za szybko, musimy wprowadzić ograniczenia na wewnętrznym interfejsie rutera tego, który wysyła dane do tych komputerów. 4
IP i TC - nowe narzędzie konfiguracji Jak już wcześniej wspomniano wraz z iproute2 otrzymujemy nowe narzędzie konfiguracji interfejsów sieciowych i tras rutowania. Narzędzie IP Aby ustawić interfejs sieciowy a następnie umieścić go w tablicy rutingu należało wykonać sekwencję komend: #ifconfig eth0 192.168.1.10 netmask 255.255.255.0 broadcast 192.168.1.255 #route add net 192.168.1.0 netmask 255.255.255.0 #route add default gw 192.168.1.1 przy użyciu ip to samo zadanie wykonujemy: #ip address add 192.168.1.10/24 broadcast 192.168.1.255 dev eth0 #ip link set dev eth0 up #ip route add default via 192.168.1.1 Podgląd aktualnego stanu aktywnych interfejsów przy użyciu ifconfig wygląda następująco: #ifconfig eth0 Link encap:ethernet HWaddr 00:50:DA:E3:52:77 inet addr:192.168.1.10 Bcast:192.168.1.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:6556978 errors:1 dropped:0 overruns:44 frame:1 TX packets:5613800 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:100 RX bytes:2755421382 (2627.7 Mb) Interrupt:6 Base address:0xd800 TX bytes:1765035412 (1683.2 Mb) natomiast przy użyciu ip: #ip address show 2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo link/ether 00:50:da:e3:52:77 brd ff:ff:ff:ff:ff:ff inet 192.168.1.10/24 brd 192.168.1.255 scope global eth0 Podgląd tablicy routingu wykonujemy poprzez: #route n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 0.0.0.0 192.168.1.1 0.0.0.0 UG 1 0 0 eth0 a poprzez ip: #ip route show 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10 default via 192.168.1.1 dev eth0 metric 1 Podgląd tablicy translacji adresów MAC na adresy IP wykonujemy: #arp -a n 5
Address HWtype HWaddress Flags Mask Iface 192.168.1.1 ether 00:50:BA:F2:82:1C C eth0 192.168.1.12 ether 00:80:AD:40:67:F8 C eth0 192.168.1.34 ether 00:E0:7D:9F:11:F4 C eth0... przy użyciu ip: #ip neighbour show 192.168.1.1 dev eth1 lladdr 00:50:ba:f2:82:1c nud delay 192.168.1.12 dev eth1 lladdr 00:80:ad:40:67:f8 nud delay 192.168.1.34 dev eth1 lladdr 00:e0:7d:9f:11:f4 nud delay... Uwaga: Szczegółowy opis polecenia ip znajduje się w dokumencie IP Command Reference, autorstwa Alexey a N. Kuznetsov a, zawitego na dołączonym CD. Narzędzie TC Nazwa narzędzia pochodzi od angielskiego określenia na Kontrolę Ruchu (ang. Traffic Control). Jej zadaniem definiowanie kolejek, klas i filtrów opisanych dalszych rozdziałach tego dokumentu, a ponieważ jest to podstawowe zagadnienie niniejszego opracowania składnia polecenia tc zostanie opisana stosunkowo dokładnie. Składnia polecenia tc wygląda następująco: #tc [ OPTIONS ] OBJECT { COMMAND help } gdzie: OBJECT := { qdisc class filter } określa czy polecenie dotyczy odpowiednio kolejki z dyscypliną, klasy czy filtru, OPTIONS := { -s[statistics] -d[details] -r[raw] } określa dodatkowe opcje polecenia, COMMAND := {add del ls...} określa jaka komenda ma być wykonana na OBJECT. W poniższych sekcjach opisano skrótowy opis składni komendy tc dla obiektów qdisc i klass. Opis składni dla obiektu filter znajduje się w rozdziale dotyczącym filtrów. Dyscypliny kolejkowania qdisc Podstawowa składnia polecenia definiującego dyscyplinę kolejkowania przedstawia się następująco: #tc qdisc [ add del replace change get ] dev STRING > [ handle QHANDLE ] [ root parent CLASSID ] > [ [ QDISC_KIND ] [ help OPTIONS ] ] #tc qdisc show [ dev STRING ] gdzie 6
STRING jest nazwą urządzenia, QDISC_KIND określa rodzaj dyscypliny (nazwę kolejki), QHANDLE określa uchwyt kolejki, CLASSID - definiuje rodzica kolejki, w przypadku gdy kolejka nie jest korzeniem root, OPTIONS w dużej mierze zależy od typu kolejki. Drugie polecenie pozwala na pokazanie aktualnie zdefiniowanych kolejek. Klasy class Podstawowa składnia polecenia definiująca klasy wygląda następująco: #tc class [ add del change get ] dev STRING > [ classid CHANDLE] [ root parent CLASSID ] > [ [ QDISC_KIND ] [ help OPTIONS ] ] #tc class show [ dev STRING ] [ root parent CLASSID ] gdzie poszczególne parametry pełnia identyczną funkcje jak w przypadku dyscyplin kolejkowania, natomiast parametr: CHANDLE określa uchwyt klasy. Drugie polecenie pozwala wylistować zdefiniowane klasy dla urządzenia względem korzenia root, lub względem korzenia poddrzewa. 7
Terminologia Aby prawidłowo zrozumieć opisywane tu zagadnienie, niezbędne jest zapoznanie się z używaną w tym dokumencie odpowiednią terminologią 1. Dyscyplina kolejkowania (ang. Queueing Discipline) algorytm zarządzający kolejką urządzenia, dla ruchu przychodzącego (ang. ingrees) lub wychodzącego (ang. egrees). Bezklasowa dyscyplina kolejkowania (ang. Classless qdisc) dyscyplina kolejkowania bez możliwości tworzenia wewnętrznych podziałów. Dyscyplina kolejkowania z klasami (ang. Classful qdisc) dyscyplina kolejkowania może zawierać wiele klas. Każda z nich może zawierać następne dyscypliny kolejkowania i tak dalej i tak dalej - ale nie musi. Klasyfikator (ang. Classifier) każda dyscyplina kolejkowania z klasami musi wiedzieć, do której klasy ma wysłać pakiet. Wykonuje to właśnie na podstawie klasyfikatora. Filtr (ang. Filter) klasyfikacja może zostać wykonana na podstawie filtrów. Filtr zawiera pewną liczbę warunków, które jeśli pasują, sprawiają że filtr również pasuje. Planowanie (ang. Scheduling) dyscyplina kolejkowania z klasami (qdisc), z pomocą klasyfikatora może zdecydować, że niektóre pakiety powinny zostać wysłane wcześniej niż inne. Proces ten nazywamy planowaniem. Planowanie nazywa się również porządkowaniem, ale jest to raczej mylące. Kształtowanie (ang. Shaping) proces odwlekania momentu wypuszczenia pakietu tak by pasował do zdefiniowanych charakterystyk ruchowych i jego maksymalnych wartości. Kształtowanie ruchu wykonywane jest przy opuszczaniu przez pakiet systemu. Narzucanie polityki (ang. Policing) proces odwrotny do kształtowania, wykonywany na ruchu przychodzącym. Może on tylko odrzucać pakiety a nie odwlekać ich obsługę ponieważ nie ma kolejki dla ruchu przychodzącego. Kolejka bezstratna (ang. Work-Conserving) ta kolejka zawsze dostarcza pakiet, jeśli tylko jest dostępny. Innymi słowy, nigdy nie odwleka wysłania pakietu, jeśli urządzenie sieciowe jest gotowe do przyjęcia go (w przypadku ruchu wychodzącego). Kolejka stratna (ang. non-work-conserving) niektóre kolejki, takie jak na przykład TBF mogą być zmuszone przytrzymać pakiet przez pewien czas, by dopasować się do ustalonego limitu na przepustowość. Oznacza to, że czasami nie wyślą pakietu, mimo że gdzieś w nich się znajduje. Poniższy rysunek przedstawia teoretyczne działanie rutera: 1 Na podstawie Kształtowanie Ruchu i Zaawansowany Ruting HOWTO 8
Rysunek 1 Teoretyczne działanie routera Duży kwadrat reprezentuje jądro. Lewa strzałka reprezentuje ruch docierający do komputera z sieci. Zostaje on następnie wrzucony do klasyfikatora ruchu przychodzącego, który może zastosować filtry i być może odrzucić ten ruch. Nazywamy to narzucaniem polityki. Dzieje się to we wczesnym stadium, zanim pakiet obejrzy sobie większość jądra, jest to więc dobre miejsce by odrzucać ruch bez zbędnego angażowania cykli CPU. Jeśli pakiet zostanie przepuszczony, może być skierowany do aplikacji działającej lokalnie - trafia wtedy na stos IP by zostać przetworzony, a potem do tej konkretnej aplikacji. Pakiet może jednak być przekazywany dalej, trafia wtedy do klasyfikatora dla ruchu wychodzącego. Programy przestrzeni użytkownika wysyłające pakiety również dostarczają danych dla klasyfikatora ruchu wychodzącego. Ruch wychodzący z takiego czy innego źródła trafia następnie do przetworzenia w określonej liczbie skonfigurowanych kolejek qdisc. W domyślnym, nie skonfigurowanym stanie, istnieje jedynie jedna kolejka dla ruchu wychodzącego - jest to pfifo_fast, która zawsze odbiera pakiet. Nazywamy to kolejkowaniem (ang. enqueueing). Pakiet czeka zatem w qdisc na decyzję jądra powodującą wysłanie go przez któryś z interfejs sieciowy. Nazywamy to z kolei opróżnianiem kolejki (ang. dequeueing). Rysunek ten ma zastosowanie również dla sytuacji z jednym urządzeniem sieciowym - strzałki skierowane do i od jądra nie powinny być brane zbyt dosłownie. W każ dym urządzeniu sieciowym obsługiwane jest zarówno odebranie pakietu jak i jego wysłanie. Uwaga: Dokładny opis tego zagadnienia znajduje się w dokumencie Linux Traffic Control - Implementation Overview (dołączone na CD). Do specyfikacji pasma tc używa następujących reguł: mb = 1024 kb = 1024 * 1024 b => bajtów/s mbit = 1024 kbit = 1024 * 1024 bit => bitów/s. 9
Dyscypliny kolejkowania Proste, bezklasowe dyscypliny kolejkowania Tak jak to już powiedziano, dyscyplinami kolejkowania zmieniamy sposób w jaki dane są wysyłane. Bezklasowe dyscypliny kolejkowania to te, które zajmują się jedynie odbieraniem danych, przesuwaniem ich transmisji w czasie lub ewentualnie odrzucaniem. Mogą być użyte do kontroli pasma dla całego interfejsu, bez żadnych dodatkowych podziałów na klasy i kolejki. Najczęściej używaną dyscypliną kolejkowania jest pfifo_fast i jest ustawiana jako domyślna. Istnieją również inne typy kolejek zapewniających określone pasmo jak również sprawiedliwy podział przepustowości dla każdej konwersacji. Zazwyczaj używa się ich w połączeniu z innymi klasami. Kolejka pfifo_fast Kolejka ta to tradycyjne pierwszy wszedł, pierwszy wyjdzie (ang. First In First Out, FIFO), co oznacza, że żaden pakiet nie jest specjalnie traktowany. Przynajmniej nie wprost. Kolejka ta ma 3 pasma (ang. band). W każdym paśmie z osobna działają reguły FIFO. Jednak dopóki w paśmie 0 są jeszcze pakiety, pasmo 1 nie zostanie obsłużone. Tak samo dzieje się w przypadku pasm 1 i 2. Jądro honoruje tak zwaną flagę typu usługi (ang. Type of Service, ToS) i zajmuje się ustawianiem opcji minimalna zwłoka w pakietach z pasma 0. Parametry kolejki Nie można konfigurować kolejki pfifo_fast, ponieważ jest ustawiona na sztywno w domyślnej konfiguracji. Poniżej opisano jak to jest zrobione: priomap określa w jaki sposób priorytety dla pakietów, przydzielane przez kernel, odwzorowywane są na pasma. Odwzorowywanie zachodzi na podstawie oktetu ToS pakietu, opis poniżej. Txqueuelen długość tej kolejki odpowiada konfiguracji interfejsu. Można ją sprawdzić i ustawić posługując się poleceniami ifconfig i ip. By ustawić długość kolejki na 10, wykonaj polecenie ifconfig eth0 txqueuelen 10. Nie można ustawić tego parametru za pomocą polecenia tc. 10
Opis pola ToS Oktetu ToS pakietu, wygląda następująco: Rysunek 2 Oktet ToS pakietu Czterobitowe pole ToS definiowane jest w następujący sposób: Binarnie Decymalnie Znaczenie 1000 8 Zminimalizuj zwłokę 0100 4 Maksymalizuj przepustowość 0010 2 Maksymalizuj niezawodność 0001 1 Zminimalizuj koszt 0000 0 Normalna usługa Ponieważ naprawo od pola ToS znajduje się jeszcze jeden bit, pole ToS jest równe podwojonej wartości bitów ToS. Domyślna mapa priorytetów (priomap) w linii poleceń, wygląda następująco: 1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 TBF Tocken Bucket Filter Token Bucket Filter (TBF) to prosta kolejka z dyscypliną, która przepuszcza tylko dane przychodzące z pewną częstotliwością nie przekraczającą nałożonych ograniczeń, ale z możliwością przyjęcia krótkich serii danych, które przekraczają to ustawienie. Co również nie jest bez znaczenia TBF jest bardzo precyzyjna, przyjazna zarówno dla sieci jak i procesora. Implementacja TBF składa się z wiadra (ang. bucket), wypełnianego pewnymi wirtualnymi porcjami danych, żetonami (ang. token) z określoną częstotliwością. Najważniejszym parametrem wiadra jest jego rozmiar, określający ilość żetonów, które może ono przechować. Każdy nadchodzący żeton wyjmuje jeden przychodzący pakiet z kolejki danych i jest kasowany z wiadra. Skojarzenie tego algorytmu z dwoma przepływami - żetonów i danych, daje trzy możliwe scenariusze: Dane docierają do kolejki z częstotliwością równą częstotliwości napływania żetonów. W tym przypadku każdy przychodzący pakiet pobiera z wiadra swój żeton i przechodzi przez kolejkę bez zwłoki. Dane docierają do kolejki z częstotliwością mniejszą niż częstotliwość napływania żetonów. Tylko ich część jest używana, więc te puste zbierane są do momentu osiągnięcia rozmiaru wiadra. W takim przypadku może zaistnieć sytuacja, w której dane zaczynają napływać bardzo szybko, w takim wypadku pakiety opróżniane są z kolejki wychodzącej tworząc krótką serię pakietów przekraczających normalny limit przepustowości. 11
Dane docierają do kolejki z częstotliwością większą niż częstotliwość napływania żetonów. W takim wypadku wiadro zostanie w końcu opróżnione z żetonów, powodując przez moment zwiększenie przepustowości, nazywa się to przekroczeniem limitu. Jeśli pakiety nadal będą napływały z niezmienną częstotliwością, niektóre będą odrzucane. Ostatni scenariusz umożliwia kształtować przepustowość, dostępną dla danych, które przechodzą przez filtr. Należy również zwrócić uwagę, że w przedstawianej implementacji żetony odpowiadają bajtom a nie pakietom. Parametry kolejki Parametry dostępne zawsze: limit lub latency limit lub opóźnienie limit to ilość bajtów, które mogą zostać skolejkowane w oczekiwaniu na wolne żetony. Można również określić ten parametr wskazując opóźnienie, określające maksymalny czas jaki pakiet może spędzić w kolejce, w takim wypadku brany jest pod uwagę rozmiar wiadra, częstotliwość i ewentualnie częstotliwość szczytową (jeśli zostanie ustawiona). burst/buffer/maxburst seria/bufor/maksymalna seria rozmiar wiadra określa maksymalna ilość bajtów dla których jednocześnie mogą być dostępne żetony. Generalnie, kształtowanie ruchu większych przepustowości wymaga większego bufora. Dla ruchu 10mbit/s na karcie Intel, wymagane jest przynajmniej 10 kilobajtowy bufor. Jeśli bufor będzie za mały, pakiety mogą być odrzucane dlatego, że przepływa więcej żetonów na jednostkę zegara, niż mieści się w wiadrze mpu Pakiet długości zero bajtów nie zużywa zero przepustowości. Dla ethernetu, pusty pakiet zużywa mniej niż 64 bajty. Minimalna Jednostka Pakietu (ang. Minimum Packet Unit) określa minimalną zajętość żetonu przez pakiet. rate częstotliwość ustawienie szybkości. Jeśli wiadro zawiera żetony i nie może być puste (domyślnie pracuje z nieograniczoną prędkością), a jest to nie akceptowalne, można użyć dodatkowych parametrów. Po więcej szczegółów odsyłam do dokumentacji. Przykładowa konfiguracja Prosta, ale bardzo przydatna konfiguracja. #tc qdisc add dev eth0 root tbf rate 220kbit latency 50ms burst 1540 Jeśli mamy urządzenie sieciowe z całkiem dużą kolejką, tak jak na przykład modem kablowy, a po drugiej stronie podłączymy szybkie urządzenie takie jak na interfejs ethernetowy, można zauważyć, że wysyłanie czegoś od razu niszczy interaktywność. Dzieje się tak dlatego, ponieważ wysyłanie pakietów zapełni kolejkę w modemie, która jest prawdopodobnie duża (taka konfiguracja pomaga uzyskać dużą przepustowość). Linia powyżej spowalnia wysyłanie do częstotliwości, która nie prowadzi do zapełniania kolejki w modemie kolejka będzie już na ruterze, gdzie mamy swobodę jej konfiguracji. 12
SFQ Stochastic Fairness Queueing Sprawiedliwe Kolejkowanie Stochastyczne (ang. Stochastic Fairness Queueing - SFQ) to prosta implementacja rodziny algorytmów ze sprawiedliwym podziałem pasma. Jest mniej dokładna niż inne, ale wymaga również mniejszej ilości wyliczeń. Dodatkowo SFQ jest praktycznie samo konfigurowalna. Kluczowym słowem przy omawianiu SFQ jest konwersacja (ang. conversation) lub przepływ (ang. flow), które odpowiadają prawie sesjom TCP czy strumieniom UDP. Ruch dzielony jest na znaczną liczbę kolejek FIFO, jedną dla każdej konwersacji, a następnie rozsyłany algorytmem round-robin, dzięki czemu każda sesja ma zawsze szansę wysłania pakietu. Zapewnia to sprawiedliwy podział pasma i uniemożliwia jednej konwersacji zajęcie całego pasma. SFQ nazywana jest stochastyczną, ponieważ tak naprawdę nie alokuje kolejki dla każdej sesji, a używa procedury dzielącej ruch na ograniczoną liczbę kolejek przy pomocy algorytmu mieszającego (ang. hash). Ponieważ używana jest wartość mieszająca, więcej niż jedna sesja mogą skończyć w tym samym wiadrze. Oznaczałoby to w praktyce zmniejszenie szansy wysłania pakietu o połowę i podzielenie tym samym na pół dostępną efektywną prędkość. By temu zapobiec, SFQ zmienia często algorytm mieszający i nawet jeśli dojdzie do opisanej sytuacji będzie to działo się tylko przez parę sekund. SFQ jest użyteczne w przypadku gdy jeden z interfejsów wychodzących jest często zapełniony. W przeciwnym wypadku, nie zostanie stworzona kolejka i tak naprawdę nie będzie żadnego efektu. W dalszej części dokumentu bardzo często będziemy używać kolejki SFQ w połączeniu z innymi dyscyplinami kolejkowania. Parametry kolejki perturb wartość określająca co ile sekund zmieniany będzie algorytm mieszający. Jeśli nie zostanie podana, wyliczona wartość mieszająca nie będzie rekonfigurowana. Generalnie pomijanie tego parametru nie jest zalecane, wartość 10 sekund wydaje się dobrym wyborem. quantum ilość bajtów, którą strumień może zdjąć z kolejki zanim szansę wysłania otrzyma następna kolejka. Domyślnie ustawione jest na równowartość maksymalnej jednostki transmisji 1 pakietu (MTU). Zaleca się nie stosowanie wartości mniejszej niż MTU gdyż uniemożliwi to większych pakietów. 13
Dyscypliny kolejkowania z klasami Ruch, który dociera do korzenia kolejki z dyscypliną (qdisc) zawierającą klasy, jest klasyfikowany, a następnie przesyłany do odpowiedniej klasy podrzędnej. Aby określić co dzieje się z konkretnym pakietem używa się filtrów. Ważne jest aby zrozumieć że to filtry wywoływane są w kolejce a nie na odwrót. Filtry dołączone do określonych kolejek z dyscypliną, są przez nią używane do podjęcia decyzji skolejkowania pakietu w jedną z klas. Każda podklasa może zawierać własne filtry, dopasowując pakiet do swoich założeń. W przypadku braku filtrów klasa kolejkuje pakiet do kolejki, która ją zawiera. Poniższy rysunek w uproszczeniu przedstawia budowę i funkcjonowanie kolejek, klas i filtrów dołączonych do kolejki głównej. Rysunek 3 kolejki, klasy i filtry Oprócz zawierania w sobie innych kolejek, większość kolejek z dyscypliną zawierające klasy wykonuje również kształtowanie. Pozwala to na jednoczesne planowanie kolejności wysyłania pakietów jak i częstotliwości z jaką będą one wysyłane Każdy interfejs ma jedną wychodzącą kolejkę-korzeń, którą domyślnie jest wspomniana wcześniej bezklasowa pfifo_fast. Każdej z kolejek z dyscypliną można nadać uchwyt, który będzie potem używany przez polecenia konfigurujące filtry by odwołać się do tej konkretnej kolejki. Poza wychodzącymi kolejkami, interfejs może posiadać również przychodzące, które podlegają narzuceniu polityki. Uchwyt kolejki składa się ze starszego i młodszego numeru (starszy:młodszy). Charakterystyczną nazwą dla kolejki-korzenia jest 1:, które równe jest 1:0. Młodszy numer kolejki z dyscypliną zawsze równy jest 0. Klasy muszą mieć ten sam starszy numer, określający ich kolejkę rodzica, natomiast numer młodszy określa numer podklasy. Przykładowy rysunek przedstawia definicję różnych dyscyplin kolejkowania w postaci drzewa. 14
Rysunek 4 Przykładowe drzewo kolejek i klas Numerowanie klas i kolejek jest dowolne, poza sytuacjami opisanymi wcześniej, jednak proponowana tu konwencja pozwala na sprawniejsze poruszanie się w strukturze drzewa i łatwiejsze rozpoznacie rodziców i potomków. Kiedy jądro zdecyduje że musi zdjąć pakiet z i wysłać go interfejsem, kolejka będąca korzeniem całego drzewa (root 1:) odbiera od jądra żądanie rozkolejkowania. Następnie żądanie to wysyłane jest do potomków kolejki (w tym wypadku klas), które z kolei przesyłają je dalej w głąb drzewa do swoich potomków (tutaj już klas lub kolejek). Na podstawie ustawień specyfikujących klasy (np. szerokość pasma, priorytet) podejmowana jest decyzja, który pakiet, z której kolejki trafia do kolejki rodzica, a jeden z nich do kolejki w korzeniu skąd jest wysyłany przez interfejs. W przypadku gdy w całym drzewie znajduje się tylko jeden pakiet jądro musi przeglądnąć całe drzewo. Precyzując, zagnieżdżone klasy rozmawiają tylko ze swoimi rodzicami, nigdy z interfejsem. Wynika z tego ważny fakt, że klasa nie jest rozkolejkowana szybciej niż pozwala na to jej rodzic. Dodatkowo tylko kolejka w korzeniu całego drzewa rozmawia bezpośrednio z interfejsem i jest prze niego rozkolejkowywana 2. HTB Hierarchical Token Bucket Kolejka HTB jest została stworzona jako bardziej zrozumiała i intuicyjna alternatywa dla opisywanej poniżej kolejki CBQ. Pozwala na kontrolę ruchu wychodzącego z serwera, symulacji kilku wolniejszych połączeń, jak również wysyłanie różnego rodzaju ruchu na różnych symulowanych połączeniach. HTB określa sposób odwzorowania fizycznego połączenia w symulowane połączenia i decyduje, które z nich powinno być użyte dla określonego połączenia. Kolejka HTB nie jest integralną częścią jądra Linux a. Sposób instalacji opisano w odpowiednim rozdziale poniżej. 2 Szerszy opis tego zagadnienia znajduje się w opracowaniu Linux Traffic Control Iplementation Overview, autorstwa Werner a Almensberger a (na CD) 15
Dzielenie połączenia Kolejka HTB zapewnia obsługę usługi odpowiadającej pewnej klasie na co najmniej minimalnym poziomie. W przypadku gdy klasa wymaga mniejszej przepustowości, pozostałe pasmo jest współdzielone z innymi klasami, które mogą wymagać większego pasma. Użyjemy następującego polecenia aby podpiąć kolejkę HTB do korzenia urządzenia: #tc qdisc add dev eth0 root handle 1: htb default 12 Ta komenda podpina dyscyplinę kolejkowania HTB do urządzenia eth0 i nadaje mu uchwyt 1:. Parametr default 12 oznacza że każdy niesklasyfikowany ruch pakietów będzie przekazywany do klasy 1:12. Przyjrzyjmy się następnym poleceniom #TC= tc class add dev eth0 #$TC parent 1: classid 1:1 htb rate 100kbps ceil 100kbps #$TC parent 1:1 classid 1:10 htb rate 30kbps ceil 100kbps #$TC parent 1:1 classid 1:11 htb rate 10kbps ceil 100kbps #$TC parent 1:1 classid 1:12 htb rate 60kbps ceil 100kbps Pierwsza linia tworzy klasę korzeń identyfikowaną jako 1:2 w kolejce qdisc 1:. Definicja klasy korzenia jest tylko jedna a jej rodzicem jest kolejka z dyscypliną. Klasa korzeń, podobnie jak inne klasy pozwala na pożyczanie pasma pomiędzy klasami dziećmi. W następnych trzech linkach tworzone są klasy potomne 1:1. Parametr rate określa pasmo używane przez daną klasę. Parametr ceil zostanie opisany w dalszej części rozdziału Możemy również określić dyscyplinę kolejkowania w każdej z klas. Domyślnie używaną jest kolejka pfifo. Poniższe trzy liniki definiują określone dyscypliny kolejkowania dla każdej z klas #tc qdisc add dev eth0 parent 1:10 handle 20: pfifo limit 5 #tc qdisc add dev eth0 parent 1:11 handle 30: pfifo limit 5 #tc qdisc add dev eth0 parent 1:12 handle 40: sfq perturb 10 W ten sposób stworzyliśmy drzewo podziału pasma, w którym klasy współdzielą przepustowość 100 kbps w stosunku 3:1:6 i każda z klas może pożyczać pasmo od innej w przypadku gdy wypożyczający nie wykorzystuje całego zasobu. Wypożyczanie pasma Parametr ceil określa maksymalną przepustowość jaką klasa może wykorzystać, a więc i ile może wypożyczać od swojego rodzeństwa. Domyślną wartością jest parametr rate. Parametr ten jest użyteczny w przypadku gdy chcemy ograniczyć maksymalną przepustowość dla danej klasy tak by nie przekroczyła określonej częstotliwości. Należy pamiętać że klasa która jest korzeniem nie może wypożyczać pasma. Parametr ceil dla klasy powinien mieć wartość większą, lub równą, parametrowi rate. Również parametr ten dla klasy powinien być większy lub równy parametrowi ceil jej dzieci. 16
Opróżnianie kolejki Sprzęt sieciowy może wysyłać tylko jeden pakiet w tym samym czasie i z określona przez jego parametry techniczne częstotliwością. Oprogramowanie dzielące połączenie wykorzystuje możliwość aproksymacji, która pozwala na osiągnięcie efektu wielu połączeń działających z różną, zazwyczaj mniejszą częstotliwością. W przypadku gdy fizyczne łącze dzielimy na logiczne pasma parametry burst i cburst pozwalają kontrolować maksymalną ilość danych, które mogą być wysłane z maksymalną prędkością bez dzielenia pasma z innymi klasami. Kiedy określimy parametr burst, dla klasy rodzica, mniejszy niż dla niektórych klas potomnych, możemy się spodziewać, że te klasy będą się czasami przytykać. W przypadku gdy określimy zbyt małą wartość dla parametru burst możemy otrzymać mniejsze pasmo niż ustawiliśmy. Priorytety ruchu Nadawanie priorytetu ma dwie strony. Pierwsza określa w jaki sposób pasmo jest dzielone klasy potomne. W użytym do tej pory przykładzie ruch był dzielony zgodnie z częstotliwością klasy. W przypadku gdy określimy priorytety najpierw brane są pod uwagę klasy posiadające priorytet o wartości najniższej zachowując zasadę częstotliwości miedzy klasami tego samego priorytetu. Druga strona wiąże się z opóźnieniami pakietów. Trudno jest je określić dla szybkich interfejsów takich jak ethernet. W takim wypadku można wykorzystać kolejki. W takim przypadku możemy dodać klasę z pasmem ograniczonym do wartości mniejszej niż 100 kbps, następnie stworzyć jej potomka, który będzie nam symulował wolniejsze łącze. Parametry kolejki Kolejka HTB może przyjmować następujące parametry default domyślna klasa przyjmująca ruch niesklasyfikowany, parametr ten przypisuje się tylko do qdisc, a nie do klas. rate parametr określający szybkość pasma. ceil parametr określający maksymalny rozmiar pasma, osiągany poprzez wypożyczanie go od innych kolejek posiadających tego samego rodzica. burst i cburst parametry określają maksymalną ilość danych, które mogą być wysłane z maksymalną prędkością bez dzielenia pasma z innymi klasami. prio określa priorytet kolejki. Kolejka PRIO Kolejka PRIO nie zajmuje się tak naprawdę kształtowaniem ruchu, dzieli jedynie ruch na podstawie tego, jak zostały skonfigurowane filtry. Można ją traktować jak rozszerzoną 17
kolejkę pfifo_fast (zamiast pasma jest osobna klasa zamiast prostej kolejki FIFO). Kolejka PRIO jest bardzo użyteczna, gdy należy priorytetować określone rodzaje ruchu nie tylko na podstawie flag ToS, ale całej potęgi, którą zapewniają filtry tc. Może równie ż zawierać inne kolejki, podczas gdy pfifo_fast jest ograniczona do prostych kolejek FIFO. Kiedy pakiet zostaje skolejkowany w qdisc PRIO, na podstawie komend filtrujących wybierana jest klasa. Domyślnie, stworzone są trzy klasy zawierające czyste kolejki FIFO bez żadnej struktury wewnętrznej, ale można zastąpić je dowolnymi kolejkami qdisc. Zawsze gdy pakiet musi zostać wyjęty z kolejki, sprawdza się klasę :1. Wyższe klasy są sprawdzane tylko wtedy, gdy poprzednie nie zwróciły pakietu. Ponieważ kolejka ta nie zajmuje się kształtowaniem ruchu, należy używać jej tylko jeśli fizyczne łącze jest naprawdę obciążone, lub powiązać ją z kolejką qdisc z klasami, która nie zajmuje się kształtowaniem ruchu. Formalnie rzecz biorąc, kolejka PRIO jest planującą kolejką bezstratną. Pasma są klasami i domyślnie nazywane są od numer_starszy:1 do numer_starszy:3, więc jeśli kolejka PRIO nazywa się 12:, można użyj tc do przefiltrowania ruch na 12:1 dla podniesienia priorytetu. Uwaga: Należy pamiętać że pasmo 0 trafia na młodszy numer 1, a pasmo 1 na młodszy numer 2 i tak dalej. Parametry kolejki Następujące parametry rozpoznawane są przez tc dla kolejki PRIO: bands pasma ilość pasm do utworzenia. Każde pasmo to tak naprawdę klasa. Jeśli zmieniamy ten numer, należy zmienić również priomap. priomap - mapa priorytetów jeśli nie dostarczymy filtrów tc do klasyfikowania ruchu, kolejka PRIO będzie sprawdzać priorytety TC_PRIO stwierdzić, jak kolejkować ruch. Działa to tak jak kolejka pfifo_fast wspomniana wcześniej. Przykłady użycia Przyjrzyjmy się następującej sekwencji poleceń. #tc qdisc add dev eth0 root handle 1: prio #tc qdisc add dev eth0 parent 1:1 handle 10: sfq #tc qdisc add dev eth0 parent 1:2 handle 20: sfq #tc qdisc add dev eth0 parent 1:3 handle 30: sfq Pierwsze polecenie od razu tworzy klasy 1:1, 1:2 i 1:3. Drzewo urządzenia wygląda następująco. 18