И еще немного про tc и честное распределение скорости 21


При использовании очереди sfq в получаем практически честное распределения трафика между пользователям, точнее между сетевыми соединениями пользователей. Получается, что чем больше у пользователя соединений, тем больше скорости он получает, а это значит, что не совсем честные пользователи и p2p получают преимущество. Описанных недостатков лишена очередь esfq, поскольку позволяет разделять трафик на основе адреса источника или назначения. Однако у esfq есть другой недостаток — он не входит в ядро .

О том как как собрать его для вашей версии ядра здесь речи не пойдет. Пользователям достаточно просто установить его из пакета:

[email protected]:~# 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 — скорость подключения к сети интернет (для того чтобы работал, -10% от реальной скорости)
BW — минимальная гарантированная скорость для того или иного класса трафика.

Основные планировщики пакетов и классы для входящего трафика:

# Egress policing
 qdisc del dev $IF_E root 2> /dev/null > /dev/null
 qdisc add dev $IF_E root handle 1: htb default 103
 class add dev $IF_E parent 1: classid 1:1 htb rate $RATE burst 32k
## Prio 1
 class add dev $IF_E parent 1:1 classid 1:101 htb rate $BW \
ceil $RATE burst 2k prio 1
 qdisc add dev $IF_E parent 1:101 handle 101: esfq perturb 2 hash src
 filter add dev $IF_E parent 1:0 prio 1 protocol ip handle 101 fw \
classid 1:101
## Prio 2
 class add dev $IF_E parent 1:1 classid 1:102 htb rate $BW \
ceil $RATE burst 2k prio 2
 qdisc add dev $IF_E parent 1:102 handle 102: esfq perturb 2 hash src
 filter add dev $IF_E parent 1:0 prio 2 protocol ip handle 102 fw \
classid 1:102
## Prio 3
 class add dev $IF_E parent 1:1 classid 1:103 htb rate $BW \
ceil $RATE burst 2k prio 3
 qdisc add dev $IF_E parent 1:103 handle 103: esfq perturb 2 hash src
 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

С помощью раскладываем трафик по классам:

# 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 и честное распределение скорости

  • Rascal От автора

    Возможно. Ограничиваться будет только скорость подключения к интернету.

  • dachn

    Уважаемый 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

    Сохранится ли работоспособность скрипта?

  • Rascal От автора

    В данном случае действительно можно просто проигнорировать. В вашем случае, наверное, будет проще оригинальный скрипт переделать под esfq, который от sfq отличается дополнительными опциями: «hash dst» — для входящего трафика и «hash src» — для исходящего.

  • dachn

    Спасибо за разъяснение, значит эти сообщения в логе можно просто проигнорировать? Это не ошибки, если я правильно понял. У меня роутер TP-Link 842ND и хотелось бы перейти на прошивку Openwrt. Ваш скрипт и описание написаны очень понятно даже для меня, только один еще вопрос, можно ли добавить правила для ограничения скорости Lan-Lan и Lan-Inet из предыдущего скрипта? (http://cdn.rascal.su/uploads/2010/09/qos_tc.sh.gz)

  • dachn

    уважаемый 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

    • Rascal От автора

      Данный блок используется для очистки правил iptables перед навешиванием правил qos. Это нужно для того, чтобы при перезапуске скрипта не создавались дублирующие правила, а так же для того, чтобы при удалении правила из скрипта, не приходилось его удалять из iptables вручную.

  • Dachn

    почему при загрузке выводится данное сообщение?
    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.
    заранее спасибо

    • Rascal От автора

      К сожалению телепаты в отпуске. Вы можете подождать, когда они вернуться. Или можете привести скрипт, который выполняется при загрузке и приводит к появлению этих ошибок.

  • Rascal От автора

    При проверке пакета по правилам цепочки в iptables он проверяется на соответствие всем правилам и проходит по последнему совпадению. Т.е. в вашем варианте LAN-to-LAN будет работать.

  • Rascal От автора

    Ну правильно, я видимо уже сплю. «match ip» в случае когда используется метки через iptables не стоит использовать. Заворачивать пакеты в очередь нужно средствами iptables

    • acaN

      Спасибо за помощь, теперь ограничение работает в обе стороны. http://pastebin.com/D0gTbyk9
      Эффективны ли при таком скрипте правила LAN-to-LAN или

      # Limit for ips iptables -t mangle -A qos_tc -s 192.168.1.200 -j MARK --set-mark 104 iptables -t mangle -A qos_tc -d 192.168.1.200 -j MARK --set-mark 104

      Делают их неэффективными?

  • acaN

    Вроде разобрался с правилами, скрипт больше не сыпет ошибки, работает ограничение входящей скорости, но скорость аплоада не ограничивает. http://pastebin.com/xtpTqs76 Как будто строка

    tc filter add dev $WAN_IFACE parent 1:0 prio 4 protocol ip  u32 \
    match ip src 192.168.1.200/32 flowid 1:104
    

    не имеет эффекта.
    И еще вопрос: не конфликтует ли с таким ограничением по ip классификация «LAN-to-LAN» пакетов?

  • Rascal От автора

    В приведенном примере нет попытки фильтровать по IP. А в целом все довольно просто, фильтр вида:

     tc filter add dev $LAN_IFACE parent 1:0 prio 1 protocol ip handle 101 fw \ classid 1:101 

    Заменяется на

     tc filter add dev $LAN_IFACE parent 1:0 prio 1 protocol ip u32 \ match ip dst 192.168.1.100/32 flowid 1:101 

    При этом трафик попадает в очередь 1:101 не на основании метки 101, как в первом варианте, а на основании соответствия ip-адреса назначения пакета — 192.168.1.100.

  • acaN

    Пользуюсь «скрещённой» версией скрипта http://pastebin.com/f0H9Ujwd
    Как в него добавить ограничение для ip как в комментарии выше? По скудоумию никак не могу вкурить в ман, какие надо выставлять parent для нового класса с сопоставлением ip. Роутер постоянно ругается «RTNETLINK answers: Invalid argument»

  • Rascal От автора

    Например, можно добавить в /etc/rc.local

    IF_E="eth0"
    IF_I="ifb0"
    RATE="100mbit"
    BW_DOWN="5mbit"
    BW_UP="2mbit"
    # 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 101
    tc class add dev $IF_E parent 1: classid 1:1 htb rate $RATE burst 32k
    ## Default
    tc class add dev $IF_E parent 1:1 classid 1:101 htb rate $RATE \
    ceil $RATE burst 2k prio 2
    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 2 protocol ip handle 101 fw \
    classid 1:101
    ## 192.168.1.100
    tc class add dev $IF_E parent 1:1 classid 1:102 htb rate $BW_UP \
    ceil $BW_UP burst 2k prio 2
    tc qdisc add dev $IF_E parent 1:102 handle 102: sfq perturb 2
    tc filter add dev $IF_E parent 1:0  protocol ip prio 2 u32 \
    match ip src 192.168.1.100/32 flowid 1:102
    # 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 101              
    tc class add dev $IF_I parent 1: classid 1:1 htb rate $RATE burst 32k 
    ## Default
    tc class add dev $IF_I parent 1:1 classid 1:101 htb rate $RATE \
    ceil $RATE burst 2k prio 2
    tc qdisc add dev $IF_I parent 1:101 handle 101: sfq perturb 2 
    tc filter add dev $IF_I parent 1:0 prio 1 protocol ip handle 101 fw \
    classid 1:101
    ## 192.168.1.100
    tc class add dev $IF_I parent 1:1 classid 1:102 htb rate $BW_DOWN \
    ceil $BW_DOWN burst 2k prio 2
    tc qdisc add dev $IF_I parent 1:102 handle 102: sfq perturb 2
    tc filter add dev $IF_I parent 1:0  protocol ip prio 2 u32 \
    match ip dst 192.168.1.100/32 flowid 1:102
    
  • Рома

    Добрый день. Имею роутер Wr842nd. На стоковой прошивке греется сильно и регулярно зависает. Решил попробовать openWrt. Вроде все нормально, только мне без управления трафиком-ограничение по определенному айпи никак нельзя. Необходимо ограничить устройству с айпи адресом 192.168.1.100 входящую скорость на уровне 5 Mbit , а исходящую на 2 Mbit. Как это сделать, как должен выглядеть скрипт, куда его положить этот скрипт, чтобы всегда применялись эти правила. Спасибо. Помогите плиз.

  • Rascal От автора

    Здравствуйте. Кроме замены типа очереди с «sfq» на «esfq» нужно будет добавить опции специфичные для «esfq», а именно: «hash src» для исходящего трафика и «hash dst» для входящего.

Комментарии закрыты