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


14.3. DSMARK

Esteve Camps

Ten tekst to streszczenie moich tez zebranych w Wsparcie dla QoS w Linuksie, wrzesień 2000.

Dokumenty źródłowe:

Ten rozdział jest autorstwa Esteve Camps <esteve%hades.udg.es>.

14.3.1. Wprowadzenie

Po pierwsze, dobrze byłoby przeczytać RFC poświęcone temu tematowi (RFC2474, RFC2475, RFC2597 i RFC2598) ze strony IETF DiffServ working Group oraz strony autorstwa Wernera Almesbergera (napisał kod odpowiedzialny za różnicowanie usług w Linuksie).

14.3.2. Z czym jest związany Dsmark?

Dsmark jest kolejką z dyscypliną, która oferuje możliwości potrzebne w `Usługach Zróżnicowanych' (ang. "Differentiated Services") (nazywanych również DiffServ lub po prostu DS). DiffServ jest jedną z dwóch architektur QoS (druga nazywa się Usługami Zintegrowanymi) bazujących na wartościach przenoszonych przez pakiet w polu DS nagłówka IP.

Jednym z pierwszych rozwiązań zaprojektowanych dla IP z myślą o QoS było pole Typ Usługi (bajt ToS) umieszczone w nagłówku IP. Zmieniając tą wartość, możemy wybrać wysoki/niski poziom przepustowości, zwłokę czy też niezawodność. Nie zapewnia to wymaganej elastyczności jeśli chodzi o nowe usługi (takie jak aplikacje czasu rzeczywistego, interaktywne i inne). Po tym pomyśle pojawiły się nowe architektury. Jedną z nich jest DiffServ, która zachowała bity ToS i przemianowane pole DS.

14.3.3. Wskazówki dotyczące Usług Zróżnicowanych

Usługi Zróżnicowane są zorientowane na grupy. Oznacza to, że nie wiemy nic o potokach (którymi zajmą się Usługi Zróżnicowane); wiemy o agragacjach potoków i zastosujemy w stosunku do nich różne zasady, w zależności od tego, do której agregacji należy pakiet.

Kiedy pakiet dociera do węzła brzegowego (węzła wejściowego do domeny DiffServ) można w stosunku do niego zastosować zdefiniowane zasady, poddać go kształtowaniu ruchu i/lub zaznaczyć go (oznaczanie dotyczy przydzielania wartości polu DS. Całkiem jak z krowami :-) ). Jest to znacznik na podstawie którego węzły domeny DiffServ będą decydowały, który poziom QoS zastosować.

Jak pewnie wydedukujesz, Usługi Zróżnicowane zawierają domenę, w której reguły DS będą stosowane. Tak naprawdę możesz o niej myśleć w ten sposób: `Pakiety docierające do mojej domeny będą poddane działaniu reguł, które dyktują zasady klasyfikujące a każdy przemierzany węzeł zastosuje w stosunku do takiego pakietu poziom QoS'.

Tak naprawdę, możesz stosować własne zasady w swoich lokalnych domenach, ale pewne `Ustalenia Poziomu Usług' (ang. "Service Level Agreements") powinny zostać rozważone przy podłączaniu do innych domen DS.

Możesz mieć w tym momencie masę pytań. DiffServ to więcej niż do tej pory powiedziałem. Proszę zrozumieć, że nie potrafię streścić 3 RFC w 50 liniach :-).

14.3.4. Praca z Dsmark

Jak podaje bibliografia DiffServ, rozróżniamy węzły brzegowe i wewnętrzne. Są to dwa ważne punkty w ścieżce obsługiwanego ruchu. Oba typy wykonują klasyfikację gdy otrzymują pakiety. Rezultaty tej klasyfikacji mogą zostać wykorzystane w różnych miejscach procesu DS zanim pakiet zostanie wypuszczony do sieci. Dlatego architektura DiffServ udostępnia strukturę `sk_buff', zawierającą nowe pole nazwane `skb->tc_index', w którym przechowywana jest wartość początkowej klasyfikacji dla późniejszego wykorzystania w trakcie procesu DS.

Wartość `skb->tc_index' zostaje początkowo ustawiona przez qdisc DSMARK, przez pobranie pola DS z nagłówka pakietu IP. Poza tym, klasyfikator `cls_tcindex' przeczyta całość lub część pola `skb->tc_index' i użyje tej wartości by wybrać klasy.

Przyjrzyjmy się najpierw komendzie qdisc DSMARK i jej parametrom:

... dsmark indices INDICES [ default_index DEFAULT_INDEX ] [ set_tc_index ]
Co oznaczają?

  • indices: rozmiar tabeli par (maska,wartość). Maksymalna wartość to 2ˆn, gdzie n>=0.

  • Default_index: domyślny wskaźnik na wpis w tabeli, jeśli klasyfikator nie dopasuje żadnego warunku.

  • Set_tc_index: instruuje proces dsmark by pobrać pole DS i zapisać je do `skb->tc_index'.

Przyjrzyjmy się procesowi DSMARK.

14.3.5. Jak działa SCH_DSMARK.

Kolejka wykonuje następujące kroki:

  • Jeśli podano opcję `set_tc_index' w komendzie qdisc, pole DS jest zczytywane z pakietu i przechowywane w zmiennej `skb->tc_index'.

  • Wywoływany jest klasyfikator. Wynikiem jego działania jest identyfikator klasy, który zapisany zostanie w zmiennej `skb->tc_index' (jeśli nie znajdzie się żaden filtr, który pasuje, używana jest wartość `default_index' - a jeśli jej nie ma, zachowanie może być nieprzewidywalne).

  • Po wysłaniu do wewnętrznych qdisc, w których możesz użyć wartości w któregoś z filtrów, identyfikator klasy zwrócony przez wewnętrzne qdisc zostaje zapisany do `skb->tc_index'. Wartość tej zmiennej zostanie użyta w przyszłości, by wskazać indeks w tabeli maska-wartość. Końcowa wartość przypisana pakietowi zostanie uzyskana po wykonaniu następującej operacji:

    Nowe_Pole_DS = ( Stare_Pole_DS & maska ) | wartość

  • To znaczy, wartość końcowa będzie wynikiem operacji logicznej `i' na starym polu DS i masce, oraz wynikiem operacji logicznej `lub' z parametrem wartości. Spójrz na poniższy diagram by zrozumieć ten proces:

                         skb->ihp->tos
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >
     |                                                       |     ^
     | -- If you declare set_tc_index, we set DS             |     |  <-----May change
     |    value into skb->tc_index variable                  |     |O       DS field
     |                                                      A|     |R
   +-|-+      +------+    +---+-+    Internal   +-+     +---N|-----|----+
   | | |      | tc   |--->|   | |-->  . . .  -->| |     |   D|     |    |
   | | |----->|index |--->|   | |     Qdisc     | |---->|    v     |    |
   | | |      |filter|--->| | | +---------------+ |   ---->(mask,value) |
-->| O |      +------+    +-|-+--------------^----+  /  |  (.  ,  .)    |
   | | |          ^         |                |       |  |  (.  ,  .)    |
   | | +----------|---------|----------------|-------|--+  (.  ,  .)    |
   | | sch_dsmark |         |                |       |                  |
   +-|------------|---------|----------------|-------|------------------+
     |            |         | <- tc_index -> |       |
     |            |(read)   |    may change  |       |  <--------------Index to the
     |            |         |                |       |                    (mask,value)
     v            |         v                v       |                    pairs table
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->
                         skb->tc_index

Jak wykonać oznaczanie pakietu? Zmień maskę i wartość klasy, którą chciałbyś komentować. Spójrz na następującą linijkę:

tc class change dev eth0 classid 1:1 dsmark mask 0x3 value 0xb8
Zmienia to parę (maska,wartość) w tablicy mieszającej powodując oznaczenie pakietów należących do klasy 1:1. Musisz `zmienić' te wartości z uwagi na domyślne wartości, które para (maska,wartość) otrzymuje przy inicjalizacji (zobacz tabelę poniżej).

Teraz wytłumaczymy jak działa filtr TC_INDEX i jak wpasowuje się w to wszystko. Oprócz pracy z usługami DS, TC_INDEX może być używany w innych konfiguracjach.

14.3.6. Filtr TC_INDEX

Poniżej podstawowa komenda deklarująca filtr TC_INDEX:

... tcindex [ hash ROZMIAR ] [ mask MASKA ] [ shift PRZESUNIĘCIE ]
            [ pass_on | fall_through ]
            [ classid CLASSID ] [ police OKREŚLENIE_POLITYKI ]
Pokażemy teraz przykład by wyjaśnić tryb pracy TC_INDEX. Zwróć uwagę na wyróżnione słowa:
tc qdisc add dev eth0 handle 1:0 root dsmark indices 64 \
 set_tc_index
tc filter add dev eth0 parent 1:0 protocol ip prio 1 \ 
 tcindex mask 0xfc shift 2
tc qdisc add dev eth0 parent 1:0 handle 2:0 cbq bandwidth 10Mbit \
 cell 8 avpkt 1000 mpu 64
# EF traffic class
tc class add dev eth0 parent 2:0 classid 2:1 cbq bandwidth 10Mbit \
 rate 1500Kbit avpkt 1000 prio 1 bounded isolated allot 1514 weight 1 maxburst 10
# Packet fifo qdisc for EF traffic
tc qdisc add dev eth0 parent 2:1 pfifo limit 5
tc filter add dev eth0 parent 2:0 protocol ip prio 1 \
 handle 0x2e tcindex classid 2:1 pass_on
(Powyższy kod nie jest kompletny. Pochodzi z przykładu dla EFCBQ dostarczanego z dystrybucją iproute2).

Po pierwsze, załóżmy że otrzymaliśmy pakiet oznaczony `EF'. Jeśli zapoznasz się z RFC2598 dowiesz się, że rekomendowaną przez DSCP wartością dla ruchu `EF' jest 101110. Oznacza to, że pole DS będzie miało wartość 10111000 (pamiętaj, że mniej znaczące bity w bajcie ToS nie są używane przez DS), lub w zapisie heksdecymalnym 0xB8.

              TC INDEX
              FILTER
   +---+      +-------+    +---+-+    +------+                +-+    +-------+
   |   |      |       |    |   | |    |FILTER|  +-+    +-+    | |    |       |
   |   |----->| MASK  | -> |   | | -> |HANDLE|->| |    | | -> | | -> |       |
   |   |  .   | =0xfc |    |   | |    |0x2E  |  | +----+ |    | |    |       |
   |   |  .   |       |    |   | |    +------+  +--------+    | |    |       |
   |   |  .   |       |    |   | |                            | |    |       |
-->|   |  .   | SHIFT |    |   | |                            | |    |       |-->
   |   |  .   | =2    |    |   | +----------------------------+ |    |       |
   |   |      |       |    |   |       CBQ 2:0                  |    |       |
   |   |      +-------+    +---+--------------------------------+    |       |
   |   |                                                             |       |
   |   +-------------------------------------------------------------+       |
   |                          DSMARK 1:0                                     |
   +-------------------------------------------------------------------------+

A więc dociera pakiet, z polem DS ustawionym na wartość 0xB8. Tak jak wytłumaczyliśmy wcześniej, kolejka DSMARK identyfikowana w tym przykładzie przez wartość 1:0, pobiera wartość z pola DS i zapisuje je w zmiennej `skb->tc_index'. Następny krok w przykładzie będzie dotyczył filtra skojarzonego z tą qdisc (druga linijka w przykładzie). Wykona to następujące operacje:

Wartość1 = skb->tc_index & MASKA
Klucz = Value1 >> PRZESUNIĘCIE

W tym przykładzie, MASKA=0xFC a PRZESUNIĘCIE=2.

Wartość1 = 10111000 & 11111100 = 10111000
Klucz = 10111000 >> 2 = 00101110 -> 0x2E heksdecymalnie

Zwrócona wartość odpowiadać będzie uchwytowi wewnętrznego filtra w qdisc (w tym przykładzie, identyfikatorowi 2:0). Jeśli istnieje filtr z taką wartością id, sprawdzone zostaną odpowiednie instrukcje dotyczące polityki oraz ograniczeń przepustowości/częstotliwości (w tym przypadku filtr je zawiera) i zwrócona zostanie wartość identyfikatora klasy (w naszym przypadku, 2:1), która z kolei zostanie zapisana do zmiennej `skb->tc_index'.

Jednak gdy znaleziony zostanie filtr z danym identyfikatorem, rezultat zależeć będzie od deklaracji flagi `fall_through'. Jeśli jest ona ustawiona, jako identyfikator klasy zwracany jest identyfikator klasy. Jeśli nie, zwracany jest błąd i proces kontynuowany jest na reszcie filtrów. Użycie flagi `fall_through' wymaga jednak ostrożności; powinno odbywać się tylko gdy istnieje prosta relacja między wartościami `skb->tc_index' a identyfikatorem klasy.

Ostatnie parametry, które skomentujemy to wartość mieszająca i `pass_on'. Pierwszy odnosi się do rozmiaru tabeli mieszającej. `pass_on' jest z kolei używany do wskazania, że jeśli nie znaleziony zostanie identyfikator klasy równy zwróconemu wynikowi, należy kontynuować sprawdzanie na następnym filtrze. Domyślną akcją jest `fall_through' (spójrz na następną tabelę).

Spójrzmy na koniec na wartości możliwe do ustawienia w parametrach TC_INDEX:

Nazwa TC                Wartość         Domyślnie
-----------------------------------------------------------------
Hash                    1...0x10000     Zależne od implementacji
Maska                   0...0xffff      0xffff
Przesunięcie            0...15          0
Fall through / Pass_on  Flaga           Fall_through
Identyfikator klasy     Major:minor     żadna
Polityka                .....           żadna

Ten rodzaj filtra jest bardzo potężny i niezbędne jest zapoznanie się z wszystkimi jego możliwościami. Poza tym, nie jest to jedyny filtr, którego można użyć w konfiguracjach DiffServ - można go używać tak jak każdego innego rodzaju filtru.

Polecam zapoznanie się z przykładami DiffServ zawartymi w dystrybucji iproute2. Obiecuję, że uzupełnie ten tekst tak szybko jak będę mógł, poza tym wszystko co wytłumaczyłem jest rezultatem całej masy testów. Chciałbym podziękować wszystkim, którzy wytkną mi ewentualne błędy.


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