Symuluj wolne połączenie między dwoma maszynami serwerowymi Ubuntu

9

Chcę zasymulować następujący scenariusz: biorąc pod uwagę, że mam 4 maszyny serwerowe Ubuntu A, B, C i D. Chcę zmniejszyć przepustowość sieci o 20% między maszyną A i maszyną C oraz o 10% między maszyną A i B. zrobić to za pomocą narzędzi do symulacji sieciowej / ograniczania przepustowości?

Yehia Elshater
źródło
iptables może mieć zdolność dławienia. Nigdy go nie użyłem, ale warto się temu przyjrzeć.
Michael Martinez
@MichaelMartinez Nie, nie ma. tcdziała, gdy jest używany z oznaczeniem iptables.
Xavier Lucas
@XavierLucas dobrze wiedzieć!
Michael Martinez

Odpowiedzi:

15

Aby to zrobić, możesz użyć tcsamego z u32filtrami lub w połączeniu ze znakowaniem iptables (być może bardziej proste, jeśli nie chcesz nauczyć się składni filtrów złożonych). W następnym poście szczegółowo opiszę poprzednie rozwiązanie.


Symulowanie konfiguracji

Jako przykład rozważmy A, B, C i D z uruchomionymi wirtualnymi interfejsami 10 Mbit / s .

Zasadniczo chcesz:

  • A <==> B: kształtowanie 9 Mbit / s dla wyjścia
  • A <==> C: kształtowanie 8 Mbit / s dla wyjścia

Aby to zasymulować, utworzę 4 sieciowe przestrzenie nazw i wirtualne interfejsy Ethernet podłączone do mostka.

Oczywiście w twoim przypadku będziesz pracować z prawdziwymi kartami sieciowymi, a most będzie twoją bramą lub przełącznikiem w zależności od infrastruktury.

W mojej symulacji będziemy mieli następującą konfigurację w sieci 10.0.0.0/24:

                                  10.0.0.254            

                                  +-------+                     
                                  |       |                     
                                  |  br0  |                     
                                  |       |                   
                                  +---+---+                     
                                      |                         
                                      | veth{A..D}.peer        
                                      |                      
                  +------------+------+-----+------------+     
                  |            |            |            |      
            vethA |      vethB |      vethC |      vethD |      
              +---+---+    +---+---+    +---+---+    +---+---+  
              |       |    |       |    |       |    |       |   
              |   A   |    |   B   |    |   C   |    |   D   |   
              |       |    |       |    |       |    |       |  
              +-------+    +-------+    +-------+    +-------+    

              10.0.0.1      10.0.0.2     10.0.0.3     10.0.0.4           

Po pierwsze, fazę konfiguracji, abyś mógł zrozumieć, z czego jest wykonana, pomiń ją, jeśli nie jesteś z nią zaznajomiony, nic wielkiego. Musisz jednak wiedzieć, że polecenie ip netns exec <namespace> <command>pozwala wykonać polecenie w sieciowej przestrzeni nazw (tj. W jednym z pól poprzedniego losowania). Zostanie to wykorzystane również w następnej sekcji.

# Create the bridge
ip link add br0 type bridge

# Create network namespaces and veth interfaces and plug them into the bridge
for host in {A..D} ; do 
    ip link netns add ${host}
    ip link add veth${host} type veth peer name veth${host}.peer
    ip link set dev veth${host}.peer master br0
    ip link set dev veth${host} netns ${host}
    ip netns exec ${host} ip link set veth${host} up
done

# Assign IPs
ip addr add 10.0.0.254/24 dev br0
ip netns exec A ip addr add 10.0.0.1/24 dev vethA
ip netns exec B ip addr add 10.0.0.2/24 dev vethB
ip netns exec C ip addr add 10.0.0.3/24 dev vethC
ip netns exec D ip addr add 10.0.0.4/24 dev vethD

W tym momencie mamy opisaną wcześniej konfigurację.


Kształtowanie ruchu

Czas przejść do kontroli ruchu, aby uzyskać to, czego chcesz. tcNarzędzie pozwala na dodanie dyscyplin kolejkowania:

  • Dla wyjścia: gdy jądro musi wysłać pakiety i przed uzyskaniem dostępu do sterownika karty sieciowej.
  • Do wejścia: po uzyskaniu dostępu do sterownika karty sieciowej i przed uruchomieniem procedur jądra dla odebranych pakietów.

Zawiera 3 pojęcia: qdisc , klasy i filtry . Pojęć tych można używać do konfigurowania zarządzania złożonym przepływem pakietów i ustalania priorytetów ruchu na podstawie dowolnych kryteriów / kryteriów.

W skrócie :

  • Qdisc są strukturami, w których pakiety będą zwykle kolejkowane / usuwane z kolejki.
  • Klasy są pojemnikami na qdisc działającymi z określonymi zachowaniami.
  • Filtry to sposoby kierowania pakietów między klasami, wiele z nich można zdefiniować w tym samym punkcie wejścia z priorytetami podczas przetwarzania.

Wszystko to zwykle działa jako drzewo, w którym liście są qdisc, a klasy są węzłami. Katalog główny drzewa lub poddrzewa zostanie zadeklarowany jako, <id>:a węzły podrzędne zostaną zadeklarowane jako <parent_id>:<children_id>. Pamiętaj o tej składni.

W twoim przypadku weźmy A i wyrenderuj drzewo, które chcesz skonfigurować tc:

                                     1:
                                      |
                                      |
                                      |
                                     1:1
                                   /  |  \
                                  /   |   \
                                 /    |    \
                               1:10  1:20  1:30
                                |     |     |
                                |     |     |
                               :10   :20   :30

Objaśnienie:

  • 1:jest qdisc root dołączony do urządzenia vethA, zostanie on wzięty jawnie jak w htbprzypadku Hierarchy Token Bucket (domyślna qdisc urządzenia to pfifolub pfifo_fastzależy od systemu operacyjnego). Jest to szczególnie odpowiednie do zarządzania pasmem. Pakiety niepasujące do filtrów zdefiniowanych na tym poziomie trafią do 1:30klasy.
  • 1:1będzie htbklasą ograniczającą cały ruch urządzenia do 10 Mbit / s.
  • 1:10będzie htbklasą ograniczającą ruch wyjściowy do 9 Mbit / s (90% z 10 Mbit / s).
  • 1:20będzie htbklasą ograniczającą ruch wyjściowy do 8 Mbit / s (80% z 10 Mbit / s).
  • 1:30będzie htbklasą ograniczającą ruch do 10 Mbit / s (awaryjne).
  • :10, :20, :30sfqqdisc dla Kolejkowania Stochastic Fairness. Innymi słowy, te qdisc zapewnią uczciwość w planowaniu transmisji w oparciu o przepływy.

Całą tę konfigurację wykonują następujące polecenia:

ip netns exec A tc qdisc add dev vethA root handle 1: htb default 30
ip netns exec A tc class add dev vethA parent 1: classid 1:1 htb rate 10mbit burst 15k
ip netns exec A tc class add dev vethA parent 1:1 classid 1:10 htb rate 9mbit burst 15k
ip netns exec A tc class add dev vethA parent 1:1 classid 1:20 htb rate 8mbit burst 15k
ip netns exec A tc class add dev vethA parent 1:1 classid 1:30 htb rate 10mbit burst 15k
ip netns exec A tc qdsic add dev vethA parent 1:10 handle 10: sfq perturb 10
ip netns exec A tc qdisc add dev vethA parent 1:20 handle 20: sfq perturb 10
ip netns exec A tc qdisc add dev vethA parent 1:30 handle 30: sfq perturb 10

Ostatnią rzeczą, której potrzebujemy, jest dodanie filtrów, aby pakiety IP z docelowym adresem IP równym B trafiły do 1:10klasy, a pakiety IP z docelowym adresem IP równym C trafiły do 1:20klasy:

ip netns exec A tc filter add dev vethA parent 1: protocol ip prio 1 u32 match ip dst 10.0.0.2/32 flowid 1:10
ip netns exec A tc filter add dev vethA parent 1: protocol ip prio 2 u32 match ip dst 10.0.0.3/32 flowid 1:20

Teraz, gdy wpadłeś na ten pomysł, musisz dodać podobne tcreguły do ​​B i C, aby nadać kształt również transmisjom w kierunku A z tych platform.


Testowanie

Teraz przetestujmy to. W tym celu jestem osobiście przyzwyczajony do gry iperf, po prostu składa się z pojedynczego pliku binarnego, który można uruchomić jako klient lub serwer i automatycznie wysyła jak najwięcej ruchu między dwoma hostami.

Pomiędzy A i B :

 $ ip netns exec B iperf -s -p 8001
  ...
 $ ip netns exec A iperf -c 10.0.0.2 -p 8001 -t 10 -i 2
------------------------------------------------------------
Client connecting to 10.0.0.2, TCP port 8001
TCP window size: 21.0 KByte (default)
------------------------------------------------------------
[  5] local 10.0.0.1 port 58191 connected with 10.0.0.2 port 8001
[ ID] Interval       Transfer     Bandwidth
[  5]  0.0- 2.0 sec  2.38 MBytes  9.96 Mbits/sec
[  5]  2.0- 4.0 sec  2.12 MBytes  8.91 Mbits/sec
[  5]  4.0- 6.0 sec  2.00 MBytes  8.39 Mbits/sec
[  5]  6.0- 8.0 sec  2.12 MBytes  8.91 Mbits/sec
[  5]  8.0-10.0 sec  2.00 MBytes  8.39 Mbits/sec
[  5]  0.0-10.1 sec  10.8 MBytes  8.91 Mbits/sec

Otrzymujemy nasz limit przepustowości 9 Mbit / s .

Pomiędzy A i C:

$ ip netns exec C iperf -s -p 8001
...
$ ip netns exec A iperf -c 10.0.0.3 -p 8001 -t 10 -i 2
------------------------------------------------------------
Client connecting to 10.0.0.3, TCP port 8001
TCP window size: 21.0 KByte (default)
------------------------------------------------------------
[  5] local 10.0.0.1 port 58522 connected with 10.0.0.3 port 8001
[ ID] Interval       Transfer     Bandwidth
[  5]  0.0- 2.0 sec  2.25 MBytes  9.44 Mbits/sec
[  5]  2.0- 4.0 sec  1.75 MBytes  7.34 Mbits/sec
[  5]  4.0- 6.0 sec  1.88 MBytes  7.86 Mbits/sec
[  5]  6.0- 8.0 sec  1.88 MBytes  7.86 Mbits/sec
[  5]  8.0-10.0 sec  1.75 MBytes  7.34 Mbits/sec
[  5]  0.0-10.1 sec  9.62 MBytes  7.98 Mbits/sec

Otrzymujemy nasz limit przepustowości 8 Mbit / s .

Pomiędzy A i D:

$ ip netns exec D iperf -s -p 8001
...
$ ip netns exec A iperf -c 10.0.0.4 -p 8001 -t 10 -i 2
------------------------------------------------------------
Client connecting to 10.0.0.4, TCP port 8001
TCP window size: 21.0 KByte (default)
------------------------------------------------------------
[  5] local 10.0.0.1 port 40614 connected with 10.0.0.4 port 8001
[ ID] Interval       Transfer     Bandwidth
[  5]  0.0- 2.0 sec  2.62 MBytes  11.0 Mbits/sec
[  5]  2.0- 4.0 sec  2.25 MBytes  9.44 Mbits/sec
[  5]  4.0- 6.0 sec  2.38 MBytes  9.96 Mbits/sec
[  5]  6.0- 8.0 sec  2.25 MBytes  9.44 Mbits/sec
[  5]  8.0-10.0 sec  2.38 MBytes  9.96 Mbits/sec
[  5]  0.0-10.2 sec  12.0 MBytes  9.89 Mbits/sec

Tutaj mamy osiągnięty wirtualny interfejs z pełną prędkością 10 Mbit / s .

Zauważ, że seria pierwszego pomiaru każdego przebiegu może być lepiej obsługiwana w htbklasach poprzez dostosowanie odpowiedniego parametru.


Sprzątanie

Usuwać :

  • Filtr priorytetu 1 na 1:: tc filter del dev vethA parent 1: prio 1 u32.
  • Wszystkie filtry na 1:: tc filter del dev vethA parent 1:.
  • Klasa 1:20i jej dzieci: tc class del dev vethA parent 1:1 classid 1:20.
  • Całe drzewo: tc qdisc del dev vethA.

Aby wyczyścić zestaw symulacji:

# Remove veth pairs and network namespaces
for host in {A..D} ; do
    ip link del dev veth${host}.peer
    ip netns del ${host}
done

# Remove the bridge
ip link del dev br0
Xavier Lucas
źródło
1
Wielkie dzięki za niesamowitą odpowiedź. Jeśli to możliwe, czy możesz dodać polecenia, aby usunąć filtry? na wypadek, gdyby ktoś chciał bezpiecznie przywrócić tę konfigurację po symulacji.
Yehia Elshater,
1
@YahiaZakaria Właśnie dodałem tę informację w dalszej części mojego postu.
Xavier Lucas
0

Ubuntu ma IPFW przeniesione z FreeBSD, a IPFW ma DUMMYNET, które pozwalają zarządzać różnymi parametrami sieci - przepustowością, opóźnieniem, szybkością utraty pakietów itp.

Kondybas
źródło
0

Najlepiej jest użyć narzędzi tc ze zintegrowanym teraz (przynajmniej na serwerze Ubuntu) modułem netem. Więcej informacji można znaleźć w tym artykule z Stackoverflow .

Luc Stepniewski
źródło
Netem dotyczy emulacji rtt i przeciążenia, a nie pasma.
Xavier Lucas,
1
@XavierLucas, masz rację, do przepustowości potrzebujesz tylko tc, nawet bez netem.
Luc Stepniewski
0

Trickle działa dobrze.

Ta dyskusja pokazuje pewne ograniczenia: /unix/109973/how-to-change-speed-limit-of-running-trickle-instance

Mathew
źródło
Trickle służy do symulacji przepustowości sieci dla określonego programu. Wydaje się, że PO szuka rozwiązania w zakresie gospodarza.
Xavier Lucas
Trickled można wykorzystać do symulacji grupy połączeń (nie tylko jednego połączenia). Rzeczywiście pytanie to można interpretować jako „wszystkie połączenia host-host”.
Mathew