Mininet. Введение в Iperf

Введение в Iperf.

1 Общая информация

1.1 Цели

  • Освоить основные приёмы работы с генератором трафика iperf3.

1.2 Задачи

  • Подготовить лабораторный стенд.
  • В процессе интерактивного эксперимента изучить основные опции и шаблоны использования генератора трафика iperf3.
  • Построить графики по данным интерактивного эксперимента.
  • В процессе воспроизводимого эксперимента получить представление о создании скриптов эксперимента.
  • Построить графики по данным воспроизводимого эксперимента.

1.3 Основные термины

  • Полоса пропускания (Bandwidth) — это физическое свойство среды передачи, которое зависит от таких факторов, как конструкция и длина провода или волокна.
    • Для сетевых инженеров пропускная способность — это максимальная скорость передачи данных канала, величина, измеряемая в битах в секунду (бит/с)
    • На производительность могут влиять несколько факторов, таких как задержка, потеря пакетов, джиттер и другие.
  • Пропускная способность (throughput) — это скорость в битах в секунду, с которой процесс-отправитель может доставлять биты процессу-получателю (при связи между двумя конечными устройствами).
    • Поскольку другие сеансы будут совместно использовать полосу пропускания по сетевому пути и поскольку эти другие сеансы будут повторяться, доступная пропускная способность может колебаться со временем
  • Иногда термины пропускная способность (throughput) и полоса пропускания (bandwidth) используются взаимозаменяемо.

1.4 Iperf3

  • iPerf3 — это инструмент для измерения пропускной способности сети в режиме реального времени.
  • Сайт: https://iperf.fr/.
  • Репозиторий: https://github.com/esnet/iperf.
  • Лицензия: 3-пунктовая лицензия BSD.
  • iPerf3 может работать с протоколами TCP, UDP и SCTP:
    • TCP и SCTP:
      • измерение пропускной способности;
      • размер MSS/MTU;
      • поддержка размера окна TCP.
    • UDP:
      • клиент может создавать потоки UDP с заданной пропускной способностью;
      • измерение потери пакетов;
      • измерение джиттера задержки;
      • поддержка групповой рассылки (multicast).

1.5 Графики по iperf3

  • Для построения графиков по iperf3 будем использовать пакет iperf3_plotter.
  • Репозиторий: https://github.com/ekfoury/iperf3_plotter.
  • Скрипты:
    • preprocessor.sh: преобразует файл JSON iPerf3 в файл значений, разделённых запятыми (CSV). Использует AWK для форматирования полей.
    • plot_iperf.sh: принимает JSON-файл iPerf3, вызывает препроцессор и вызывает gnuplot для создания выходных PDF-файлов.

1.6 Видео: Введение в Iperf. Введение

2 Подготовка стенда

2.1 Лабораторная топология

  • В топологии используется сеть 10.0.0.0/8, назначенная Mininet по умолчанию.
  • Топология представляет собой коммутатор с двумя подключёнными к нему хостами.
  • Для запуска топологии используем параметры командной строки:
    1sudo mn --topo=single,2 -x
    
  • Посмотрите топологию:
    1mininet> net
    2mininet> links
    3mininet> dump
    

2.2 Рабочие файлы

  • Подключимся к виртуальной машине:
    1ssh -Y mininet@192.168.x.y
    
  • Для рабочих файлов будем использовать каталог ~/work/lab_iperf3:
    1mkdir -p ~/work/lab_iperf3
    

2.3 Установка необходимого программного обеспечения

2.3.1 Конфигурация интерфейсов виртуальной машины

  • Добавьте к виртуальной машине интерфейс NAT.
  • Загрузите виртуальную машину и войдите в учётную запись mininet (пароль mininet).
  • Добавьте в файл /etc/netplan/01-netcfg.yaml второй интерфейс.
  • В результате файл примет следующий вид:
    1network:
    2  version: 2
    3  renderer: networkd
    4  ethernets:
    5    eth0:
    6      dhcp4: yes
    7    eth1:
    8      dhcp4: yes
    
  • Перезагрузите виртуальную машину.

2.3.2 Установка iperf3

  • По умолчанию стоит генератор трафика iperf2 (команда iperf).
  • Установим iperf3.
  • Загрузите виртуальную машину и войдите в учётную запись mininet:
    1ssh -Y mininet@192.168.x.y
    
  • Обновим список пакетов:
    1sudo apt-get update
    
  • Установите iperf3:
    1sudo apt-get install iperf3
    

2.3.3 Установка скриптов для визуализации результатов

  • Для функционирования скриптов необходимы следующие пакеты:
    • gnuplot;
    • jq;
    • awk.

2.3.4 Установка iperf3_plotter на виртуальную машину

  • Зайдём на виртуальную машину:

    1ssh -Y mininet@192.168.x.y
    
  • Обновим репозитории программного обеспечения на виртуальной машине:

    1sudo apt-get update
    
  • Установим необходимое программное обеспечение на виртуальную машину:

    1sudo apt-get install git jq gnuplot-nox mc
    
  • Скачаем iperf3_plotter. Для этого перейдём во временную рабочую папку и скачаем репозиторий:

    1cd /tmp
    2git clone https://github.com/ekfoury/iperf3_plotter.git
    
  • Установим iperf3_plotter:

    1cd /tmp/iperf3_plotter
    2sudo cp plot_* /usr/bin
    3sudo cp *.sh /usr/bin
    
  • Скрипты написаны плохо, не работают с путями, имеющими в названии пробелы.

2.3.5 Установка iperf3_plotter на локальный компьютер

  • Установим iperf3_plotter (на своём компьютере). Для этого перейдём во временную рабочую папку и скачаем репозиторий:
    1git clone https://github.com/ekfoury/iperf3_plotter.git
    
  • Заменим жёстко закодированные пути в файлах:
    1cd iperf3_plotter
    2sed -i -e "s:/usr/bin:~/.local/bin:g" plot_iperf.sh
    
  • Скопируем нужные файлы в каталог с локальными исполняемыми файлами:
    1cp plot_* ~/.local/bin
    2cp *.sh ~/.local/bin
    
  • Скрипты написаны плохо, не работают с путями, имеющими в названии пробелы.

2.4 Видео: Введение в Iperf. Подготовка стенда

3 Интерактивный эксперимент

3.1 Параметры команды iperf3

  • Пользователь взаимодействует с iPerf3 с помощью команды iperf3.

  • Основной синтаксис iperf3, используемый как на клиенте, так и на сервере, выглядит следующим образом:

    1iperf3 [-s|-c] [ options ]
    
    • -s: запуск сервера;
    • -c: запуск клиента.

3.2 Запуск клиента и сервера

  • Запустим mininet:

    1sudo mn --topo=single,2 -x
    
  • В терминале h2 запустите сервер:

    1iperf3 -s
    
    • Теперь сервер прослушивает порт 5201 в ожидании входящих подключений.
  • В терминале h1 запустите клиента:

    1iperf3 -c 10.0.0.2
    
    • Параметр -c указывает, что хост h1 настроен как клиент.
    • Параметр 10.0.0.2 — это IP-адрес сервера (хост h2).
  • После завершения теста отображается сводный отчет как на клиенте, так и на сервере, содержащий следующие данные:

    • ID: идентификационный номер соединения.
    • Интервал (Interval): временной интервал для периодических отчетов о пропускной способности. По умолчанию временной интервал равен 1 секунде.
    • Передача (Transfer): сколько данных было передано за каждый интервал времени.
    • Пропускная способность (Bitrate): измеренная пропускная способность в каждом временном интервале.
    • Retr: количество повторно переданных TCP-сегментов за каждый временной интервал. Это поле увеличивается, когда TCP-сегменты теряются в сети из-за перегрузки или повреждения.
    • Cwnd: указывает размер окна перегрузки в каждом временном интервале. TCP использует эту переменную для ограничения объема данных, которые клиент TCP может отправить до получения подтверждения отправленных данных.
  • Чтобы остановить сервер, нажмите Ctrl+c в терминале хоста h2.

  • Пользователь также может видеть результаты пропускной способности на стороне сервера.

  • Суммарные данные на сервере аналогичны данным на стороне клиента и должны интерпретироваться таким же образом.

3.3 Запуск клиента и сервера в интерфейсе mininet

  • Тоже самое можно выполнить и интерфейсе mininet
  • Запустите сервер на хосте h2:
    1mininet> h2 iperf3 -s &
    
  • Запустите клиента на хосте h1:
    1mininet> h1 iperf3 -c h2
    
  • Остановите серверный процесс:
    1mininet> h2 killall iperf3
    

3.4 Установка периода времени передачи

  • В терминале h2 запустите сервер:
    1iperf3 -s
    
  • В терминале h1 запустите клиента с параметром -t, за которым следует количество секунд:
    1iperf3 -c 10.0.0.2 -t 5
    
  • Чтобы остановить сервер, нажмите Ctrl+c в терминале хоста h2.

3.5 Установка временного интервала

  • Настроим клиент для выполнения теста пропускной способности с 2-секундным интервалом времени отсчёта как на клиенте, так и на сервере.
  • Опция -i позволяет установить интервал между отсчётами в секундах.
  • В этом случае значение должно быть установлено на 2 секунды как на клиенте, так и на сервере.
  • Параметр -i может быть указан по-разному на клиенте и сервере.
  • В терминале h2 запустите сервер:
    1iperf3 -s -i 2
    
  • В терминале h1 запустите клиента с параметром -i, за которым следует количество секунд:
    1iperf3 -c 10.0.0.2 -i 2
    
  • Чтобы остановить сервер, нажмите Ctrl+c в терминале хоста h2.

3.6 Изменение количества байтов для передачи

  • Зададим на клиенте отправку определённого объёма данных путём установки количества байтов для передачи.

  • По умолчанию iPerf3 выполняет измерение пропускной способности в течение 10 секунд.

  • Однако при задании количества данных клиент будет продолжать отправлять пакеты до тех пор, пока не будут отправлены все байты, указанные пользователем.

  • В терминале h2 запустите сервер:

    1iperf3 -s
    
  • В терминале h1 запустите клиента, задав объём данных:

    1iperf3 -c 10.0.0.2 -n 16G
    
    • Параметр -n указывает объем данных для передачи: 16 Гбайт.
  • Чтобы остановить сервер, нажмите Ctrl+c в терминале хоста h2.

3.7 Определение протокола транспортного уровня

  • По умолчанию измерения пропускной способности проводятся по протоколу TCP, который является протоколом конфигурации по умолчанию.
  • Чтобы изменить протокол на UDP, нужно задать опцию -u на стороне клиента.
  • Для протокола SCTP используется опция --sctp.
  • iPerf3 автоматически определяет протокол транспортного уровня на стороне сервера.
  • В терминале h2 запустите сервер:
    1iperf3 -s
    
  • В терминале h1 запустите клиента, задав протокол UDP:
    1iperf3 -c 10.0.0.2 -u
    
  • Чтобы остановить сервер, нажмите Ctrl+c в терминале хоста h2.
  • После завершения теста он покажет следующие сводные данные:
    • ID, интервал, передача, битрейт: то же, что и у TCP.
    • Джиттер (Jitter): разница в задержке пакетов.
    • Lost/Total: указывает количество потерянных дейтаграмм по сравнению с общим количеством отправленных на сервер (и процентное соотношение).

3.8 Изменение номера порта

  • Если нужно измерить пропускную способность определённого порта, используется параметр -p для настройки клиента и сервера для отправки/получения пакетов или датаграмм через указанный порт.
  • В терминале h2 запустите сервер, используя параметр -p, чтобы указать порт прослушивания:
    1iperf3 -s -p 3250
    
  • В терминале h1 запустите клиента, указав порт:
    1iperf3 -c 10.0.0.2 -p 3250
    
  • Чтобы остановить сервер, нажмите Ctrl+c в терминале хоста h2.

3.9 Работа с одним клиентом

  • По умолчанию сервер iPerf3 продолжает прослушивать входящие соединения.
  • Чтобы сервер мог обрабатывать одного клиента, а затем останавливаться, к серверу добавляется параметр -1.
  • В терминале h2 запустите сервер, используя параметр -1, чтобы принять только одного клиента:
    1iperf3 -s -1
    
  • В терминале h1 запустите клиента, указав порт:
    1iperf3 -c 10.0.0.2
    
  • После завершения этого теста сервер немедленно останавливается.

3.10 Экспорт результатов в файл JSON

  • JSON (JavaScript Object Notation, нотация объектов JavaScript) — это облегченный формат обмена данными.
  • iPerf3 позволяет экспортировать результаты теста в файл JSON, что позволяет другим приложениям легко анализировать файл и интерпретировать результаты.
  • В терминале h2 запустите сервер:
    1iperf3 -s
    
  • В терминале h1 запустите клиента, указав параметр -J для отображения вывода в формате JSON:
    1iperf3 -c 10.0.0.2 -J
    
  • Параметр -J выводит текст JSON на экран через стандартный вывод (stdout) после завершения теста.
  • Чтобы экспортировать вывод в файл нужно перенаправить стандартный вывод в файл:
    1iperf3 -c 10.0.0.2 -J > /home/mininet/work/lab_iperf3/iperf_results.json
    2chown mininet:mininet /home/mininet/work/lab_iperf3/iperf_results.json
    
  • После создания файла JSON команда ls используется для проверки того, что файл создан.
  • Команда cat может использоваться для отображения содержимого файла.
  • Чтобы остановить сервер, нажмите Ctrl+c в терминале хоста h2.

3.11 График результатов iPerf3

  • Визуализируем результаты эксперимента.
  • Скопируйте файл iperf3_results.json с виртуальной машины к себе, в рабочий каталог.
  • Обращайте внимание, чтобы путь к файлу не содержал пробелов.
  • Чтобы сгенерировать выходные данные для файла JSON iPerf3, выполните следующую команду:
    1plot_iperf.sh iperf3_results.json
    
  • Этот сценарий создаёт графики для следующих полей:
    • окно перегрузки (cwnd.pdf),
    • повторная передача (retransmits.pdf),
    • время приема-передачи (RTT.pdf),
    • отклонение времени приема-передачи (RTT_Var.pdf),
    • пропускная способность (throughput.pdf),
    • максимальная единица передачи (MTU.pdf),
    • количество переданных байтов (bytes.pdf).
  • Сценарий построения также создаёт файл CSV (1.dat), который может использоваться другими приложениями.
  • Эти файлы хранятся в каталоге результатов, созданном в том же каталоге, где был выполнен скрипт.

3.12 Видео: Введение в Iperf. Интерактивный эксперимент

4 Воспроизводимый эксперимент

4.1 API Mininet

  • API Mininet построен на трех основных уровнях:
    • Низкоуровневый API. Низкоуровневый API состоит из базовых узлов и классов ссылок (таких как Host, Switch, Link и их подклассы), которые на самом деле могут быть созданы по отдельности и использоваться для создания сети, но это немного громоздко.
    • API среднего уровня. API среднего уровня добавляет объект Mininet, который служит контейнером для узлов и ссылок. Он предоставляет ряд методов (addHost(), addSwitch(), addLink()) для добавления узлов и ссылок в сеть, а также настройки сети, запуска и завершения работы (start(), stop()).
    • Высокоуровневый API. Высокоуровневый API добавляет абстракцию шаблона топологии (класс Topo), который предоставляет возможность создавать повторно используемые параметризованные шаблоны топологии. Эти шаблоны можно передать команде mn (через параметр –custom) и использовать из командной строки.
  • Когда напрямую управляют узлами и коммутаторами, используется низкоуровневый API.
  • Когда запускают или останавливают сеть, используют API среднего уровня (в частности, класс Mininet).
  • Полные сети могут быть созданы с использованием любого из уровней API, но обычно выбирают либо API среднего уровня (например, Mininet.add*()), либо API высокого уровня (Topo. add*()) для создания сетей.

4.2 Примеры создания сетей с использованием уровней API Mininet

  • Низкоуровневый API. Узлы и ссылки:
     1h1 = Host( 'h1' )
     2h2 = Host( 'h2' )
     3s1 = OVSSwitch( 's1', inNamespace=False )
     4c0 = Controller( 'c0', inNamespace=False )
     5Link( h1, s1 )
     6Link( h2, s1 )
     7h1.setIP( '10.1/8' )
     8h2.setIP( '10.2/8' )
     9c0.start()
    10s1.start( [ c0 ] )
    11print( h1.cmd( 'ping -c1', h2.IP() ) )
    12s1.stop()
    13c0.stop()
    
  • API среднего уровня. Сетевой объект:
     1net = Mininet()
     2h1 = net.addHost( 'h1' )
     3h2 = net.addHost( 'h2' )
     4s1 = net.addSwitch( 's1' )
     5c0 = net.addController( 'c0' )
     6net.addLink( h1, s1 )
     7net.addLink( h2, s1 )
     8net.start()
     9print( h1.cmd( 'ping -c1', h2.IP() ) )
    10CLI( net )
    11net.stop()
    
  • API высокого уровня. Шаблоны топологии:
     1class SingleSwitchTopo( Topo ):
     2    "Single Switch Topology"
     3    def build( self, count=1 ):
     4        hosts = [ self.addHost( 'h%d' % i )
     5                  for i in range( 1, count + 1 ) ]
     6        s1 = self.addSwitch( 's1' )
     7        for h in hosts:
     8            self.addLink( h, s1 )
     9
    10net = Mininet( topo=SingleSwitchTopo( 3 ) )
    11net.start()
    12CLI( net )
    13net.stop()
    
  • API среднего уровня на самом деле является самым простым и лаконичным для этого примера, поскольку не требует создания класса топологии.
  • API низкого и среднего уровня являются гибкими и мощными, но могут быть менее удобными для повторного использования по сравнению с высокоуровневым API Topo и шаблонами топологии.

4.3 Простейшая топология

  • На основе скрипта mininet/examples/emptynet.py создадим простейшую топологию lab_iperf3_topo:

     1#!/usr/bin/env python
     2
     3"""
     4Simple topology
     5"""
     6
     7from mininet.net import Mininet
     8from mininet.node import Controller
     9from mininet.cli import CLI
    10from mininet.log import setLogLevel, info
    11
    12def emptyNet():
    13
    14    "Create an empty network and add nodes to it."
    15
    16    net = Mininet( controller=Controller, waitConnected=True )
    17
    18    info( '*** Adding controller\n' )
    19    net.addController( 'c0' )
    20
    21    info( '*** Adding hosts\n' )
    22    h1 = net.addHost( 'h1', ip='10.0.0.1' )
    23    h2 = net.addHost( 'h2', ip='10.0.0.2' )
    24
    25    info( '*** Adding switch\n' )
    26    s1 = net.addSwitch( 's1' )
    27
    28    info( '*** Creating links\n' )
    29    net.addLink( h1, s1 )
    30    net.addLink( h2, s1 )
    31
    32    info( '*** Starting network\n')
    33    net.start()
    34
    35    info( '*** Running CLI\n' )
    36    CLI( net )
    37
    38    info( '*** Stopping network' )
    39    net.stop()
    40
    41
    42if __name__ == '__main__':
    43    setLogLevel( 'info' )
    44    emptyNet()
    
  • Основные элементы:

    • addSwitch(): добавляет коммутатор в топологию и возвращает имя коммутатора;
    • ddHost(): добавляет хост в топологию и возвращает имя хоста;
    • addLink(): добавляет двунаправленную ссылку в топологию (и возвращает ключ ссылки, но это не важно). Ссылки в Mininet являются двунаправленными, если не указано иное.
    • Mininet: основной класс для создания и управления сетью;
    • start(): запускает вашу сеть;
    • pingAll(): проверяет подключение, пытаясь заставить все узлы пинговать друг друга;
    • stop(): останавливает вашу сеть;
    • net.hosts: все хосты в сети;
    • dumpNodeConnections(): сбрасывает подключения к/от набора узлов;
    • setLogLevel( 'info' | 'debug' | 'output' ): установить уровень вывода Mininet по умолчанию; рекомендуется info.
  • Создадим в лабораторной работе подкаталог для данного эксперимента:

    1mkdir -p ~/work/lab_iperf3/iperf3_topo
    
  • Скопируем скрипт на виртуальную машину в каталог лабораторной и запустим:

    1sudo python lab_iperf3_topo.py
    
  • После запуска можно посмотреть элементы топологии:

    1mininet> net
    2mininet> links
    3mininet> dump
    

4.4 Методы настройки хоста

  • Хосты Mininet предоставляют ряд удобных методов настройки сети:
    • IP(): возвращает IP-адрес хоста или определенного интерфейса;
    • MAC(): возвращает MAC-адрес хоста или определенного интерфейса;
    • setARP(): добавить статическую запись ARP в кэш ARP хоста;
    • setIP(): установить IP-адрес для хоста или определенного интерфейса;
    • setMAC(): установить MAC-адрес для хоста или определенного интерфейса.
  • Пример использования в скрипте:
    1print( "Host", h1.name, "has IP address", h1.IP(), "and MAC address", h1.MAC() )
    
  • Задание: Попробуйте изменить приведённый выше код, чтобы он печатал IP-адрес и MAC-адрес каждого хоста.

4.5 Настройка параметров производительности

  • Mininet предоставляет функции ограничения производительности и изоляции с помощью классов CPULimitedHost и TCLink:

    1from mininet.node import CPULimitedHost
    2from mininet.link import TCLink
    3...
    4net = Mininet( controller=Controller, host = CPULimitedHost, link = TCLink )
    
  • Основные функции:

    • self.addHost(name, cpu=f): позволяет указать долю общих ресурсов процессора системы, которая будет выделена виртуальному хосту;
    • self.addLink(node1, node2, bw=10, delay='5ms', max_queue_size=1000, loss=10, use_htb=True): добавляет двунаправленный канал с характеристиками пропускной способности, задержки и потерь:
      • максимальный размер очереди 1000 пакетов;
      • использование ограничителя скорости Hierarchical Token Bucket;
      • эмулятор задержки/потери netem;
      • параметр bw выражается числом в Мбит;
      • задержка выражается в виде строки с заданными единицами измерения (например, 5ms, 100us, 1s);
      • потери выражаются в процентах (от 0 до 100);
      • max_queue_size выражается в пакетах.
  • Задание: Измените приведённый выше код, чтобы каналы были 100 Мбит/с с задержкой 75 мс. Рассчитать производительность связи между h1 и h2.

4.6 Полный эксперимент

  • Сгенерируем трафик и сохраним результат в файл json.
  • Зададим скрипт lab_iperf3.py для полного эксперимента:
     1#!/usr/bin/env python
     2
     3"""
     4Simple experiment.
     5Output: iperf_result.json
     6"""
     7
     8from mininet.net import Mininet
     9from mininet.node import Controller
    10from mininet.cli import CLI
    11from mininet.log import setLogLevel, info
    12from mininet.link import TCLink
    13import time
    14
    15def emptyNet():
    16
    17    "Create an empty network and add nodes to it."
    18
    19    net = Mininet( controller=Controller, waitConnected=True, link = TCLink )
    20
    21    info( '*** Adding controller\n' )
    22    net.addController( 'c0' )
    23
    24    info( '*** Adding hosts\n' )
    25    h1 = net.addHost( 'h1', ip='10.0.0.1' )
    26    h2 = net.addHost( 'h2', ip='10.0.0.2' )
    27
    28    info( '*** Adding switch\n' )
    29    s1 = net.addSwitch( 's1' )
    30
    31    info( '*** Creating links\n' )
    32    net.addLink( h1, s1, cls=TCLink, bw=100, delay='75ms' )
    33    net.addLink( h2, s1, cls=TCLink, bw=100, delay='75ms' )
    34
    35    info( '*** Starting network\n')
    36    net.start()
    37
    38    info( '*** Traffic generation\n')
    39    h2.cmdPrint( 'iperf3 -s -D -1' )
    40    time.sleep(10)  # Wait 10 seconds for servers to start
    41    h1.cmdPrint( 'iperf3 -c', h2.IP(), '-J > iperf_result.json' )
    42
    43    info( '*** Stopping network' )
    44    net.stop()
    45
    46if __name__ == '__main__':
    47    setLogLevel( 'info' )
    48    emptyNet()
    
  • Создадим в лабораторной работе подкаталог для данного эксперимента:
    1mkdir -p ~/work/lab_iperf3/iperf3
    
  • Запустите скрипт на виртуальной машине:
    1sudo python lab_iperf3.py
    
  • Постройм графики из получившегося файла json:
    1plot_iperf.sh iperf_result.json
    
  • Создадим Makefile для проведения всего эксперимента:
     1all: iperf_result.json plot
     2
     3iperf_result.json:
     4        sudo python lab_iperf3.py
     5
     6plot: iperf_result.json
     7        plot_iperf.sh iperf_result.json
     8
     9clean:
    10        -rm -f *.json *.csv
    11        -rm -rf results
    

4.7 Видео: Введение в Iperf. Воспроизводимый эксперимент

Предыдущий
Следующий