LINUX.ORG.RU

История изменений

Исправление Pinkbyte, (текущая версия) :

Тогда почему у меня по дефолту на физических интерфейсах fq_codel, а на бридже — noqueue? Это баг в инитскриптах OpenWRT?

Нет, это фича скриптов openwrt. Как я уже говорил - если не надо шейпить отдельные интерфейсы - лучше делать так. В OpenWRT видать считают что так нужно. Имеют полное право.

но для общего развития — можно на это посмотреть?

Примерно так:

iptables -t mangle -vn -L
Chain PREROUTING (policy ACCEPT 14M packets, 6620M bytes)
 pkts bytes target     prot opt in     out     source               destination         
  12M 6333M FROM_INET  all  --  ppp999 *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT 1389K packets, 1242M bytes)
 pkts bytes target     prot opt in     out     source               destination         
16075  843K TCPMSS     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp flags:0x06/0x02 TCPMSS clamp to PMTU
 881K 1212M FROM_INET  all  --  ppp999 *       0.0.0.0/0            0.0.0.0/0           
 506K   29M TO_INET    all  --  *      ppp999  0.0.0.0/0            0.0.0.0/0           

Chain POSTROUTING (policy ACCEPT 15M packets, 11G bytes)
 pkts bytes target     prot opt in     out     source               destination         
  13M 8056M TO_INET    all  --  *      ppp999  0.0.0.0/0            0.0.0.0/0           

Chain FROM_INET (2 references)
 pkts bytes target     prot opt in     out     source               destination         
20055 2200K MARK       icmp --  *      *       0.0.0.0/0            0.0.0.0/0            MARK set 0xb
 4835  670K MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 MARK set 0xb
    0     0 MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp spt:22 MARK set 0xb

Chain TO_INET (2 references)
 pkts bytes target     prot opt in     out     source               destination         
 8394  918K MARK       icmp --  *      *       0.0.0.0/0            0.0.0.0/0            MARK set 0x15
    0     0 MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 MARK set 0x15
 6420  780K MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp spt:22 MARK set 0x15

Приведены только основные записи, чтобы было примерно понятно о чём речь. Заметь, что маркировка делается дважды.

Идем дальше. В /etc/conf.d/net(гента же) есть следующий кусок:

postup() {
        if [ "${IFACE}" = ppp999 ]; then
                tc qdisc del dev ${IFACE} root &>/dev/null
                tc qdisc add dev ${IFACE} root handle 1: prio
                tc filter add dev ${IFACE} parent 1: prio 10 protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb1

                tc qdisc del dev ${IFACE} ingress &>/dev/null
                tc qdisc add dev ${IFACE} ingress handle ffff:
                tc filter add dev ${IFACE} parent ffff: prio 10 protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0

        fi
        if [ "${IFACE}" = tunv6 ]; then
                tc qdisc del dev ${IFACE} root &>/dev/null
                tc qdisc add dev ${IFACE} root handle 1: prio
                tc filter add dev ${IFACE} parent 1: prio 20 protocol ipv6 u32 match u32 0 0 action mirred egress redirect dev ifb1
                # TODO: ingress qdisc may not work for some reason, remove it if problems occur

                tc qdisc del dev ${IFACE} ingress &>/dev/null
                tc qdisc add dev ${IFACE} ingress handle ffff:
                tc filter add dev ${IFACE} parent ffff: prio 20 protocol ipv6 u32 match u32 0 0 action mirred egress redirect dev ifb0
        fi
        if [ "${IFACE}" = br0 -o "${IFACE}" = vlan2 ]; then
                tc qdisc del dev ${IFACE} root &>/dev/null
                tc qdisc add dev ${IFACE} root handle 1: prio
                tc filter add dev ${IFACE} parent 1:0 prio 10 protocol ip handle 100 fw action mirred egress redirect dev ifb0
                tc filter add dev ${IFACE} parent 1:0 prio 20 protocol ipv6 handle 100 fw action mirred egress redirect dev ifb0
        fi
}

ifb0 отвечает за шейпинг входящего трафика, ifb1 - исходящего. Но так как я уже упомянул, что шейпить надо в том числе трафик, входящий на сам роутер, а от IMQ пришлось отказаться - имеем вот такой вот геморрой.

Дальше - веселее :-). Сам шейпер:

# Variables that control script parameters
MAIN_IFACE="ifb0"
OUT_IFACE="ifb1"

BAND="7Mbit"
HIGH_LIMIT="6Mbit"

# Simple shaper for outgoing traffic (device ${OUT_IFACE})
tc qdisc del dev ${OUT_IFACE} root &>/dev/null
tc qdisc add dev ${OUT_IFACE} root handle 1: prio

# add some qdisc to high priority traffic
tc qdisc add dev ${OUT_IFACE} parent 1:1 handle 10: sfq

# Properly marked traffic is high-priority
tc filter add dev ${OUT_IFACE} parent 1:0 prio 1 protocol ip \
handle 21 fw \
flowid 1:1

# Properly marked IPv6 traffic is high-priority
tc filter add dev ${OUT_IFACE} parent 1:0 prio 2 protocol ipv6 \
handle 21 fw \
flowid 1:1

# Other traffic is lowest-priority
tc filter add dev ${OUT_IFACE} parent 1:0 prio 100 protocol ip u32 match u32 0 0 flowid 1:3

# Other traffic(IPv6) is lowest-priority
tc filter add dev ${OUT_IFACE} parent 1:0 prio 200 protocol ipv6 u32 match u32 0 0 flowid 1:3

# Shaper for incoming traffic
tc qdisc del dev ${MAIN_IFACE} root handle 1: hfsc &>/dev/null
tc qdisc add dev ${MAIN_IFACE} root handle 1: hfsc

# Internet traffic (full MAXIMUM speed)
tc class add dev ${MAIN_IFACE} parent 1:0 classid 1:1 hfsc sc rate ${BAND} ul rate ${BAND}
# Dummy subclass for delayed shaping
tc class add dev ${MAIN_IFACE} parent 1:0 classid 1:100 hfsc sc rate 1Gbit ul rate 1Gbit
# Subclasses of Internet traffic
tc class add dev ${MAIN_IFACE} parent 1:1 classid 1:10 hfsc rt umax 1500 dmax 2ms rate 1Mbit ls rate ${HIGH_LIMIT}
tc class add dev ${MAIN_IFACE} parent 1:1 classid 1:11 hfsc ls rate 1Mbit

# SFQ Disciplines traffic with filter based on destination IP (fair use)
# for high-priority traffic
tc qdisc add dev ${MAIN_IFACE} parent 1:10 handle 10: sfq
tc filter add dev ${MAIN_IFACE} parent 10: protocol ip handle 1 flow hash keys nfct-dst divisor 256 baseclass 1:10
# for low-priority traffic
tc qdisc add dev ${MAIN_IFACE} parent 1:11 handle 11: sfq
tc filter add dev ${MAIN_IFACE} parent 11: protocol ip handle 1 flow hash keys nfct-dst divisor 256 baseclass 1:11
# end of SFQ Disciplines

# qdisc for dummy subclass
tc qdisc add dev ${MAIN_IFACE} parent 1:100 handle 100: pfifo limit 1000

# Properly marked traffic is high-priority
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 2 protocol ip \
handle 11 fw \
flowid 1:10

# Properly marked IPv6 traffic is high-priority
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 3 protocol ipv6 \
handle 11 fw \
flowid 1:10

# Not input traffic and not classified valid as FORWARD traffic - it should be low priority
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 90 protocol ip \
handle 100 fw \
flowid 1:11

# Not input IPv6 traffic and not classified valid as FORWARD traffic - it should be low priority
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 100 protocol ipv6 \
handle 200 fw \
flowid 1:11

# Not input traffic, shape it AGAIN later
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 2000 protocol ip u32 \
match u32 0 0 \
flowid 1:100 \
action xt -j MARK --set-mark 100 &>/dev/null

# Not input IPv6 traffic, shape it AGAIN later
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 1000 protocol ipv6 u32 \
match u32 0 0 \
flowid 1:100 \
action xt -j MARK --set-mark 200 &>/dev/null

Когда я это дописывал, я уже сам не верил, что эта сотона заработает

Кусок из ip6tables не привожу - там всё примерно аналогично.

Схема сети следующая:

2 VLAN-а(для проводной сети и wi-fi). vlan1(проводной) включен в мост(br0) - для виртуальных машин и контейнеров. Интернет поступает посредством PPPoE-соединения - ppp999. Поверх него - IPv6-туннель до Hurricane Electric. IPv6 в локалке поднят как на проводном VLAN-е, так и на беспроводном. Шейпить надо, как понимаешь и IPv4 и IPv6.

Исходная версия Pinkbyte, :

Тогда почему у меня по дефолту на физических интерфейсах fq_codel, а на бридже — noqueue? Это баг в инитскриптах OpenWRT?

Нет, это фича скриптов openwrt. Как я уже говорил - если не надо шейпить отдельные интерфейсы - лучше делать так. В OpenWRT видать считают что так нужно. Имеют полное право.

но для общего развития — можно на это посмотреть?

Примерно так:

iptables -t mangle -vn -L
Chain PREROUTING (policy ACCEPT 14M packets, 6620M bytes)
 pkts bytes target     prot opt in     out     source               destination         
  12M 6333M FROM_INET  all  --  ppp999 *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT 1389K packets, 1242M bytes)
 pkts bytes target     prot opt in     out     source               destination         
16075  843K TCPMSS     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp flags:0x06/0x02 TCPMSS clamp to PMTU
 881K 1212M FROM_INET  all  --  ppp999 *       0.0.0.0/0            0.0.0.0/0           
 506K   29M TO_INET    all  --  *      ppp999  0.0.0.0/0            0.0.0.0/0           

Chain POSTROUTING (policy ACCEPT 15M packets, 11G bytes)
 pkts bytes target     prot opt in     out     source               destination         
  13M 8056M TO_INET    all  --  *      ppp999  0.0.0.0/0            0.0.0.0/0           

Chain FROM_INET (2 references)
 pkts bytes target     prot opt in     out     source               destination         
20055 2200K MARK       icmp --  *      *       0.0.0.0/0            0.0.0.0/0            MARK set 0xb
 4835  670K MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 MARK set 0xb
    0     0 MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp spt:22 MARK set 0xb

Chain TO_INET (2 references)
 pkts bytes target     prot opt in     out     source               destination         
 8394  918K MARK       icmp --  *      *       0.0.0.0/0            0.0.0.0/0            MARK set 0x15
    0     0 MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 MARK set 0x15
 6420  780K MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp spt:22 MARK set 0x15

Приведены только основные записи, чтобы было примерно понятно о чём речь. Заметь, что маркировка делается дважды.

Идем дальше. В /etc/conf.d/net(гента же) есть следующий кусок:

postup() {
        if [ "${IFACE}" = ppp999 ]; then
                tc qdisc del dev ${IFACE} root &>/dev/null
                tc qdisc add dev ${IFACE} root handle 1: prio
                tc filter add dev ${IFACE} parent 1: prio 10 protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb1

                tc qdisc del dev ${IFACE} ingress &>/dev/null
                tc qdisc add dev ${IFACE} ingress handle ffff:
                tc filter add dev ${IFACE} parent ffff: prio 10 protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0

        fi
        if [ "${IFACE}" = tunv6 ]; then
                tc qdisc del dev ${IFACE} root &>/dev/null
                tc qdisc add dev ${IFACE} root handle 1: prio
                tc filter add dev ${IFACE} parent 1: prio 20 protocol ipv6 u32 match u32 0 0 action mirred egress redirect dev ifb1
                # TODO: ingress qdisc may not work for some reason, remove it if problems occur

                tc qdisc del dev ${IFACE} ingress &>/dev/null
                tc qdisc add dev ${IFACE} ingress handle ffff:
                tc filter add dev ${IFACE} parent ffff: prio 20 protocol ipv6 u32 match u32 0 0 action mirred egress redirect dev ifb0
        fi
        if [ "${IFACE}" = br0 -o "${IFACE}" = vlan2 ]; then
                tc qdisc del dev ${IFACE} root &>/dev/null
                tc qdisc add dev ${IFACE} root handle 1: prio
                tc filter add dev ${IFACE} parent 1:0 prio 10 protocol ip handle 100 fw action mirred egress redirect dev ifb0
                tc filter add dev ${IFACE} parent 1:0 prio 20 protocol ipv6 handle 100 fw action mirred egress redirect dev ifb0
        fi
}

ifb0 отвечает за шейпинг входящего трафика, ifb1 - исходящего. Но так как я уже упомянул, что шейпить надо в том числе трафик, входящий на сам роутер, а от IMQ пришлось отказаться - имеем вот такой вот геморрой.

Дальше - веселее :-). Сам шейпер:

# Variables that control script parameters
MAIN_IFACE="ifb0"
OUT_IFACE="ifb1"

BAND="7Mbit"
HIGH_LIMIT="6Mbit"

# Simple shaper for outgoing traffic (device ${OUT_IFACE})
tc qdisc del dev ${OUT_IFACE} root &>/dev/null
tc qdisc add dev ${OUT_IFACE} root handle 1: prio

# add some qdisc to high priority traffic
tc qdisc add dev ${OUT_IFACE} parent 1:1 handle 10: sfq

# Properly marked traffic is high-priority
tc filter add dev ${OUT_IFACE} parent 1:0 prio 1 protocol ip \
handle 21 fw \
flowid 1:1

# Properly marked IPv6 traffic is high-priority
tc filter add dev ${OUT_IFACE} parent 1:0 prio 2 protocol ipv6 \
handle 21 fw \
flowid 1:1

# Other traffic is lowest-priority
tc filter add dev ${OUT_IFACE} parent 1:0 prio 100 protocol ip u32 match u32 0 0 flowid 1:3

# Other traffic(IPv6) is lowest-priority
tc filter add dev ${OUT_IFACE} parent 1:0 prio 200 protocol ipv6 u32 match u32 0 0 flowid 1:3

# Shaper for incoming traffic
tc qdisc del dev ${MAIN_IFACE} root handle 1: hfsc &>/dev/null
tc qdisc add dev ${MAIN_IFACE} root handle 1: hfsc

# Internet traffic (full MAXIMUM speed)
tc class add dev ${MAIN_IFACE} parent 1:0 classid 1:1 hfsc sc rate ${BAND} ul rate ${BAND}
# Dummy subclass for delayed shaping
tc class add dev ${MAIN_IFACE} parent 1:0 classid 1:100 hfsc sc rate 1Gbit ul rate 1Gbit
# Subclasses of Internet traffic
tc class add dev ${MAIN_IFACE} parent 1:1 classid 1:10 hfsc rt umax 1500 dmax 2ms rate 1Mbit ls rate ${HIGH_LIMIT}
tc class add dev ${MAIN_IFACE} parent 1:1 classid 1:11 hfsc ls rate 1Mbit

# SFQ Disciplines traffic with filter based on destination IP (fair use)
# for high-priority traffic
tc qdisc add dev ${MAIN_IFACE} parent 1:10 handle 10: sfq
tc filter add dev ${MAIN_IFACE} parent 10: protocol ip handle 1 flow hash keys nfct-dst divisor 256 baseclass 1:10
# for low-priority traffic
tc qdisc add dev ${MAIN_IFACE} parent 1:11 handle 11: sfq
tc filter add dev ${MAIN_IFACE} parent 11: protocol ip handle 1 flow hash keys nfct-dst divisor 256 baseclass 1:11
# end of SFQ Disciplines

# qdisc for dummy subclass
tc qdisc add dev ${MAIN_IFACE} parent 1:100 handle 100: pfifo limit 1000

# Properly marked traffic is high-priority
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 2 protocol ip \
handle 11 fw \
flowid 1:10

# Properly marked IPv6 traffic is high-priority
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 3 protocol ipv6 \
handle 11 fw \
flowid 1:10

# Not input traffic and not classified valid as FORWARD traffic - it should be low priority
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 90 protocol ip \
handle 100 fw \
flowid 1:11

# Not input IPv6 traffic and not classified valid as FORWARD traffic - it should be low priority
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 100 protocol ipv6 \
handle 200 fw \
flowid 1:11

# Not input traffic, shape it AGAIN later
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 2000 protocol ip u32 \
match u32 0 0 \
flowid 1:100 \
action xt -j MARK --set-mark 100 &>/dev/null

# Not input IPv6 traffic, shape it AGAIN later
tc filter add dev ${MAIN_IFACE} parent 1:0 prio 1000 protocol ipv6 u32 \
match u32 0 0 \
flowid 1:100 \
action xt -j MARK --set-mark 200 &>/dev/null

Когда я это дописывал, я уже сам не верил, что эта сотона заработает