B6. Продуктивність і черги
Модуль 2 дає числа для пропускної здатності, затримки й добутку «смуга × затримка», а модуль 12 пояснює, чому TCP сам наповнює будь-яку чергу, яку йому дають. Ця робота показує обидва ефекти на стенді, де все під вашим контролем: канал на 10 Mbit/s, затримка 20 мс в обидва боки, втрати й різна довжина черги.
Після цієї роботи ви зможете:
- побудувати ланцюжок
netem→tbfна вихідному інтерфейсі маршрутизатора й пояснити, що в ньому робить кожна ланка; - виміряти пропускну здатність через
iperf3 -Jі прочитати з його виводу алгоритм перевантаження, пропускну здатність і повторні передачі; - порівняти CUBIC і BBR на чистому шляху й на шляху з втратами та пояснити різницю механізмом, а не словами «BBR швидший»;
- виміряти затримку
pingпід навантаженням і побачити bufferbloat у числах; - замінити довгу FIFO-чергу на
fq_codelі виміряти ефект; - подати результат у вигляді звіту, в якому кожне твердження стоїть на виміряному числі.
Так виглядає розбір скарги «відеодзвінок розвалюється, коли хтось завантажує файл»: швидкість каналу нормальна, а затримка в черзі на вузькому місці під навантаженням виростає на сотні мілісекунд.
Завдання
Section titled “Завдання”Результат роботи: топологія з трьох просторів імен у кінцевому стані
(netem + tbf + fq_codel), каталог results/ із замірами
і report.md. Чекер перевіряє налаштування й наявність замірів, а не те, яку
швидкість чи затримку ви отримали: на різних машинах числа різні.
Топологія. Назви просторів імен і адреси фіксовані, назви інтерфейсів ви обираєте самі.
b6-cli 10.66.1.2 ── 10.66.1.1 b6-rt 10.66.2.1 ── 10.66.2.2 b6-srv| Простір імен | Адреси | Роль |
|---|---|---|
b6-cli |
10.66.1.2/24 |
клієнт iperf3 і ping, маршрут за замовчуванням через 10.66.1.1 |
b6-rt |
10.66.1.1/24, 10.66.2.1/24 |
маршрутизатор із вузьким місцем; ip_forward=1 |
b6-srv |
10.66.2.2/24 |
сервер iperf3, маршрут за замовчуванням через 10.66.2.1 |
Кінцевий стан, який перевіряє чекер.
- На інтерфейсі
b6-rtз адресою10.66.2.1(у бік сервера):netemіз затримкою 20 мс як коренева черга, під неюtbf rate 10mbit, а підtbf(як його дочірня черга)fq_codel. - На інтерфейсі
b6-rtз адресою10.66.1.1(у бік клієнта):netemіз затримкою 20 мс. - У каталозі
results/заміри, названі як у таблиці нижче. - У
report.mdсім розділів, названих як у таблиці.
Файл у results/ |
Що в ньому |
|---|---|
*.json |
виводи iperf3 -J із клієнта b6-cli до 10.66.2.2; потрібен хоча б один із -C cubic і хоча б один із -C bbr |
ping-idle.txt |
ping до 10.66.2.2 без навантаження |
ping-load.txt |
ping до 10.66.2.2 під час iperf3, коли в tbf довга черга |
ping-load-fqcodel.txt |
те саме після заміни черги на fq_codel |
Розділ report.md (заголовок другого рівня) |
Вимога |
|---|---|
## Топологія |
короткий опис, як побудовано |
## Базова лінія |
числа: швидкість без netem, RTT без навантаження |
## Затримка і втрати |
числа: що змінили затримка й втрати |
## CUBIC і BBR |
числа: обидва алгоритми на чистому шляху й під втратами |
## Bufferbloat |
числа: RTT під навантаженням проти RTT без нього |
## fq_codel |
числа: те саме після заміни черги |
## Висновки |
власними словами, що з чого випливає |
У розділах із числами потрібні значення з одиницями (9.4 Mbit/s, 42 ms).
Чого робити не треба. Не підбирайте параметри, щоб «вийшла гарна
картина»: вимірюйте те, що вийшло, і пояснюйте його. Складні
профілі трафіку, tc filter, cake, ECN і tc-police до роботи не входять.
Обмеження. Швидкість каналу 10 Mbit/s і затримка 20 мс в кожен бік фіксовані, щоб числа різних студентів можна було порівнювати. Кожен замір тривалістю не менше 10 секунд.
Готово, коли sudo ./check.sh проходить усі перевірки, а в звіті
кожне з тверджень таблиці «Що треба вміти підтвердити» стоїть на числі.
Перед початком
Section titled “Перед початком”- Прочитайте в модулі 2 розділ про добуток «смуга × затримка»,
а в модулі 12 розділи про чергу на вузькому місці,
керування перевантаженням (CUBIC, BBR) і керування чергою (
fq_codel). - Потрібні права root,
iperf3,iproute2(tc),python3. Їх ставитьsetup/provision.sh; вручну:sudo apt-get install iperf3 iproute2. - BBR має бути серед доступних алгоритмів:
sysctl net.ipv4.tcp_available_congestion_control. Якщо в переліку немаєbbr, виконайтеsudo modprobe tcp_bbr. - Побудуйте топологію так, як у B2: три простори
імен, дві пари
veth, маршрути,ip_forward. - Каталог
results/іreport.mdтримайте там, звідки запускаєтеcheck.sh.
-
Топологія і базова лінія.
Збудуйте топологію з таблиці вище. Кінці пар
vethстворюйте одразу у просторах імен, щоб у просторі господаря не лишалося зайвого.Виміряйте без жодного шейпінгу. Перший
iperf3— сервер уb6-srv, далі клієнт:Terminal window sudo ip netns exec b6-srv iperf3 -ssudo ip netns exec b6-cli iperf3 -c 10.66.2.2 -t 10 -J > results/baseline.jsonsudo ip netns exec b6-cli ping -c 15 -i 0.2 10.66.2.2 > results/ping-idle.txtМіж замірами
iperf3чекайте кілька секунд: сервер обслуговує одного клієнта за раз і після завершення тесту ще кілька секунд не готовий до наступного.Перевірте:
pingповертає відповіді зttl=63(пакет пройшов маршрутизатор), а базова швидкість наvethна порядки вища за ті 10 Mbit/s, що ви обмежите далі. Запишіть обидва числа. -
Вузьке місце: затримка й
tbf.Тепер на інтерфейсі
b6-rtу бік сервера зберіть ланцюжок. Кореневою ставитеnetemіз затримкою, під нею ліміт швидкості:Terminal window sudo ip netns exec b6-rt tc qdisc add dev <до-сервера> root handle 1: netem delay 20mssudo ip netns exec b6-rt tc qdisc add dev <до-сервера> parent 1:1 handle 10: \tbf rate 10mbit burst 32kbit latency 500mssudo ip netns exec b6-rt tc qdisc add dev <до-клієнта> root netem delay 20msnetemсам не має ліміту швидкості, томуtbfстоїть під ним як дочірня черга.latency 500msкажеtbf, скільки найдовше пакет може простояти в черзі: це і є розмір буфера, приблизно 625 кБ при 10 Mbit/s. Навмисно завелика черга потрібна для етапу 4.Перевірте:
tc qdisc show dev <до-сервера>показує обидві ланки,pingтепер дає приблизно 40 мс (два рази по 20 мс), аiperf3із CUBIC упирається трохи нижче 10 Mbit/s. Поясніть, чому не точно 10 (заголовки, стартова фаза TCP) і чомуpingдо сервера показує 40, а не 20. Заміри збережіть:results/cubic.json,results/ping-idle.txt(перезапишіть: тепер це RTT з затримкою, але без навантаження).Перед цим запишіть у звіт добуток «смуга × затримка» для цього шляху: 10 Mbit/s × 40 мс дає 50 кБ у польоті. Порівняйте з буфером на 625 кБ.
-
Втрати.
Додайте до
netemна інтерфейсі в бік сервера випадкові втрати 1 %:Terminal window sudo ip netns exec b6-rt tc qdisc change dev <до-сервера> root handle 1: netem delay 20ms loss 1%Виміряйте
iperf3із-C cubicі-C bbr(по 20 с, між ними пауза), збережіть якresults/cubic-loss.jsonіresults/bbr-loss.json. Прочитайте з JSON швидкість отримувача й кількість повторних передач (sum_sent.retransmits), а алгоритм підтвердіть полемend.sender_tcp_congestion.Порівняйте з чистим шляхом (
cubic.jsonз етапу 2 і такий самийbbr.json). Поясніть різницю, спираючись на модуль 12: що кожен алгоритм вважає сигналом перевантаження.Після заміру поверніть втрати до нуля (
loss 0%абоnetem delay 20msбезloss): інакше наступні етапи змішають два ефекти. -
Bufferbloat.
Запустіть довге навантаження CUBIC (наприклад, 20 с) і під час нього з іншого термінала міряйте
ping:Terminal window sudo ip netns exec b6-cli iperf3 -c 10.66.2.2 -t 20 -C cubic# в іншому терміналі, за кілька секунд після старту:sudo ip netns exec b6-cli ping -c 15 -i 0.3 10.66.2.2 > results/ping-load.txtПорівняйте середню й максимальну затримку з
ping-idle.txt. Канал завантажено повністю, а затримка виросла: CUBIC наповнює чергу, поки не з’являться втрати, а черга на півсекунди дозволяє їй рости довго. Запишіть обидва числа й різницю в рази.Окремо подумайте, що це означає для користувача, чий голосовий дзвінок ділить з цим потоком той самий канал.
-
fq_codel.
Замініть довгу чергу
tbfнаfq_codel, залишивши обмеження швидкості на місці:fq_codelстає дочірньою чергоюtbf(у прикладі з етапу 2 цеparent 10:1):Terminal window sudo ip netns exec b6-rt tc qdisc replace dev <до-сервера> parent 10:1 handle 20: fq_codelПовторіть заміри з етапу 4 і збережіть
results/ping-load-fqcodel.txt. Виміряйте також швидкістьiperf3і порівняйте з етапом 2: якою ціною досягнуто меншу затримку?Поясніть у звіті, що саме робить CoDel: він міряє час, який пакет провів у черзі, і скидає пакети, щоб TCP вчасно зменшив вікно, а
fqдає кожному потоку окрему підчергу, тому потікpingне стоїть позаду потокуiperf3. -
Звіт.
Складіть
report.mdза розділами з таблиці вище. Кожен розділ із числами мусить мати таблицю чи список значень з одиницями, а висновок пояснювати механізм: чому вийшло саме це.
Перевірка
Section titled “Перевірка”З каталогу, де лежать results/ і report.md:
sudo /шлях/до/labs/b6-performance/check.sh# або з явними шляхами:sudo ./check.sh ~/b6/results ~/b6/report.mdЧекер нічого не будує. Він знаходить інтерфейси b6-rt за адресами,
тому назви інтерфейсів не мають значення. Перевіряється:
- Топологія: адреси на місці,
ip_forward=1, клієнт досягає сервера через маршрутизатор (TTL відповіді 63). - Черги: у бік сервера діє
tbfіз швидкістю 10 Mbit/s; на обох інтерфейсахb6-rtєnetemіз затримкою; підtbfстоїтьfq_codel. - Живий тест: чекер сам запускає короткий
iperf3(порт 5299) і переконується, що швидкість не перевищує обмеження з запасом, тобто шейпер стоїть на шляху трафіку. - Заміри: у
results/є JSONiperf3із CUBIC і з BBR (алгоритм читається з поляsender_tcp_congestion, а адреси клієнта й сервера мають збігатися з топологією) і три файлиping. - Звіт: у
report.mdусі сім розділів, розділи із замірами містять числа з одиницями.
Чекер не порівнює швидкості чи затримки з очікуваними: результат
залежить від машини. Якщо ядро не має sch_netem чи sch_fq_codel,
відповідні пункти чекер друкує як пропущені (--) і не рахує
їх ні успіхом, ні помилкою.
Що треба вміти підтвердити
Section titled “Що треба вміти підтвердити”| Твердження | Чим доводиться |
|---|---|
| Шейпер стоїть на шляху даних | iperf3 не перевищує 10 Mbit/s |
Затримка складається з двох netem |
ping ≈ 40 мс без навантаження |
| Черга на вузькому місці визначає затримку | ping під навантаженням у рази вищий, ніж без нього |
| Алгоритм справді той | sender_tcp_congestion у JSON |
| Втрати по-різному б’ють по CUBIC і BBR | cubic-loss.json і bbr-loss.json |
fq_codel зменшує затримку |
ping-load-fqcodel.txt проти ping-load.txt |
| Швидкість при цьому майже та сама | iperf3 до і після |
Часті помилки
Section titled “Часті помилки”tc каже Specified qdisc kind is unknown. Ядро не має потрібного
модуля (sch_netem, sch_fq_codel). Спробуйте sudo modprobe sch_netem,
а якщо модуля немає зовсім (контейнер, мінімальне ядро), цей етап виконати
не вийде: робіть його на віртуальній машині.
Шейпер стоїть не на тому інтерфейсі. Дані iperf3 -c (клієнт → сервер)
йдуть через b6-rt у бік сервера, тож tbf має стояти саме там.
Якщо поставити його в бік клієнта, він обмежуватиме лише квитанції, а
швидкість лишиться гігабітною.
iperf3 із CUBIC і BBR міряли в різних умовах. Якщо між ними ви
змінили чергу чи втрати, порівняння не має сенсу. Міняйте одну річ за раз.
iperf3: error - the server is busy running a test або обрив
з’єднання. Попередній тест ще не завершився на боці сервера. Зачекайте
кілька секунд.
ping під навантаженням запущено до iperf3 або після нього.
Запускайте його через 2–3 секунди після старту тесту й зупиняйте до
його кінця.
У tbf надто малий burst. Якщо burst менший за MTU, пакети не
проходять взагалі; 32kbit (4 кБ) для цієї роботи підходить.
replace замість add для fq_codel. У tbf уже є дочірня черга
(стандартна FIFO), тому її замінюють командою replace.
Порівняння «до і після» без повторів. Один прогін може відрізнятися від наступного на кілька відсотків. Повторіть заміри хоча б тричі й наведіть у звіті розкид.
Далі, якщо цікаво
Section titled “Далі, якщо цікаво”Порівняйте з cake (потрібен sch_cake), який поєднує шейпер і
керування чергою в одній ланці. Додайте ECN (ecn у fq_codel і
sysctl net.ipv4.tcp_ecn=1) і подивіться, чи зменшилася кількість
втрат. Змініть затримку до 100 мс і побачте, як від RTT залежить швидкість
набору вікна у CUBIC і BBR. Побудуйте графік iperf3 -J за секундами
(поле intervals) для кожного алгоритму.