Введение в 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).
- TCP и SCTP:
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
- Посмотрите топологию:
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
второй интерфейс. - В результате файл примет следующий вид:
- Перезагрузите виртуальную машину.
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
. Для этого перейдём во временную рабочую папку и скачаем репозиторий:Установим
iperf3_plotter
:Скрипты написаны плохо, не работают с путями, имеющими в названии пробелы.
2.3.5 Установка iperf3_plotter
на локальный компьютер
- Установим
iperf3_plotter
(на своём компьютере). Для этого перейдём во временную рабочую папку и скачаем репозиторий:1git clone https://github.com/ekfoury/iperf3_plotter.git
- Заменим жёстко закодированные пути в файлах:
- Скопируем нужные файлы в каталог с локальными исполняемыми файлами:
- Скрипты написаны плохо, не работают с путями, имеющими в названии пробелы.
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
) после завершения теста. - Чтобы экспортировать вывод в файл нужно перенаправить стандартный вывод в файл:
- После создания файла 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 состоит из базовых узлов и классов ссылок (таких как
- Когда напрямую управляют узлами и коммутаторами, используется низкоуровневый API.
- Когда запускают или останавливают сеть, используют API среднего уровня (в частности, класс
Mininet
). - Полные сети могут быть созданы с использованием любого из уровней API, но обычно выбирают либо API среднего уровня (например,
Mininet.add*()
), либо API высокого уровня (Topo. add*()
) для создания сетей.
4.2 Примеры создания сетей с использованием уровней API Mininet
- Низкоуровневый API. Узлы и ссылки:
- API среднего уровня. Сетевой объект:
- 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
После запуска можно посмотреть элементы топологии:
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
:Основные функции:
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
для проведения всего эксперимента: