Skip to main content

QoS, bbr и fq_codel в Openwrt

В ходе работы с сетевыми шлюзами \ роутерами на Linux стандартной задачей является "справедливое распределение канала" между пользователями. На самом деле задачу можно сформулировать просто - если 1 пользователь качает торрент, то пинг в игре у другого пользователя не должен (сильно) падать - это справедливо, это качественно.

По умолчанию в Linux используется qdisk (это часть шейпера, которая занимается сортировкой пакетов перед отправкой) типа pfifo_fast который не различает "пользователей на уровне IP" и чем больше 1 пользователь отправляет пакетов, тем меньше в аппаратной очереди достаётся другому пользователю, который отсылает меньше пакетов.

Более глубоко история и проблематика описана в статье на хабре. Простое решение, не требующее дополнительных пакетов это использовать fq_codel в качестве дефолтного qdisk.

/etc/sysctl.conf:

net.core.default_qdisc = fq_codel

Логика работы данного qdisk в том, чтобы из каждого стрима данных (например TCP) отправлять следующий пакет не позднее чем каждые 5 милисекунд, давая приоритет более мелким пакетам и "началам стримов" (например пинг, DNS, SYN будут иметь приоритет).


Более сложный и требующий пары дополнительных пакетов (tc kmod-ifb), но работающий также для download вариант ниже

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin tc qdisc replace dev br-lan root fq_codel ip link add name ifbwan type ifb tc qdisc del dev $(uci get network.wan.ifname) ingress tc qdisc add dev $(uci get network.wan.ifname) handle ffff: ingress tc qdisc del dev ifbwan root tc qdisc add dev ifbwan root fq_codel ip link set ifbwan up # if you don't bring the device up your connection will lock up on the next step. tc filter add dev $(uci get network.wan.ifname) parent ffff: matchall action mirred egress redirect dev ifbwan

Здесь br-lan это бридж через который данные уходят в интернет, и uci get network.wan.ifname  это интерфейс входящих данных (WAN)

 

Также связанная задача оптимизации, это максимальная эффективность использования физического канала. С красивой анимацией и примерами она описана в статье на хабре и тут. Если коротко - чтобы избежать потери пакетов при заполненном физическом аплинке (или VPN тоннеле, например) нужно использовать пакет kmod-tcp-bbr и 

/etc/sysctl.conf:

net.ipv4.tcp_congestion_control=bbr

 

На момент 2022 года для роутеров с openwrt и сетевых шлюзов на Linux примерно до 1к пользователей это лучший вариант, который я использовал \ тестировал.