/ Linux Reviews / Networking / Kształtowanie Ruchu i Zaawansowany Routing HOWTO - en - pl


9.2. 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ą zostać użyte do kontroli pasma dla całego interfejsu, bez żadnych dodatkowych podziałów. Bardzo ważne jest, byś zrozumiał tą część kolejkowania zanim zajmiemy się zagadnieniem zagnieżdżonych dyscyplin kolejkowania z klasami ruchu.

Najczęściej używaną dyscypliną jest `pfifo_fast' - i jest domyślna. Jej popularność wyjaśnia dlaczego zaawansowane opcje są takie wydajne. Nie zawierają po prostu nic oprócz `kolejnej kolejki'.

Każda z tych kolejek ma swoje mocne i słabe strony. Nie wszystkie są też dokładnie przetestowane.

9.2.1. pfifo_fast

Kolejka ta, dokładnie tak jak wskazuje na to jej nazwa, to tradycyjne `Pierwszy Wszedł, Pierwszy Wyjdzie' (ang. "First In First Out", FIFO). Oznacza to, że żaden pakiet nie będzie specjalnie traktowany (przynajmniej nie wprost). Kolejka ta ma 3 `pasma' (ang. "band"). W każdym z pasm reguły FIFO działają niezależnie. Jednak jeśli w paśmie 0 są jeszcze pakiety, pasmo 1 nie zostanie obsłużone. Tak samo dzieje się w przypadku pasm 1 i 2.

Kernel honoruje tak zwaną flagę `Typu Usługi' (ang. "Type of Service") i zajmuje się ustawianiem opcji `minimalna zwłoka' w pakietach z pasma 0.

Nie pomylcie tej bezklasowej kolejki z klasową kolejką PRIO! Mimo, że zachowują się podobnie, pfifo_fast jest bezklasowa i nie można dodawać innych kolejek do niej przy użyciu polecenia tc.

9.2.1.1. Parametry i ich użycie

Nie można konfigurować kolejki pfifo_fast, ponieważ jest ustawiona na sztywno w domyślnej konfiguracji. Poniżej 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, który wygląda tak:

   0     1     2     3     4     5     6     7
+-----+-----+-----+-----+-----+-----+-----+-----+
|                 |                       |     |
|   KOLEJNOŚĆ     |          TOS          | MBZ |
|                 |                       |     |
+-----+-----+-----+-----+-----+-----+-----+-----+

Czterobitowe pole ToS definiowane jest w następujący sposób:

Binarnie Decymalnie  Znaczenie
-----------------------------------------
1000     8           Zminimalizuj zwłokę (md)
0100     4           Zmaksymalizuj przepustowość (mt)
0010     2           Zmaksymalizuj niezawodność (mr)
0001     1           Zminimalizuj koszt (mmc)
0000     0           Normalna usługa

Ponieważ na prawo od pola ToS znajduje się jeszcze jeden bit, pole ToS jest równe podwojonej wartości bitów ToS. tcpdump -v -v pokazuje wartość całego pola ToS, nie tylko tych 4 bitów. Jest to wartość, którą możesz znaleźć w pierwszej kolumnie tej tabeli:

TOS     Bity  Znaczenie                    Priorytet Linuksa    Pasmo
---------------------------------------------------------------------
0x0     0     Normalna Usługa              0 Najlepszy efekt    1
0x2     1     Zminimalizuj koszt           1 Wypełniacz         2
0x4     2     Zmaksymalizuj niezawodność   0 Najlepszy efekt    1
0x6     3     mmc+mr                       0 Najlepszy efekt    1
0x8     4     Zmaksymalizuj przepustowość  2 Większość          2
0xa     5     mmc+mt                       2 Większość          2
0xc     6     mr+mt                        2 Większość          2
0xe     7     mmc+mr+mt                    2 Większość          2
0x10    8     Zminimalizuj zwłokę          6 Interaktywnie      0
0x12    9     mmc+md                       6 Interaktywni       0
0x14    10    mr+md                        6 Interaktywni       0
0x16    11    mmc+mr+md                    6 Interaktywni       0
0x18    12    mt+md                        4 Większość interakt.1
0x1a    13    mmc+mt+md                    4 Większość interakt.1
0x1c    14    mr+mt+md                     4 Większość interakt.1
0x1e    15    mmc+mr+mt+md                 4 Większość interakt.1

Dużo numerków. Druga kolumna zawiera wartość czterech bitów pola ToS, a następnie ich znaczenie. Na przykład wartość 15 oznacza pakiet wymagający Minimalnego Kosztu, Maksymalnej Niezawodności, Maksymalnej Przepustowości i Minimalnej Zwłoki. Nazwałbym go `Pakietem Holenderskim'.

Czwarta kolumna to sposób w jaki kernel interpretuje bity ToS, określony priorytetem, który jest im przyznawany.

Ostatnia kolumna to wynik domyślnej mapy priorytetów (priomap). W linii poleceń, wygląda ona tak:

1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1

Oznacza to na przykład dla priorytetu 4, że mapowany jest na pasmo 1. Mapa priorytetów pozwala również na wylistowanie wyższych priorytetów (> 7), które nie odpowiadają mapowaniom ToS, ale są rozsyłane dla innych zastosowań.

Poniższy wydruk pochodzi z RFC 1349 (przeczytaj ten dokument jeśli chcesz zapoznać się ze szczegółami) i omawia jak aplikacje mogłyby ustawiać pole TOS swoich pakietów:

TELNET                   1000           (zminimalizuj zwłokę)
FTP
    kanał kontroli       1000           (zminimalizuj zwłokę)
    Dane                 0100           (zmaksymalizuj przepustowość)

TFTP                     1000           (zminimalizuj zwłokę)

SMTP 
    Faza komend          1000           (zminimalizuj zwłokę)
    Faza danych          0100           (zmaksymalizuj przepustowość)

Domain Name Service
    Zapytanie UDP        1000           (zminimalizuj zwłokę)
    Zapytanie TCP        0000
    Transfer Strefy      0100           (zmaksymalizuj przepustowość)

NNTP                     0001           (zminimalizuj koszt)

ICMP
    Błędy                0000
    Zapytania            0000 (zwykle)
    Odpowiedzi           <takie jak zapytania> (zwykle)

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ć wartości tego parametru za pomocą tc!

9.2.2. Token Bucket Filter

Token Bucket Filter (TBF, w wolnym tłumaczeniu "Filtr Wiadra Żetonów") 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ą tych ograniczeń.

TBF jest bardzo precyzyjna, przyjazna zarówno dla sieci jak i procesora. Powinna być twoim pierwszym wyborem jeśli chcesz po prostu zwolnić interfejs!

Implementacja TBF składa się z bufora (`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 TBF z częstotliwością równą częstotliwości napływania żetonów. W tym przypadku każdy przychodzący pakiet ma swój żeton i przechodzi przez kolejkę bez zwłoki.

  • Dane docierają do TBF 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'. Mogą być potem użyte do krótkiej serii pakietów przekraczających normalny limit przepustowości.

  • Dane docierają do TBF z częstotliwością większą niż częstotliwość napływania żetonów. Oznacza to, że `wiadro' zostanie w końcu opróżnione z pustych żetonów, powodując przez moment zwiększenie przepustowości. Nazywa się to `przekroczeniem limitu' i jeśli pakiety nadal będą napływały z niezmienną częstotliwością, niektóre będą odrzucane.

Ostatni scenariusz jest bardzo ważny, ponieważ umożliwia kształtować przepustowość dostępną dla danych które przechodzą przez filtr.

Akumulacja żetonów zapewnia pewnego rodzaju zapas bezpieczeństwa, który wykorzystany zostanie gdy pakiety zaczną nagle docierać z większą niż dotychczas częstotliwością. W końcu jednak, ciągłe obciążenie większe od maksymalnego zdefiniowanego spowoduje przeładowanie i pakiety zaczną być najpierw opóźniane, a w końcu odrzucane.

Proszę zauważyć, że w implementacji programowej, żetony odpowiadają bajtom a nie pakietom.

9.2.2.1. Parametry i ich użycie

Mimo, że zapewne nie będziesz potrzebował ich zmieniać, tbf udostępnia parę zmiennych kontrolnych. Po pierwsze, parametry dostępne zawsze:

limit lub latency (limit lub opóźnienie)

Limit to numer bajtów, które mogą zostać skolejkowane w oczekiwaniu na wolne żetony. Możesz również określić parametr wskazując opóźnienie, określające maksymalny czas jaki pakiet może spędzić w TBF. To drugie bierze pod uwagę rozmiar `wiadra', częstotliwość i ewentualnie (jeśli zostanie ustawiona) częstotliwość szczytową.

burst/buffer/maxburst

Rozmar `wiadra', w bajtach. Jest to 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, potrzebujesz przynajmniej 10 kilobajtowego bufora, jeśli chcesz osiągnąć żądaną przepustowość!

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ść żetona przez pakiet.

rate

Ustawienie prędkości. Zajrzyj do notatek powyżej o limitach!

Jeśli `wiadro' zawiera żetony i nie może być puste, domyślnie pracuje z nieograniczoną prędkością. Jeśli jest to nieakceptowalne, użyj następujących parametrów:

peakrate

Domyślnie, jeśli dostępne są żetony a przybywają pakiety, są one natychmiast wysyłane. Może to nie być konkretnie to, czego chcesz, szczególnie jeśli masz duże `wiadro'.

Parametr `peakrate' może zostać użyty do określenia jak szybko `wiadro' może być opróżniane. Jeśli go określisz, po wysłaniu pakietu odczekamy chwilę i dopiero po jej upływie wyślemy następny - dzięki przeliczeniu przestrzeni czasowej między pakietami tak, aby wysyłać dokładnie tyle ile wynosi wartość tego parametru.

Jednak ponieważ zegar Unixowy ma rozdzielczość tylko 10ms, otrzymując 10.000 bitów średniego ruchu ograniczeni jesteśmy do `peakrate' równej około 1mbit/s!

mtu/minburst

Oczywiście `peakrate' równe 1mbit/s nie jest zbyt użyteczne, jeśli twój normalny ruch wynosi więcej. Większa wartość szczytowa możliwa jest do osiągnięcia przez wysyłanie większej ilości pakietów na jedną jednostkę zegara, co oznacza, że tworzymy drugie wiadro!

To drugie wiadro domyślnie ma wielkość jednego pakietu, więc tak naprawdę nie jest wcale wiadrem.

By wyliczyć maksymalną wartość szczytową, pomnóż skonfigurowane MTU przez 100 (lub, bardziej poprawnie, HZ, co oznacza 100 na platformie intelowskiej i 1024 na Alfie).

9.2.2.2. Przykładowa konfiguracja

Prosta, ale bardzo przydatna konfiguracja to:

# tc qdisc add dev ppp0 root tbf rate 220kbit latency 50ms burst 1540

No dobra, dlaczego jest taka przydatna? Jeśli masz urządzenie sieciowe z całkiem dużą kolejką, tak jak na przykład modem kablowy lub DSL i łączysz je do szybkiego urządzenia takiego jak na przykład interfejs ethernetowy, zauważysz od razu, że wrzucanie czegoś od razu niszczy interaktywność.

Dzieje się tak dlatego, ponieważ wysyłanie pakietów zapełni kolejkę w modemie, która jest prawdopodobnie bardzo duża - taka konfiguracja pomaga uzyskać dużą przepustowość. Ale to nie jest to co chcesz osiągnąć, chcesz mieć pełną interaktywność a nie zapchać modem jednym strumieniem i nie móc zrobić już nic innego.

Linia powyżej spowalnia wysyłanie do częstotliwości, która nie prowadzi zapełniania kolejki w modemie - kolejka będzie już na Linuksie, gdzie mamy swobodę konfiguracji jej do określonego rozmiaru.

Zmień wartość 220kbit na swoją faktyczną prędkość wysyłania danych minus parę procent. Jeśli masz naprawdę bardzo szybki modem, możesz troszkę zwiększyć wartość `burst'.

9.2.3. Sprawiedliwe Kolejkowanie Stochastyczne (ang. "Stochastic Fairness Queueing")

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ń.

Kluczowym pojęciem w SFQ jest konwersacja (lub potok), która odpowiada zwykle sesji TCP lub strumieniowi UDP. Ruch dzielony jest w dużą ilość kolejek FIFO, po jednej na każdą konwersację. Następnie każda z kolejek opróżniana jest na zasadzie `round-robin' tak aby każda z sesji mogła wysłać swoje dane.

Zapewnia to sprawiedliwą pracę i uniemożliwia jednej konwersacji zajęcie całego pasma. SFQ nazywana jest `stochastyczną', ponieważ tak naprawdę nie przydziela kolejki dla każdej sesji, a używa procedury dzielącej ruch na ograniczoną liczbę kolejek przy pomocy algorytmu `mieszającego' (ang. "hashing").

Ponieważ używana jest wartość mieszająca ( wspominany hash ), może dojść do sytuacji w której więcej niż jedna sesja może 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ępnej efektywnej prędkości. By temu zapobiec, SFQ zmienia często algorytm mieszający i nawet jeśli dojdzie do kolizji sesji będzie to działo się tylko przez parę sekund.

Warto zauważyć, że SFQ jest użyteczne w przypadku gdy twój interfejs wychodzący jest naprawdę pełen! Jeśli nie będzie, nie stworzona zostanie kolejka i tak naprawdę nie będzie miało to żadnego efektu. Później omówimy jak połączyć SFQ z innymi dyscyplinami kolejkowania i uzyskać to co najlepsze z obu sytuacji.

W szczególności, zastosowanie SFQ wobec interfejsu ethernetowego podłączonego do modemu kablowego lub rutera DSL jest bezcelowe, bez dalszego nałożenia ograniczeń!

9.2.3.1. Parametry i użycie

SFQ jest praktycznie samokonfigurowalna:

perturb

Wartość określajaca 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 kolejna kolejka. Domyślnie ustawione jest na równowartość maksymalnej jednostki transmisji 1 pakietu (MTU). Nie ustawiaj tego parametru poniżej MTU!

9.2.3.2. Przykładowa konfiguracja

Jeśli masz urządzenie połączone łączem o identycznej przepustowości jaka jest ogólnie dostępna, tak jak na przykład w sytuacji połączenia modemowego, to polecenie pomoże ci uwydatnić sprawiedliwy podział ruchu:

# tc qdisc add dev ppp0 root sfq perturb 10
# tc -s -d qdisc ls
qdisc sfq 800c: dev ppp0 quantum 1514b limit 128p flows 128/1024 perturb 10sec 
 Sent 4812 bytes 62 pkts (dropped 0, overlimits 0) 

Numer `800c:' to automatycznie nadawana etykietą, limit oznacza, że w kolejce oczekiwać może 128 pakietów. Dostępne są 1024 wiadra kontrolowane algorytmem mieszającym, z których 128 może być jednocześnie aktywnych (więcej pakietów nie wejdzie do kolejki!). Co 10 sekund, wartości mieszające są rekonfigurowane.


/ Linux Reviews / Networking / Kształtowanie Ruchu i Zaawansowany Routing HOWTO