Имитация медленного соединения между двумя компьютерами с Ubuntu

9

Я хочу смоделировать следующий сценарий: учитывая, что у меня есть 4 сервера Ubuntu A, B, C и D. Я хочу уменьшить пропускную способность сети на 20% между машиной A и машиной C и 10% между A и B. Как сделать это с помощью инструментов моделирования / регулирования сети?

Yehia Elshater
источник
Iptables может иметь способность дросселирования. Я никогда не использовал это, но стоит посмотреть.
Майкл Мартинес
@MichaelMartinez Нет, это не так. tcделает при использовании с маркировкой iptables.
Ксавье Лукас
@XavierLucas приятно знать!
Майкл Мартинес

Ответы:

15

Для этого вы можете использовать tcодин с u32фильтрами или в сочетании с маркировкой iptables (возможно, более простым, если вы не хотите изучать синтаксис сложных фильтров). В следующем посте я подробно расскажу о первом решении.


Имитация вашей настройки

В качестве примера рассмотрим A, B, C и D с виртуальными интерфейсами со скоростью 10 Мбит / с .

Вы в основном хотите:

  • A <==> B: 9 Мбит / с для выхода
  • A <==> C: 8 Мбит / с для выхода

Чтобы смоделировать это, я создам 4 сетевых пространства имен и виртуальные интерфейсы Ethernet, подключенные к мосту.

Конечно, в вашем случае вы будете работать с реальными сетевыми картами, и мост будет вашим шлюзом или коммутатором в зависимости от вашей инфраструктуры.

Таким образом, в моей симуляции у нас будет следующая настройка в сети 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           

Во-первых, этап установки, чтобы вы могли понять, из чего он сделан, пропустить его, если вы не знакомы с ним, ничего страшного. Однако вы должны знать, что команда ip netns exec <namespace> <command>позволяет выполнить команду в сетевом пространстве имен (т.е. в одном из полей предыдущего рисования). Это также будет использовано в следующем разделе.

# 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

Итак, на данный момент у нас есть настройки, описанные ранее.


Формирование трафика

Пришло время войти в управление движением, чтобы получить то, что вы хотите. tcИнструмент позволяет добавлять организации очередей:

  • Для выхода: однажды ядру нужно отправить пакеты и перед доступом к драйверу NIC.
  • Для входа: после доступа к драйверу NIC и до запуска подпрограмм ядра над полученными пакетами.

Он поставляется с 3 понятиями: qdisc , классы и фильтры . Эти понятия можно использовать для настройки управления сложным потоком пакетов и определения приоритетов трафика на основе любого критерия / критериев, которые вы хотите.

В двух словах :

  • Qdiscs - это структуры, в которых пакеты будут ставиться в очередь / исключаться из очереди.
  • Классы являются контейнерами для qdiscs, действующих с определенным поведением.
  • Фильтры - это способы маршрутизации пакетов между классами, несколько из которых могут быть определены в одной точке входа с приоритетами во время обработки.

Все это обычно работает как дерево, где листья - это qdiscs, а классы - это узлы. Корень дерева или поддерева будет объявлен как, <id>:а дочерние узлы будут объявлены как <parent_id>:<children_id>. Помните об этом синтаксисе.

Для вашего случая давайте возьмем A и отобразим дерево, которое вы хотели бы установить tc:

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

Пояснение:

  • 1:является корневым qdisc, присоединенным к устройству vethA, он будет принят явно, как htbдля Hierarchy Token Bucket (по умолчанию qdisc устройства является pfifoили pfifo_fastзависит от ОС). Это особенно подходит для управления полосой пропускания. Пакеты, не соответствующие фильтрам, определенным на этом уровне, перейдут в 1:30класс.
  • 1:1будет htbкласс, ограничивающий весь трафик устройства до 10 Мбит / с.
  • 1:10будет htbкласс, ограничивающий выходной трафик до 9 Мбит / с (90% от 10 Мбит / с).
  • 1:20будет htbкласс, ограничивающий выходной трафик до 8 Мбит / с (80% от 10 Мбит / с).
  • 1:30будет htbкласс, ограничивающий трафик до 10 Мбит / с (запасной вариант).
  • :10, :20, :30является sfqдисциплиной стохастической Fairness очереди. Другими словами, эти qdiscs обеспечат справедливость в планировании передачи, основанном на потоках.

Все это настраивается с помощью следующих команд:

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

Последнее, что нам нужно, это добавить фильтры, чтобы IP-пакеты с IP-адресом назначения, равным B, переходили в 1:10класс, а IP-пакеты с IP-адресом назначения, равным C, переходили в 1:20класс:

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

Теперь, когда вы поняли идею, вам нужно будет добавить похожие tcправила к B и C, чтобы также формировались передачи в направлении A от этих буровых установок.


тестирование

Теперь давайте проверим это. Для этого я лично привык играть iperf, он просто состоит из одного двоичного файла, который может быть запущен как клиент или как сервер, и автоматически отправляет как можно больше трафика между обоими хостами.

Между А и В:

 $ 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

Мы получаем наш предел пропускной способности 9 Мбит / с .

Между А и С:

$ 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

Мы получаем наш предел пропускной способности 8 Мбит / с .

Между А и 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

Здесь у нас виртуальный интерфейс достиг полной скорости 10 Мбит / с .

Обратите внимание, что пакет первого такта каждого прогона можно лучше обрабатывать в htbклассах, регулируя соответствующий параметр.


Убираться

Удалять :

  • Фильтр приоритета 1 на 1:: tc filter del dev vethA parent 1: prio 1 u32.
  • Все фильтры на 1:: tc filter del dev vethA parent 1:.
  • Класс 1:20и его дети tc class del dev vethA parent 1:1 classid 1:20.
  • Целое дерево tc qdisc del dev vethA.

Чтобы очистить набор симуляции:

# 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
Ксавье Лукас
источник
1
Большое спасибо за ваш удивительный ответ. Если возможно, не могли бы вы добавить команды для удаления фильтров? на всякий случай, если кто-то захочет безопасно откатить эту настройку после симуляции.
Yehia Elshater
1
@YahiaZakaria Я только что добавил эту информацию во второй части своего поста.
Ксавье Лукас
0

Ubuntu имеет IPFW, портированный из FreeBSD, а IPFW имеет DUMMYNET, который позволяет управлять различными параметрами сети - пропускной способностью, задержкой, скоростью потери пакетов и т. Д.

Kondybas
источник
0

Лучше всего использовать инструменты tc с теперь интегрированным (по крайней мере, в Ubuntu сервере) модулем netem. Вы можете найти больше информации в этой статье от Stackoverflow .

Люк Степневский
источник
Netem о rtt и эмуляции заторов, а не о полосе пропускания.
Ксавье Лукас
1
@ XavierLucas, вы правы, для пропускной способности вам просто нужен tc, даже без netem.
Люк Степневски,
0

Трикл работает хорошо.

Это обсуждение показывает некоторые ограничения: /unix/109973/how-to-change-speed-limit-of-running-trickle-instance

Mathew
источник
Trickle используется для имитации полосы пропускания сети для конкретной программы. ОП, кажется, ищет решение на уровне хоста.
Ксавье Лукас
Trickled может использоваться для имитации группы соединений (а не только одного соединения). Действительно, вопрос можно интерпретировать как «все соединения хост-хост».
Мэтью