Kształtowanie ruchu

(Ukradzione z http://www.cs.put.poznan.pl/ddwornikowski/sieci/sieci2/ts.html)

Wprowadzenie

Potrzeba sterowania ruchem w sieciach komputerowych wynika głównie z faktu, że obecnie zapotrzebowanie na usługi sieciowe rośnie w szybszym tempie, niż aktualne możliwości sieci. Sterowanie takie można podzielić na dwie kategorie:

  • kształtowanie ruchu (ang. traffic shaping) - wpływanie na to jak dane są wysyłane, poprzez ich opóźnianie lub odrzucanie,
  • równoważenie obciążeń (ang. load balancing) - wybór drogi w celu równoważenia obciążenia sieci lub zasobów.

Jednym z protokołów wspierających kontrolę przepływu pakietów jest protokół TCP, który pozwala transmitującym systemom dostosować się do poziomu ruchu i warunków w sieci. Jednak aby w pełni kształtować ruch w sieci konieczne są dodatkowe mechanizmy kontrolne; wykorzystuje się zatem w tym celu głównie tzw. algorytmy kolejkowania pakietów (ang. queueing discipline) – często nazywane dyscyplinami kolejkowania lub kolejkami. Kolejki obsługiwane przez interfejsy sieciowe można podzielić na dwie grupy:

  • kolejki proste (bezklasowe) - taki jak FIFO, które określają w jaki sposób pakiety są traktowane przez system, bez możliwości zagnieżdżania innych kolejek,
  • kolejki złożone (klasowe) - które mogą być rozbudowaną strukturą, zawierającą inne kolejki oraz filtry i klasy.

Kolejki bezklasowe

Pfifo_fast

Najprosztą i domyślną w systemach Linux, kolejką jest kolejka pfifo_fast. Składa się ona z trzech osobnych kolejek FIFO, zwanych pasmami. Pasmo 0 ma najwyższy priorytet, pasmo 2 najniższy. Klasyfikowanie pakietów do pasm odbywa się na podstawie pola TOS (type of service) oraz kolejności nadchodzenia pakietów.

http://tldp.org/HOWTO/Traffic-Control-HOWTO/images/pfifo_fast-qdisc.png

Stochastic fair queueing (SFQ)

SFQ zapewnia równomierne dystrybuowanie danych w sieci za pomocą pewnej liczby kolejek FIFO. Algorytm hashujący wewnątrz SFQ przydziela przepływy w sieci (czwórki sport:sip:dip:dport) do odpowiednich kolejek. Zapewnia to równe traktowanie dla każdego przepłwu. Funkcja hashująca zmieniana jest co jakiś czas, żeby zminimalizować nierównmierność (stąd stochastic).

http://tldp.org/HOWTO/Traffic-Control-HOWTO/images/sfq-qdisc.png

Pakiety dekolejkowane są zgodnie z algorytmem round-robin.

Token Bucket Filter

TBF działa w oparciu o żetony (tokens) w wiadrze, w przeciwieństwie do SFQ czy pfifo_fast, TBF jest pozwala na ogranicznie pasma. Z wiadrem (bucker) skojrzaony jest generator żetonów, które trafiają do wiadra. Z każdym cyklem z wiadra pobierany jest żeton (lub żetony) oraz porcja bajtów do wysłania.

http://tldp.org/HOWTO/Traffic-Control-HOWTO/images/tbf-qdisc.png

Możliwe są trzy sytuacje:

  • pakiety nadchodzą z częstością generowania żetonów - wtedy pakiety dekolejkowane są bez opóźnień,
  • pakiety nadchodzą z częstością mniejszą od generowania żetonów - pakiety są dekolejkowane bez opóźnień, co jakiś czas możliwe jest wysyłanie pakietów z większą prędkością w seriach (bursts)
  • pakiety nadchodzą z częstością większą od żetonów - żetony w wiadrze się wyczerpią i pakiety będą opóźniane, aż w końcu odrzucane.

Koleki klasowe (złożone)

W skład kolejki złożonej wchodzą: kolejki bezklasowe, filtry oraz klasy. Klasy są kontenerami dla innych dyscyplin kolejkowania; tworzą one strukturę drzewa, tj. każda klasa posiada jednego rodzica oraz jednego lub wielu potomków. Każda klasa posiada swój identyfikator (uchwyt), składający się z dwóch części: starszej (major, określający rodzica) oraz młodszej (minor, musi być unikalny w skali potomków tej samej klasy) – np. 1:0, co można zapisać także jako 1:, jest to identyfikator klasy korzenia. Podstawową metodą przydzielania ruchu do konkretnych klas jest zastosowanie filtrów pakietów, które dokonują klasyfikacji na podstawie wybranych parametrów, takich jak np. adres źródłowy lub docelowy, nr portów itp. Kolejki proste w klasach decydują o sposobie obsługi pakietów, które trafiły do danej klasy.

Kiedy jądro systemu zdecyduje się pobrać pakiet z kolejki złożonej, to pakiet ten będzie pochodził z jeden z dyscyplin kolejkowania należącej do jednej z klas. Tak więc kolejka złożona może priorytetyzować pewną część ruchu poprzez usiłowanie zdjęcia pakietów z jednej ze swoich kolejek wcześniej niż z innych (główny algorytm kolejkowania).

          1:   dyscyplina korzenia
           |
          1:1    podklasa
        /  |  \
       /   |   \
      /    |    \
      /    |    \
   1:10  1:11  1:12   podklasy
    |      |     |
    |     11:    |    klasy liści
    |            |
    10:         12:   dyscyplina kolejkowania
   /   \       /   \
10:1  10:2   12:1  12:2   klasy liści

PRIO

O PRIO można myśleć jak o pfifo_fast w wersji klasowej, tzn. możliwe jest definiowanie poprzez filtry do których kolejek trafi ruch wychodzący. Domyślnie także 3 kolejki wewnętrzne są definiowane z dyscyplinami FIFO, jednakże mogą one być zamienione na dowolną dyscyplinę kolejkującą.

Przykład PRIO:

          1:   root qdisc
         / | \
       /   |   \
       /   |   \
     1:1  1:2  1:3    classes
      |    |    |
     10:  20:  30:    qdiscs    qdiscs
     sfq  tbf  sfq
band  0    1    2

Hierarchical Token Bucket

HTB jest hierarchiczną, klasową wersją TBF, z zaimplementowaną zaawansowanym mechnizmem pożyczania pasma. Każda podklasa może pożyczać wolne pasmo z nadklasy, gdy przekroczy próg minimalnego pasma (rate). Pożycza pasma, aż do osiągnięcia pasma maksymalnego (ceil). W ten sposób możliwe jest zaimplementowanie złożonego mechanizmu dzielenia pasma “do” jakiejść wielkości, a jednocześnie dawać pasma gwarantowane. Kształtowanie ruchu zachodzi jedynie w liściach.

http://tldp.org/HOWTO/Traffic-Control-HOWTO/images/htb-borrow.png

Przykład

  • Dostępne pasmo: 100 kbps (kilobajtów na sekundę)
  • Klient A: 40 kbps (30 kbps na WWW, 10 kbps na resztę)
  • Klient B: 60 kbps
      1:    root htb
       |
      1:1   htb rate 100, ceil 100
     / | \
    /  |  \
   /   |   \
 1:10 1:12 1:13  klasy dla klientów
  |    |    |
 20:  30:  40:    qdiscs    qdiscs
pfifo pfifo sfq

Przykład poprawiony

          1:    root htb
           |
          1:1   htb rate 100, ceil 100
         /   \
        /     \
       /       \
     1:2(A)   1:12(B)
     / \       |
    /   \     40:    qdiscs    qdiscs
   /     \    sfq
 1:10   1:11
  |       |
 20:     30:
pfifo   pfifo

Narzędzie tc w systemie Linux

Listowanie dyscyplin ze statystykami:

# tc -s -d qdisc show dev eth0

Listowanie klas ze statystykami:

# tc -s -d class show dev eth0

Kasowanie całkowite konfiguracji:

# tc qdisc del root dev ethX

Dodawanie filtrów:

Ruch z polem destination ip = 4.3.2.1 -> klasa 10:1. Filtry doklejamy do 1:0 zawsze.

#  tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip dst 4.3.2.1/32 flowid 10:1

Ruch z portu 80 do klasy 10:1

#  tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip sport 80 0xffff flowid 10:1

Ruch na port 22 do klasy 10:1

#  tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip dport 22 0xffff flowid 10:1

Filtr z priorytetem niższym niż 1, (ruch pozostały) do 10:2:

#  tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 10:2

Przykłady

Przykład PRIO: można zapisać za pomocą tc w następujący sposób:

# 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: tbf rate 20kbit buffer 1600 limit 3000

htb1:

# tc qdisc add dev eth0 root handle 1: htb default 12
# tc class add dev eth0 parent 1: classid 1:1 htb rate 100kbps ceil 100kbps
# tc class add dev eth0 parent 1:1 classid 1:10 htb rate 30kbps ceil 100kbps
# tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10kbps ceil 100kbps
# tc class add dev eth0 parent 1:1 classid 1:12 htb rate 60kbps ceil 100kbps

# 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

# tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src <IP A> match ip dport 80 0xffff flowid 1:10
# tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src <IP A> flowid 1:11

Ćwiczenia

  1. Zaimplementuj Przykład PRIO:, jak w przykładzie, przegraj pliku przez scp na inny host. Gdzie trafił ten ruch?
  2. Wygeneruj jakiś ruch interaktywny, gdzie trafił?
  3. Włącz serwer WWW (Apache) na swoim komputerze, stwórz plik o rozmiarze 1GB (fallocate -l 1g plik.txt). Spraw aby był dostępny przez WWW z twojgo komputera.
  4. Zaimplementuj scenariusz bazując luźno na htb1. Ogranicz pasmo całkowite do 15mbps. Klientami będą komputery koleżanek/kolegów. Klient A może sciągac plik z prędkością 5/15 mbps, Klient B 10/15mbs. Przetestuj ściagając plik od siebie komenda np. wget.