8.0 KiB
8.0 KiB
Dummynet — UDP Network Emulator
1. Назначение
Эмулятор сетевых условий: задержка (фиксированная + случайная), сериализация с BWlim и потери пакетов. FULL — UDP-прокси между явно заданными endpoints; INLINE — фильтр потерь в send_hook ETCP_LINK. Задержка и BWlim реализованы в FULL.
2. Как пользоваться
Режим FULL (автономный UDP-прокси)
dummynet_create(ua, bind_ip, listen_port)— создаёт контекст, открывает UDP-сокет наlisten_port.dummynet_set_direction(dn, DUMMYNET_FORWARD, ...)иDUMMYNET_BACKWARD— настраивает параметры для каждого направления.- Источник FORWARD — endpoint, заданный как назначение BACKWARD, и наоборот. Порты независимы;
listen_port=0выбирает ОС.
[dest_backward] → [dummynet: loss/queue limit→delay→serializer] → [dest_forward]
[dest_forward] → [dummynet: loss/queue limit→delay→serializer] → [dest_backward]
Режим INLINE (send_hook в ETCP_LINK)
dummynet_filter_create(ua)— создаёт фильтр (нет своего сокета).dummynet_filter_set_loss(df, permille)— настройка потерь.set_delayпока только сохраняет параметры.dummynet_filter_attach(df, link)— встраивается вlink->send_hook, перехватывая все вызовыsocket_sendto.- Дополнительно:
dummynet_filter_block_addr/unblock_addr— блокировка отправки на конкретные адреса.
Механизмы эмуляции
| Механизм | Реализация |
|---|---|
| Delay (fixed + random) | При приёме пакета создаётся uasync-таймер (dummynet_delay_callback). После срабатывания пакет кладётся в ll_queue направления |
| Bandwidth (serializer) | Срок передачи увеличивается на время сериализации текущего пакета; дробные миллисекунды сохраняются. Один таймер направления выпускает все уже готовые пакеты, без накопления ошибки округления таймера |
| Loss (permille) | При приёме: rand() % 1000 < loss_permille → дроп. В INLINE-режиме — в хуке отправки |
| DROP | dummynet_set_mode(dn, dir, DUMMYNET_DROP) теряет новые пакеты и удаляет уже ожидающие, включая delay |
| HOLD | Останавливает сериализацию, сохраняя ограниченную очередь. RUN начинает сериализацию головы заново; накопленное выпускается с BWlim |
Статистика
recv/sent — число пакетов, recv_bytes/sent_bytes — UDP-байты без IP/UDP заголовков.
dropped — переполнение/ошибка ресурсов или отправки, lost — случайные потери и DROP, blocked — только DROP.
queue_size/queue_max учитывают все ожидающие пакеты, включая delay/HOLD. Сброс статистики сохраняет текущий размер очереди.
Дополнительные отладочные счётчики: delay_timer_set/fire, shaper_timer_set/fire.
Ключевые нюансы
- Оба направления нужно настроить до начала трафика; источник проверяется по IP и порту.
- BWlim задаётся в десятичных кбит/с по UDP-байтам; 0 означает unlimited. RTT без очередей — сумма задержек направлений и сериализации.
- Таймеры uasync имеют миллисекундную точность: несколько готовых пакетов могут выйти вместе; средняя скорость сохраняется.
- При достижении
max_queue_pktsновый пакет отбрасывается. Лимит включает ещё не сработавшие delay-таймеры. - Все операции — в потоке ua. Destroy отменяет также delay-таймеры, освобождает их аргументы и пакеты.
- INLINE-фильтр в режиме блокировки адреса не дропает пакет, а возвращает
len(пакет «успешно отправлен», но фактически никуда не ушёл).
3. API
FULL-режим
| Функция | Назначение |
|---|---|
dummynet_create(ua, bind_ip, listen_port) |
Создать контекст, открыть UDP-сокет, зарегистрировать в uasync |
dummynet_destroy(dn) |
Закрыть сокет, отменить таймеры, очистить очереди, освободить память |
dummynet_set_direction(dn, dir, delay_fixed_ms, delay_random_ms, bw_kbps, max_q, loss_permille, dest_ip, dest_port) |
Настроить параметры направления |
dummynet_set_mode(dn, dir, mode) |
RUN/DROP/HOLD направления, 0 / -1 |
dummynet_get_stats(dn, dir) |
Получить статистику направления |
dummynet_reset_stats(dn, dir) |
Сбросить статистику (-1 = все направления) |
dummynet_get_socket(dn) |
Вернуть fd сокета |
dummynet_get_listen_port(dn) |
Вернуть listen_port |
dummynet_get_uasync(dn) |
Вернуть указатель на UASYNC |
dummynet_get_queue_size(dn, dir) |
Вернуть текущий размер очереди направления |
dummynet_get_debug_counters(dn, dir, ...) |
Вернуть отладочные счётчики таймеров |
INLINE-режим (dummynet_filter)
| Функция | Назначение |
|---|---|
dummynet_filter_create(ua) |
Создать фильтр |
dummynet_filter_set_loss(df, permille) |
Установить вероятность потерь |
dummynet_filter_set_delay(df, delay_ms, jitter_ms) |
Установить задержку (NOTE: в текущей реализации delay не применяется в хуке) |
dummynet_filter_attach(df, link) |
Прикрепить хук к ETCP_LINK |
dummynet_filter_detach(df) |
Открепить хук |
dummynet_filter_destroy(df) |
Уничтожить фильтр |
dummynet_filter_get_stats(df) |
Получить статистику |
dummynet_filter_block_addr(df, ip, port) |
Заблокировать адрес (до 4 адресов) |
dummynet_filter_unblock_addr(df, ip, port) |
Разблокировать адрес |
Структуры
| Структура | Назначение |
|---|---|
dummynet_stats |
Счётчики пакетов/байтов, потерь и размера очереди; точные поля — в dummynet.h |
dummynet_dir |
Внутренняя: параметры направления, очередь, таймеры шейпера, отладочные счётчики |
dummynet |
Контекст FULL-режима: ua, сокет, два dummynet_dir, пул пакетов |
dummynet_filter |
Контекст INLINE-режима: ua, loss_permille, delay, link, статистика, список блокировок |
Зависимости
u_async.h, ll_queue.h, memory_pool.h, socket_compat.h, etcp_connections.h (для ETCP_LINK), platform_compat.h