При использовании очереди sfq в Linux получаем практически честное распределения трафика между пользователям, точнее между сетевыми соединениями пользователей. Получается, что чем больше у пользователя соединений, тем больше скорости он получает, а это значит, что не совсем честные пользователи и p2p получают преимущество. Описанных недостатков лишена очередь esfq, поскольку позволяет разделять трафик на основе адреса источника или назначения. Однако у esfq есть другой недостаток — он не входит в ядро Linux.
О том как как собрать его для вашей версии ядра здесь речи не пойдет. Пользователям openWRT достаточно просто установить его из пакета:
root@openWRT:~# opkg install kmod-sched-esfq
Далее я привожу адаптированный для esfq вариант скрипта управления трафиком с помощью tc.
Кроме адаптации под esfq изменилось еще кое-что. Вместо двух интерфейсов используется один + устройство ifb, кроме того практика показала что в большинстве случаев 6 классов трафика избыточны и 3-х классов вполне достаточно.
IF_E="eth0"
IF_I="ifb0"
RATE="135mbit"
BW="2mbit"
Переменные:
IF_E — сетевой интерфейс, на котором производится ограничение трафика
IF_I — Intermediate Functional Block, с помощью которого ограничивается входящий трафик
RATE — скорость подключения к сети интернет (для того чтобы QoS работал, -10% от реальной скорости)
BW — минимальная гарантированная скорость для того или иного класса трафика.
Основные планировщики пакетов и классы для входящего трафика:
# Egress policing
tc qdisc del dev $IF_E root 2> /dev/null > /dev/null
tc qdisc add dev $IF_E root handle 1: htb default 103
tc class add dev $IF_E parent 1: classid 1:1 htb rate $RATE burst 32k
## Prio 1
tc class add dev $IF_E parent 1:1 classid 1:101 htb rate $BW \
ceil $RATE burst 2k prio 1
tc qdisc add dev $IF_E parent 1:101 handle 101: esfq perturb 2 hash src
tc filter add dev $IF_E parent 1:0 prio 1 protocol ip handle 101 fw \
classid 1:101
## Prio 2
tc class add dev $IF_E parent 1:1 classid 1:102 htb rate $BW \
ceil $RATE burst 2k prio 2
tc qdisc add dev $IF_E parent 1:102 handle 102: esfq perturb 2 hash src
tc filter add dev $IF_E parent 1:0 prio 2 protocol ip handle 102 fw \
classid 1:102
## Prio 3
tc class add dev $IF_E parent 1:1 classid 1:103 htb rate $BW \
ceil $RATE burst 2k prio 3
tc qdisc add dev $IF_E parent 1:103 handle 103: esfq perturb 2 hash src
tc filter add dev $IF_E parent 1:0 prio 3 protocol ip handle 103 fw \
classid 1:103
Зеркалирование входящего трафика на устройство ifb, а так же планировщики пакетов и классы для исходящего трафика:
# Ingress policing and ifb mirroring
ifconfig $IF_I up
tc qdisc del dev $IF_E ingress 2> /dev/null > /dev/null
tc qdisc add dev $IF_E ingress
tc filter add dev $IF_E parent ffff: protocol ip u32 match u32 0 0 \
action mirred egress redirect dev $IF_I
tc qdisc del dev $IF_I root 2> /dev/null > /dev/null
tc qdisc add dev $IF_I root handle 1: htb default 103
tc class add dev $IF_I parent 1: classid 1:1 htb rate $RATE burst 32k
## Prio 1
tc class add dev $IF_I parent 1:1 classid 1:101 htb rate $BW \
ceil $RATE burst 2k prio 1
tc qdisc add dev $IF_I parent 1:101 handle 101: esfq perturb 2 hash dst
tc filter add dev $IF_I parent 1:0 prio 1 protocol ip handle 101 fw \
classid 1:101
## Prio 2
tc class add dev $IF_I parent 1:1 classid 1:102 htb rate $BW \
ceil $RATE burst 2k prio 2
tc qdisc add dev $IF_I parent 1:102 handle 102: esfq perturb 2 hash dst
tc filter add dev $IF_I parent 1:0 prio 2 protocol ip handle 102 fw \
classid 1:102
## Prio 3
tc class add dev $IF_I parent 1:1 classid 1:103 htb rate $BW \
ceil $RATE burst 2k prio 3
tc qdisc add dev $IF_I parent 1:103 handle 103: esfq perturb 2 hash dst
tc filter add dev $IF_I parent 1:0 prio 3 protocol ip handle 103 fw \
classid 1:103
С помощью iptables раскладываем трафик по классам:
# Delete Chains
iptables -t mangle -D POSTROUTING -o $IF_E -j qos_tc
iptables -t mangle -D PREROUTING -i $IF_E -j qos_tc
iptables -t mangle -F qos_tc
iptables -t mangle -X qos_tc
iptables -t mangle -F
iptables -t mangle -X
# Create Chain
iptables -t mangle -N qos_tc
iptables -t mangle -I POSTROUTING -o $IF_E -j qos_tc
iptables -t mangle -I PREROUTING -i $IF_E -j qos_tc
# ICMP
iptables -t mangle -A qos_tc -p icmp -j MARK \
--set-mark 101
# ACK & Other small packets
iptables -t mangle -A qos_tc -p tcp -m length \
--length :64 -j MARK --set-mark 101
# DNS
iptables -t mangle -A qos_tc -p tcp --dport 53 \
-j MARK --set-mark 101
iptables -t mangle -A qos_tc -p udp --dport 53 \
-j MARK --set-mark 101
iptables -t mangle -A qos_tc -p tcp --sport 53 \
-j MARK --set-mark 101
iptables -t mangle -A qos_tc -p udp --sport 53 \
-j MARK --set-mark 101
# Web-client
iptables -t mangle -A qos_tc -m multiport -p tcp \
--dports 80,443 -j MARK --set-mark 102
iptables -t mangle -A qos_tc -m multiport -p tcp \
--sports 80,443 -j MARK --set-mark 102
# IM-client && SSH-Client
iptables -t mangle -A qos_tc -m multiport -p tcp \
--dports 22,5190,5222,5223 -j MARK --set-mark 102
iptables -t mangle -A qos_tc -m multiport -p tcp \
--sports 22,5190,5222,5223 -j MARK --set-mark 102
Для работоспособности скрипта может потребоваться вручную загрузить соответствующие модули ядра:
insmod ip_queue 2> /dev/null > /dev/null
insmod sch_htb 2> /dev/null > /dev/null
insmod sch_esfq 2> /dev/null > /dev/null
insmod cls_u32 2> /dev/null > /dev/null
insmod sch_ingress 2> /dev/null > /dev/null
insmod cls_fw 2> /dev/null > /dev/null
insmod ipt_TOS 2> /dev/null > /dev/null
insmod sch_prio 2> /dev/null > /dev/null
insmod xt_physdev 2> /dev/null > /dev/null
insmod ifb 2> /dev/null > /dev/null
insmod act_mirred 2> /dev/null > /dev/null
Если используется мост, необходимо включить обработку трафика проходящего через него средствами iptables, чтобы корректно проставлялись метки.
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
Скачать скрипт целиком: qos_tc_new.sh.gz
21 комментарий “И еще немного про tc и честное распределение скорости”
Возможно. Ограничиваться будет только скорость подключения к интернету.
провайдер билайн l2tp
Уважаемый Rascal, появился еще один вопрос. В вашем скрипте http://cdn.rascal.su/uploads/2010/09/qos_tc.sh.gz
есть 2 интерфейса
LAN_IFACE=»eth0″
WAN_IFACE=»eth1″, но в роутере получается LAN_IFACE=»eth0″ это «br-lan», а WAN_IFACE=»eth1″ это «vpn» тунель интернета, который тоже находится в зоне WAN. Интерфейс WAN=»eth1″ соединен с локальной сетью провайдера и в вашем скрипте он получается, что ничем не ограничивается. Возможно ли в связи с этим удалить строки:
LOCAL_NETS=»10.0.0.0/8 172.16.0.0/16″ и
for net in $LOCAL_NETS;
do
iptables -t mangle -A qos_tc -s $net -d $LAN_NET -j MARK —set-mark 2
iptables -t mangle -A qos_tc -d $net -s $LAN_NET -j MARK —set-mark 2
done
Сохранится ли работоспособность скрипта?
В данном случае действительно можно просто проигнорировать. В вашем случае, наверное, будет проще оригинальный скрипт переделать под esfq, который от sfq отличается дополнительными опциями: «hash dst» — для входящего трафика и «hash src» — для исходящего.
Спасибо за разъяснение, значит эти сообщения в логе можно просто проигнорировать? Это не ошибки, если я правильно понял. У меня роутер TP-Link 842ND и хотелось бы перейти на прошивку Openwrt. Ваш скрипт и описание написаны очень понятно даже для меня, только один еще вопрос, можно ли добавить правила для ограничения скорости Lan-Lan и Lan-Inet из предыдущего скрипта? (http://cdn.rascal.su/uploads/2010/09/qos_tc.sh.gz)
уважаемый Rascal, действительно тупанул, но разобрался, что эти 2 строки при загрузке выдают эти строки:
# Delete Chains
iptables -t mangle -D POSTROUTING -o $IF_E -j qos_tc
iptables -t mangle -D PREROUTING -i $IF_E -j qos_tc
iptables -t mangle -F qos_tc
iptables -t mangle -X qos_tc
iptables -t mangle -F
iptables -t mangle -X
как я неправильно понимаю, что удалять нечего, а зачем они нужны?
а скрипт Ваш http://cdn.rascal.su/uploads/2013/03/qos_tc_new.sh_.gz
Данный блок используется для очистки правил iptables перед навешиванием правил qos. Это нужно для того, чтобы при перезапуске скрипта не создавались дублирующие правила, а так же для того, чтобы при удалении правила из скрипта, не приходилось его удалять из iptables вручную.
почему при загрузке выводится данное сообщение?
Sep 4 18:08:39 OpenWrt user.info sysinit: iptables v1.4.10: Couldn’t load target `qos_tc’:File not found
Sep 4 18:08:39 OpenWrt user.info sysinit: Try `iptables -h’ or ‘iptables —help’ for more information.
Sep 4 18:08:39 OpenWrt user.info sysinit: iptables v1.4.10: Couldn’t load target `qos_tc’:File not found
Sep 4 18:08:39 OpenWrt user.info sysinit: Try `iptables -h’ or ‘iptables —help’ for more information.
Sep 4 18:08:39 OpenWrt user.info sysinit: iptables: No chain/target/match by that name.
Sep 4 18:08:39 OpenWrt user.info sysinit: iptables: No chain/target/match by that name.
заранее спасибо
К сожалению телепаты в отпуске. Вы можете подождать, когда они вернуться. Или можете привести скрипт, который выполняется при загрузке и приводит к появлению этих ошибок.
При проверке пакета по правилам цепочки в iptables он проверяется на соответствие всем правилам и проходит по последнему совпадению. Т.е. в вашем варианте LAN-to-LAN будет работать.
Спасибо еще раз.
Ну правильно, я видимо уже сплю. «match ip» в случае когда используется метки через iptables не стоит использовать. Заворачивать пакеты в очередь нужно средствами iptables
Спасибо за помощь, теперь ограничение работает в обе стороны. http://pastebin.com/D0gTbyk9
Эффективны ли при таком скрипте правила LAN-to-LAN или
Делают их неэффективными?
Вроде разобрался с правилами, скрипт больше не сыпет ошибки, работает ограничение входящей скорости, но скорость аплоада не ограничивает. http://pastebin.com/xtpTqs76 Как будто строка
не имеет эффекта.
И еще вопрос: не конфликтует ли с таким ограничением по ip классификация «LAN-to-LAN» пакетов?
В приведенном примере нет попытки фильтровать по IP. А в целом все довольно просто, фильтр вида:
Заменяется на
При этом трафик попадает в очередь 1:101 не на основании метки 101, как в первом варианте, а на основании соответствия ip-адреса назначения пакета — 192.168.1.100.
Пользуюсь «скрещённой» версией скрипта http://pastebin.com/f0H9Ujwd
Как в него добавить ограничение для ip как в комментарии выше? По скудоумию никак не могу вкурить в ман, какие надо выставлять parent для нового класса с сопоставлением ip. Роутер постоянно ругается «RTNETLINK answers: Invalid argument»
Например, можно добавить в /etc/rc.local
Добрый день. Имею роутер Wr842nd. На стоковой прошивке греется сильно и регулярно зависает. Решил попробовать openWrt. Вроде все нормально, только мне без управления трафиком-ограничение по определенному айпи никак нельзя. Необходимо ограничить устройству с айпи адресом 192.168.1.100 входящую скорость на уровне 5 Mbit , а исходящую на 2 Mbit. Как это сделать, как должен выглядеть скрипт, куда его положить этот скрипт, чтобы всегда применялись эти правила. Спасибо. Помогите плиз.
Спасибо.
Здравствуйте. Кроме замены типа очереди с «sfq» на «esfq» нужно будет добавить опции специфичные для «esfq», а именно: «hash src» для исходящего трафика и «hash dst» для входящего.
Здравствуйте. Возник вопрос, в предыдущем скрипте можно «sfq» прямо заменить на «esfq» с получением «плюшек» шейпинга с учетом ip?