QoS, bbr и fq_codel в Openwrt
Страница перенесена в Confluence
В ходе работы с сетевыми шлюзами \ роутерами на 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к пользователей это лучший вариант, который я использовал \ тестировал.