"Правильный" шейпер для исходящего траффика

Установка, настройка, поддержка
NiTr0
Сообщения: 767
Зарегистрирован: Пт фев 08, 2008 4:46 pm

"Правильный" шейпер для исходящего траффика

Сообщение NiTr0 » Вт июн 09, 2009 11:45 am

После некоторого надругательства над шейперами в конце концов реализовал себе шейпер, который нормально ограничивает исходящий траффик, с приоретизацией траффика (для удобства пользователей) и поддержкой QoS (собссно - приоритет дается только пакетам с TOS=Minimize-Delay, но кому нужно будет еще что-то - допилить проблемы не составит). Для удобства пользовал IMQ (т.к. в теории возможно, что шейпер будет работать на насе с несколькими магистральными интерфейсами) - что впрочем не критично, IMQ интерфейс можно заменить на локальный, с минимальной правкой скриптов.

В качестве NAS пользовал LEAF, куда собссно из-за этого и пришлось прикрутить и IMQ, и gigawords патч на пппд, + кучу всякого нужного...
Вот собссно скрипты:

if-up:

Код: Выделить всё

#!/bin/sh
#ABillS %DATE% %TIME%
#
# When the ppp link comes up, this script is called with the following
# parameters
#       $1      the interface name used by pppd (e.g. ppp3)
#       $2      the tty device name
#       $3      the tty device speed
#       $4      the local IP address for the interface
#       $5      the remote IP address
#       $6      the parameter specified by the 'ipparam' option to pppd
#


debug=0;
INPUT=imq0;
UBURST="burst 512k"
DBURST="burst 64k"
AWK="/usr/bin/awk"
SED="/bin/sed"
TC="/sbin/tc"
TCQA="/sbin/tc qdisc add"
TCCA="/sbin/tc class add"
TCFA="/sbin/tc filter add"
TCCR="/sbin/tc class replace"
TCFR="/sbin/tc filter replace"
IPTM="/sbin/iptables -t mangle"
GREP="/bin/grep"
IPLS="/sbin/ip l s"
OUTPUT=$1
if [ "$OUTPUT" = "" ];
then
  OUTPUT="$PPP_IFACE"
fi

if [ -f /var/run/radattr.$OUTPUT ]
then
   PPPNUM=`echo $OUTPUT|$SED 's/ppp//'|$AWK '{printf "%03d",$1}'`
   HEXPPP=`echo $(($PPPNUM+2048))|awk '{printf("%0x\n", $1)}'`
   IP=$5
   if [ "$IP" = "" ];
   then
     IP="$PPP_REMOTE"
   fi

   QDISC_OUT=`$TC qdisc show dev $INPUT|$GREP -v sfq|$AWK '{print $2}'`
   DOWNSPEED=`$AWK  '/PPPD-Downstream-Speed-Limit/ {print $2}'  /var/run/radattr.$OUTPUT`
   UPSPEED=`$AWK  '/PPPD-Upstream-Speed-Limit/ {print $2}'  /var/run/radattr.$OUTPUT`
   FILTERS=`$AWK  '/Filter-Id/ {print $2}'  /var/run/radattr.$OUTPUT`

   if [ "$QDISC_OUT" != "htb" ];
   then
     $IPLS $INPUT up
     $TC qdisc del dev $INPUT root >/dev/null
     $TCQA dev $INPUT root handle 1: htb default 2
     $TCCR dev $INPUT parent 1: classid 1:1 htb rate 100mbit ceil 1000mbit burst 1024k cburst 64k prio 2 quantum 1514
     $TCCR dev $INPUT parent 1: classid 1:2 htb rate 100mbit ceil 1000mbit burst 1024k cburst 64k prio 1 quantum 1514
     $IPTM -N PPP || $IPTM -F PPP
     $IPTM -A PREROUTING -i ppp+ -d ! 172.31.255.0/24 -j PPP
     $IPTM -A PPP -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j TOS --set-tos Minimize-Delay
     $IPTM -A PPP -p icmp -j TOS --set-tos Minimize-Delay
     $IPTM -A PPP -j IMQ --todev 0
  fi


   if [ w${debug} = w1 ] ; then
     echo "Debug mode" >>/tmp/pptpd
     echo $DOWNSPEED >>/tmp/pptpd
     echo $UPSPEED >>/tmp/pptpd
     echo $FILTERS >>/tmp/pptpd
   fi;

    /sbin/tc qdisc del dev $OUTPUT root    > /dev/null

##### speed server->client
   if [ "$UPSPEED" != "0" ] ;
   then
     URATE=$(($UPSPEED/2))
     $TCQA dev $OUTPUT root handle 1: htb default 20
     $TCCR dev $OUTPUT parent 1: classid 1:1 htb rate ${UPSPEED}kbit $UBURST quantum 1514
     $TCCR dev $OUTPUT parent 1:1 classid 1:10 htb rate ${URATE}kbit ceil ${UPSPEED}kbit $UBURST prio 1 quantum 1514
     $TCCR dev $OUTPUT parent 1:1 classid 1:20 htb rate ${URATE}kbit ceil ${UPSPEED}kbit $UBURST prio 2 quantum 1514
     $TCQA dev $OUTPUT parent 1:10 handle 10: sfq perturb 10 quantum 1514
     $TCQA dev $OUTPUT parent 1:20 handle 20: sfq perturb 10 quantum 1514
     $TCFR dev $OUTPUT parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff flowid 1:10
     $TCFR dev $OUTPUT parent 1:0 protocol ip prio 10 u32 match ip protocol 1 0xff flowid 1:10

   fi

##### speed client->server
   if [ "$DOWNSPEED" != "0" ] ;
   then
     DRATE=$(($DOWNSPEED/2))
     $TCCR dev $INPUT parent 1:1 classid 1:1$PPPNUM htb rate ${DOWNSPEED}kbit $DBURST quantum 1514
     $TCCR dev $INPUT parent 1:1$PPPNUM classid 1:2$PPPNUM htb rate ${DRATE}kbit ceil ${DOWNSPEED}kbit $DBURST prio 4 quantum 1514
     $TCCR dev $INPUT parent 1:1$PPPNUM classid 1:3$PPPNUM htb rate ${DRATE}kbit ceil ${DOWNSPEED}kbit $DBURST prio 3 quantum 1514
     $TCQA dev $INPUT parent 1:2$PPPNUM handle 2$PPPNUM: sfq perturb 10 quantum 1514
     $TCQA dev $INPUT parent 1:3$PPPNUM handle 3$PPPNUM: sfq perturb 10 quantum 1514

     $TCFR dev $INPUT parent 1:0 handle 800::$HEXPPP protocol ip prio 1 u32 match ip src $IP/32 match ip tos 0x10 0xff flowid 1:3$PPPNUM
     $TCFR dev $INPUT parent 1:0 handle 801::$HEXPPP protocol ip prio 2 u32 match ip src $IP/32 flowid 1:2$PPPNUM
   fi

#### Filters
  if [ w$FILTERS != w ] ;
  then
    echo "filters not supported"
  fi
fi
if-down:

Код: Выделить всё

#!/bin/sh
#ABillS %DATE% %TIME%
#
# When the ppp link comes up, this script is called with the following
# parameters
#       $1      the interface name used by pppd (e.g. ppp3)
#       $2      the tty device name
#       $3      the tty device speed
#       $4      the local IP address for the interface
#       $5      the remote IP address
#       $6      the parameter specified by the 'ipparam' option to pppd
#


debug=0;
INPUT=imq0;
AWK="/usr/bin/awk"
SED="/bin/sed"
TC="/sbin/tc"
IPTM="/sbin/iptables -t mangle"
GREP="/bin/grep"
OUTPUT=$1
if [ "$OUTPUT" = "" ];
then
  OUTPUT="$PPP_IFACE"
fi


if [ -f /var/run/radattr.$OUTPUT ]
then
   PPPNUM=`echo $OUTPUT|$SED 's/ppp//'|$AWK '{printf "%03d",$1}'`
   HEXPPP=`echo $(($PPPNUM+2048))|awk '{printf("%0x\n", $1)}'`
   IP=$5
   QDISC_ETH=`$TC qdisc show dev $INPUT|$GREP root|$AWK '{print $2}'`
   DOWNSPEED=`$AWK  '/PPPD-Downstream-Speed-Limit/ {print $2}'  /var/run/radattr.$OUTPUT`
   UPSPEED=`$AWK  '/PPPD-Upstream-Speed-Limit/ {print $2}'  /var/run/radattr.$OUTPUT`
   FILTERS=`$AWK  '/Filter-Id/ {print $2}'  /var/run/radattr.$OUTPUT`
   if [ "$IP" = "" ];
      then
      IP="$PPP_REMOTE"
   fi

   if [ w${debug} = w1 ] ; then
     echo "Debug mode" >>/tmp/pptpd
     echo $DOWNSPEED >>/tmp/pptpd
     echo $UPSPEED >>/tmp/pptpd
     echo $FILTERS >>/tmp/pptpd
   fi;


##### speed server->client
   if [ "$UPSPEED" != "0" ] ;
   then
     $TC qdisc del dev $OUTPUT root    > /dev/null
   fi

##### speed client->server
   if [ "$DOWNSPEED" != "0" ] ;
   then
     $TC filter del dev $INPUT parent 1:0 handle 800::$HEXPPP protocol ip prio 1 u32 match ip src $IP/32 match ip tos 0x10 0xff flowid 1:3$PPPNUM
     $TC filter del dev $INPUT parent 1:0 handle 801::$HEXPPP protocol ip prio 2 u32 match ip src $IP/32 flowid 1:2$PPPNUM
     $TC class del dev $INPUT classid 1:3$PPPNUM
     $TC class del dev $INPUT classid 1:2$PPPNUM
     $TC class del dev $INPUT classid 1:1$PPPNUM

   fi

#### Filters
  if [ w$FILTERS != w ] ;
  then
    echo "filters not supported"
  fi

 fi
P.S. если кому нужно, могу как-то и собссно готовый образ для PPPoE наса выложить... PPTP не пользовал на нем, но думаю проблемы отконфигурить для желающих не составит.
Последний раз редактировалось NiTr0 Чт июн 11, 2009 5:48 pm, всего редактировалось 1 раз.

ran
Сообщения: 2298
Зарегистрирован: Вс окт 21, 2007 2:29 pm

Re: "Правильный" шейпер для исходящего траффика

Сообщение ran » Вт июн 09, 2009 3:48 pm

фигня это всё... практика показывает, что какая-либо приоритезация/переупорядочивание очередей на уровне отдельно взятого усера - дело неблагодарное... одному нада так, другому эдак... пусть сами себя шейпят если надобно так как им хочется ;)... к тому же ИМХО юзать IMQ не поддерживаемое официальным кернелом... уж лучше IFB... да канешна заворачивать и классифицировать придётся фильтрами а не иптеблс но там возможностей вполне лостаточно

а вот глобальный шейпер с приоритезацией/переупорядочиванием - другое дело... лично у меня шейпер состоит из 2-х частей:

1. просто ограничитель скорости согласно классам трафика в интервалах. Тупой ограничитель с аграфигенной очередью через IFB (повторюсь - кому нада нехай шейпят/приоритизируют сами, не провайдерское это дело ;) )

2. глобальный шейпер на каждом внешнем канале - вот здесь и приоритезация и классификация (глобальная, зависящая от данного конкретного внешнего канала). Цель - наиболее рациональное использование канала (в общем), недопущение монополизации, отлов пирингов и тому подобных как, etc
Любой тупик - это тщательно замаскированный выход.

dnk2009
Сообщения: 121
Зарегистрирован: Сб окт 04, 2008 6:10 pm
Контактная информация:

Re: "Правильный" шейпер для исходящего траффика

Сообщение dnk2009 » Вт июн 09, 2009 5:28 pm

ran поделись своим глобальным шейпером :wink:

ran
Сообщения: 2298
Зарегистрирован: Вс окт 21, 2007 2:29 pm

Re: "Правильный" шейпер для исходящего траффика

Сообщение ran » Ср июн 10, 2009 7:43 am

dnk2009 писал(а):ran поделись своим глобальным шейпером :wink:
та мне-то не жалко - смысла нет... потому как это дело сугубо индивидуальное (интимное так сказать) ;) сильно зависяще от конкретно решаемых задач, конфигурации серверов доступа, топологии сети etc... посему какаого-либо универсального решения "для всех" здесь быть не может. Кроме того без чёткого понимания что делается, как, зачем и почему он тебе не только не поможет, но и может навредить... а имея вышеупомянутое понимание - и сам напишешь :D

другое дело - хочешь под ключ чисто под твои условия - формулируй задачу, цену обсудим ;)
Любой тупик - это тщательно замаскированный выход.

dnk2009
Сообщения: 121
Зарегистрирован: Сб окт 04, 2008 6:10 pm
Контактная информация:

Re: "Правильный" шейпер для исходящего траффика

Сообщение dnk2009 » Ср июн 10, 2009 6:33 pm

да дело не в этом. хотелось просто посмотреть на готовое решение профессионала. разобраться. может что то подчерпнуть для себя. в общем для самосовершенствования. :D

ran
Сообщения: 2298
Зарегистрирован: Вс окт 21, 2007 2:29 pm

Re: "Правильный" шейпер для исходящего траффика

Сообщение ran » Чт июн 11, 2009 3:46 am

говорюж - для того чтобы разобраться в том что я там наворотил нада чётко представлять себе задачи которые я этим решал, мои условия, мою топологию etc... ну выложу я его и что дальше? а дальше ты меня задолбаешь вопросами... а нафига мне это щастье? :D
Любой тупик - это тщательно замаскированный выход.

dnk2009
Сообщения: 121
Зарегистрирован: Сб окт 04, 2008 6:10 pm
Контактная информация:

Re: "Правильный" шейпер для исходящего траффика

Сообщение dnk2009 » Чт июн 11, 2009 11:20 am

а ты сделай коменты :D . с моей стороны вопросов не будет.

NiTr0
Сообщения: 767
Зарегистрирован: Пт фев 08, 2008 4:46 pm

Re: "Правильный" шейпер для исходящего траффика

Сообщение NiTr0 » Чт июн 11, 2009 5:48 pm

ran писал(а):фигня это всё... практика показывает, что какая-либо приоритезация/переупорядочивание очередей на уровне отдельно взятого усера - дело неблагодарное... одному нада так, другому эдак... пусть сами себя шейпят если надобно так как им хочется ;)...
Приоритет для Minimize-Delay траффика - какбы нужная вещь. Ну а внести туда еще пинги и запросы на создание тсп-сессий - тоже не помешает, но это уже рюшечки для душевного спокойствия более-менее продвинутых юзеров - приятно им увидеть малые задержки пинга при активно раздающем торренте :D Для сходных целей и большой буфер токенов сделан - чтобы даже на 128к юзеры могли достаточно комфортно серфить.
ran писал(а):к тому же ИМХО юзать IMQ не поддерживаемое официальным кернелом... уж лучше IFB... да канешна заворачивать и классифицировать придётся фильтрами а не иптеблс но там возможностей вполне лостаточно
IMQ - потому, что крутится это все на 2.4 ядре, которое о IFB еще и не догадывается - а если и можно патчем наложить, то опять-таки сомнительная целесообразность. Но фильтрация и т.д. сделана с учетом использования в принципе любого интерфейса.
ran писал(а):а вот глобальный шейпер с приоритезацией/переупорядочиванием - другое дело... лично у меня шейпер состоит из 2-х частей:

1. просто ограничитель скорости согласно классам трафика в интервалах. Тупой ограничитель с аграфигенной очередью через IFB (повторюсь - кому нада нехай шейпят/приоритизируют сами, не провайдерское это дело ;) )

2. глобальный шейпер на каждом внешнем канале - вот здесь и приоритезация и классификация (глобальная, зависящая от данного конкретного внешнего канала). Цель - наиболее рациональное использование канала (в общем), недопущение монополизации, отлов пирингов и тому подобных как, etc
Если это для корпоративных клиентов - возможно. Для домашних же - нужен нормальный ограничитель скорости, желательно - с поддержкой QoS, при котором к примеру с того же speedtest.net скорость четко режется, а не прыгает странным образом как при обычном ингресс шейпере; а давить торренты и т.д. - как раз ненужно, для них инет и покупается...

ran
Сообщения: 2298
Зарегистрирован: Вс окт 21, 2007 2:29 pm

Re: "Правильный" шейпер для исходящего траффика

Сообщение ran » Пт июн 12, 2009 10:45 am

Приоритет для Minimize-Delay траффика - какбы нужная вещь. Ну а внести туда еще пинги и запросы на создание тсп-сессий - тоже не помешает, но это уже рюшечки для душевного спокойствия более-менее продвинутых юзеров - приятно им увидеть малые задержки пинга при активно раздающем торренте
тоже по большому счёту фигня... основа приоритезации и комфортной работы при перегруженном исходящем канале - выделение исходящей приоритетной полосы нужной ширины (формулы рассчёта имеются) для ACK-пакетов (взведён флаг ACK остальные сброшены, длина до 100 байт)... остальное не так существенно... тогда и при перегруженном аплоаде даунлоад будет работать по максимуму

ЗЫ: причём полосы реал-тайм с малой задержкой и маленькой очередью ибо потеря ака не так существенна как потеря пакета данных и его повторная передача. По протоколу тсп любой ак полученный на конкретный пакет данных автоматически подтверждает получение всех предыдущих пакетов данных. Для этого лучше всего подходит дисциплина HFSC к сож весьма скудно документированная
Любой тупик - это тщательно замаскированный выход.

~AsmodeuS~
Site Admin
Сообщения: 5707
Зарегистрирован: Пт янв 28, 2005 3:11 pm
Контактная информация:

Re: "Правильный" шейпер для исходящего траффика

Сообщение ~AsmodeuS~ » Пн июл 06, 2009 10:08 am

так какие будут предложения по улучшению linkupdown ?

ran
Сообщения: 2298
Зарегистрирован: Вс окт 21, 2007 2:29 pm

Re: "Правильный" шейпер для исходящего траффика

Сообщение ran » Пн июл 06, 2009 1:12 pm

~AsmodeuS~ писал(а):так какие будут предложения по улучшению linkupdown ?
ну патч на линкапдаун для работы через IFB я тебе уже высылал... но ты почему-то его проигнорировал ;) хотя я сам давно уже его юзаю...

повторюсь - я не считаю необходимой какую либо приоритезацию на уровне клиентского канала - пусть сам приоритезирует что ему надо и как ему надо... моё дело предоставить ему канал заявленной толщины, а как он им будет распоряжаться - его личное дело. А вот перераспределение полосы на глобальном уровне конечно же необходимо... но никакого отношения к биллингу вообще и к линкапдауну в частности не имеет
Любой тупик - это тщательно замаскированный выход.

Abram
Сообщения: 157
Зарегистрирован: Чт мар 26, 2009 11:31 am
Контактная информация:

Re: "Правильный" шейпер для исходящего траффика

Сообщение Abram » Вт июл 07, 2009 4:07 am

~AsmodeuS~ писал(а):так какие будут предложения по улучшению linkupdown ?
Возможность дергать из биллинга для удаленного NAS.

ran
Сообщения: 2298
Зарегистрирован: Вс окт 21, 2007 2:29 pm

Re: "Правильный" шейпер для исходящего траффика

Сообщение ran » Вт июл 07, 2009 6:28 am

Abram писал(а):
~AsmodeuS~ писал(а):так какие будут предложения по улучшению linkupdown ?
Возможность дергать из биллинга для удаленного NAS.
для удалённого нас просто линкапдаун должен отрабатывать на удалённом насе
Любой тупик - это тщательно замаскированный выход.

antonmayko
Сообщения: 105
Зарегистрирован: Ср апр 01, 2009 8:53 pm

Re: "Правильный" шейпер для исходящего траффика

Сообщение antonmayko » Чт июл 09, 2009 2:40 pm

Уважаемые господа!

Сильно уж не пинайте, но хочу задать глупый вопрос как раз по самой теме.

На странице http://abills.net.ua/wiki/doku.php/abil ... l_linux:ru есть болванка для шейпера в обоих направлениях. Эта болванка повторена на многих других сайтах без изменений. Входящий трафик у меня режится нормально. А вот исходящий трафик не режет совсем.
Подскажите, что не правильно в этом коде:

Код: Выделить всё

##### speed client->server
   if [ "$DOWNSPEED" != "0" ] ;
   then
     /sbin/tc qdisc add dev $1 handle ffff: ingress
     /sbin/tc filter add dev $1 parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${DOWNSPEED}kbit burst 12k drop flowid :1
   fi
 fi
Надеюсь на помощь, т.к. гугль что-то маловато рассказывает о шейпинге исх. трафика.

За ранее - спасибо.
server: ubuntu-server 10.04.3, abills 0.55, 0.58b

NiTr0
Сообщения: 767
Зарегистрирован: Пт фев 08, 2008 4:46 pm

Re: "Правильный" шейпер для исходящего траффика

Сообщение NiTr0 » Чт июл 09, 2009 6:46 pm

tc q s dev ppp0 - и смотреть что там навешано. Возможно, в ядре нет дисциплины ingress.
Но если скорость и будет резать - то резать очень неаккуратно :( Почему я и занялся шаманством с нормальным шейпером на IMQ (либо - на eth0 с небольшими модификациями).

Ответить