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

При использовании очереди 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 и честное распределение скорости”

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