Я создаю встроенное Linux-приложение в реальном времени, которое имеет различный сетевой трафик. Из множества трафика два соединения являются критичными по времени. Один из них является входными данными, а другой - для выходных данных. Моему приложению нужен этот трафик, чтобы иметь приоритет над другим, не критичным ко времени трафиком.
Я забочусь о двух вещах:
- Минимизируйте количество отброшенных пакетов из-за перегрузки на этих двух соединениях.
- Минимизируйте задержку через устройство (вход-выход) в этих двух соединениях.
Я (немного!) Разбираюсь в управлении трафиком Linux и понимаю, что это в первую очередь относится к исходящему трафику, поскольку удаленное устройство отвечает за приоритет данных, которые оно отправляет мне. Я настроил свое приложение как процесс в режиме реального времени и решил все вопросы, связанные с приоритетом его запуска.
Теперь я приступаю к настройке tc. Для моего тестового примера вот что я использую:
tc qdisc add dev eth0 root handle 1: prio bands 3 priomap 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2
tc qdisc add dev eth0 parent 1:1 handle 10: pfifo
tc qdisc add dev eth0 parent 1:2 handle 20: pfifo
tc qdisc add dev eth0 parent 1:3 handle 30: pfifo
По сути, я говорю: отправьте весь трафик с приоритетом 7 в полосе 0, а весь другой трафик в полосе 2. Как только у меня будет работать этот простой тест, я лучше справлюсь с другим трафиком.
Сначала давайте проверим мои ожидания:
Я ожидаю, что любой трафик с приоритетом 7 всегда должен выходить перед трафиком с любым другим приоритетом. Это должно сделать задержку на таком трафике относительно незатронутой другим трафиком на коробке, нет? Мой MTU установлен на 1500, и я получаю около 10 МБ / с через интерфейс. Максимальная дополнительная задержка в полосе 0, вызванная трафиком в полосе 2, составляет один пакет (<= 1500 байт) или 150 мкс (1500 байт / 10 МБайт / с = 150 мкс). </p>
Вот моя тестовая установка:
Два Linux Boxes. На Box 1 работает TCP-сервер, который отображает входные данные. Блок 2 подключается к блоку 1, отправляет пакеты по TCP и измеряет задержку (время, отправленное на полученное время).
Я использую ту же настройку tc для коробочных коробок Linux.
В приложениях (как серверных, так и клиентских) я установил SO_PRIORITY для сокета следующим образом:
int so_priority = 7;
setsockopt(m_socket.native(), SOL_SOCKET, SO_PRIORITY, &so_priority, sizeof(so_priority));
Я использую tc, чтобы убедиться, что мой трафик переходит в полосу 0, а весь остальной трафик - в полосу 2:
tc -s qdisc ls dev eth0
Вот в чем проблема: когда нет другого трафика, я вижу задержки в диапазоне 500 мс. Когда у меня есть другой трафик (например, задание scp, копирующее файл размером 100 МБ), задержки увеличиваются до 10+ мс. Что действительно странно, так это то, что ни одна из работ, которые я делал, не имела никакого влияния. На самом деле, если я поменяю местами (поэтому весь мой трафик идет по полосе 2 с более низким приоритетом, а другой трафик по полосе 1), я не вижу никакой разницы в задержке.
Чего я ожидал, так это того, что при наличии другого трафика в сети увеличилось время ожидания примерно на 150 мкс, а не на 10 мс! Кстати, я проверил, что загрузка блока другими процессами (с приоритетом не в реальном времени) не влияет ни на задержку, ни на трафик на других интерфейсах.
Еще одно замечание: если я уроню mtu до 500 байт, задержка уменьшится примерно до 5 мс. Тем не менее, это на порядок хуже, чем в незагруженном корпусе. Кроме того - почему изменение mtu так сильно на него влияет, но использование tc для настройки очередей с приоритетом не имеет значения ???
Почему тк не помогает мне? Что мне не хватает?
Спасибо!
Eric