Mikrotik Router OS, скрипт для динамического деления скорости

Mikrotik Router OS, скрипт для динамического деления скорости.



На днях встала следующая проблема: делить скорость поровну между всеми пользователями, причем так, чтобы скорость не выделялась на клиентов, которые на данный момент не пользуются интернетом, а отдавалась всем остальным, еще чтобы при большом количестве клиентов и узком канале получить некоторую «буферность» канала.

Внимательно изучив кучку мануалов, пришел к выводу, что без поднятия скрипта на внутреннем языке Router OS никак не обойтись.

Скрипт работает только с VPN клиентами, т.к. не нашел способа работы с отдельными IP.

Итак, поехали!

Пример на трех PPTP пользователей, первичная настройка

Адреса пользователей 192.168.70.10-192.168.70.12
Адрес сервера 192.168.70.1

Добавляем трех пользователей:

/ ppp secret add name="user1" service=pptp password="null" profile=default-encryption local address=192.168.70.1 remote-address=192.168.70.10 disabled=no
/ ppp secret add name="user2" service=pptp password="null" profile=default-encryption local-address=192.168.70.1 remote-address=192.168.70.11 disabled=no
/ ppp secret add name="user3" service=pptp password="null" profile=default-encryption local-address=192.168.70.1 remote-address=192.168.70.12 disabled=no


Добавляем на каждого из пользователей по интерфейсу, имя интерфейса и имя пользователя должны совпадать!

/ interface pptp-server add name="user1" user="user1" disabled=no
/ interface pptp-server add name="user2" user="user2" disabled=no
/ interface pptp-server add name="user3" user="user3" disabled=no


Mangle, не знаю почему, но во всех примерах специалисты сначала маркируют соединение, а потом помечают в нем пакеты, может быть я не совсем понимаю всей глубины мысли, но не вижу в этом особого толка и помечаю пакеты сразу в общем потоке, т.к. каждое лишнее правило заметно тормозит систему. Внимание! значение new-packet-mark должно быть «имя пользователя/сервера» +"_down” и “_up” соответственно.

/ ip firewall mangle add chain=forward src-address=192.168.70.10 dst-address=0.0.0.0/0 action=mark-packet new-packet-mark=user1_up passthrough=no disabled=no
/ ip firewall mangle add chain=forward src-address=192.168.70.11 dst-address=0.0.0.0/0 action=mark-packet new-packet-mark=user2_up passthrough=no disabled=no
/ ip firewall mangle add chain=forward src-address=192.168.70.12 dst-address=0.0.0.0/0 action=mark-packet new-packet-mark=user3_up passthrough=no disabled=no

/ ip firewall mangle add chain=forward src-address=0.0.0.0/0 dst-address=192.168.70.10 action=mark-packet new-packet-mark=user1_down passthrough=no disabled=no
/ ip firewall mangle add chain=forward src-address=0.0.0.0/0 dst-address=192.168.70.11 action=mark-packet new-packet-mark=user2_down passthrough=no disabled=no
/ ip firewall mangle add chain=forward src-address=0.0.0.0/0 dst-address=192.168.70.12 action=mark-packet new-packet-mark=user3_down passthrough=no disabled=no


Следующим шагом необходимо построить дерево в Queue. В нем и будут происходить все ограничения трафика.

/ queue tree add name="Download" parent=global-out limit-at=0 queue=hotspot-default priority=8 max-limit=0 burst-limit=0 burst-threshold=0 burst-time=0s disabled=no
/ queue tree add name="user1_down" parent=Download packet-mark=user1_down disabled=no
/ queue tree add name="user2_down" parent=Download packet-mark=user2_down disabled=no
/ queue tree add name="user3_down" parent=Download packet-mark=user3_down disabled=no

/ queue tree add name="Upload" parent=global-out limit-at=0 queue=hotspot-default priority=8 max-limit=0 burst-limit=0 burst-threshold=0 burst-time=0s disabled=no
/ queue tree add name="user1_up" parent=Upload packet-mark=user1_up disabled=no
/ queue tree add name="user2_up" parent=Upload packet-mark=user2_up disabled=no
/ queue tree add name="user3_up" parent=Upload packet-mark=user3_up disabled=no


Последним шагом будет настройка вычислительной части скрипта и помещения ее в планировщик системы, с интервалом 10-60 сек. в зависимости от производительности вашего микротика, чем меньше интервал — тем лучше.

Переменные и некоторые особенности настройки вычислительной части

MaxRateDownload -Ширина канала на всех пользователей (прием)
MaxRateUpload -Ширина канала на всех пользователей (отдача)
ActiveThresholddown -Порог при превышении которого пользователь будет считаться активным (прием)
ActiveThresholdup - Порог при превышении которого пользователь будет считаться активным (отдача)
ParentDownload -Родитель очереди (прием)
ParentUpload - Родитель очереди (отдача)


:local MaxRateDownload ("2000000");
:local MaxRateUpload ("2000000");


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

:local ActiveThresholddown ("5000");
:local ActiveThresholdup ("5000");


Эти значения устанавливайте согласно своим потребностям, но исходя из расчета: кол-во пользователей умноженное на Thresholddown =не дожно превышать MaxRateDownload иначе ваши пользователи будут всегда не активными! Естественно users*ActiveThresholdup= не должно превышать MaxRateUpload. Всегда оставляйте некоторый запас.

Принцип работы скрипта

Скрипт замеряет, с какой скоростью работает клиент и если она превышает ActiveThresholddown, добавляет его как активного на прием,
так же, увеличивает счетчик, если пользователь подключен к PPTP своей учетной записи.
Далее скрипт производит проверку ActiveThresholdup, если пользователь превысил эту отметку, то добавляет его как активного на отдачу.

Если количество активных клиентов равно нулю, изменяет его на единицу, ибо впоследствии произвести математические расчеты, а то что то на ноль не делится :)

Рассчитывает:
MaxRateDownload делит на количество активных пользователей на прием, выводит скорость на одного пользователя.
MaxRateUpload делит на количество активных пользователей на отдачу, выводит скорость на одного пользователя.

Далее устанавливает лимит всем пользователям в Queue Tree согласно рассчитанной выше.

Далее рассчитывает значение в килобитах и выводит в лог статистику.

Код скрипта

Для разных версий Router OS, нужна своя версия скрипта. Это связано с тем, что внутренний синтаксис языка постепенно эволюционирует и тем самым не всегда радует пользователей.

Код скрипта для версий 2.9.xx:

######################
:local MaxRateDownload ("2000000");
:local MaxRateUpload ("2000000");
:local ActiveThresholddown ("5000");
:local ActiveThresholdup ("5000");
:local ParentDownload ("Download");
:local ParentUpload ("Upload");
######################

######################
:local z;
:local i;
:local ii;
:local userX;
:global onlineclientsdown (0);
:global onlineclientsup (0);
:global connected (0);
######################

######################
:foreach i in=[/ppp active find] do={ :set userX [/ppp active get $i name];
:global connected ($connected+1);
/interface monitor-traffic [/interface find name=$userX] once do {:if ($received-bits-per-second>=$ActiveThresholddown) do { :set onlineclientsdown ($onlineclientsdown+1);}} };

:foreach ii in=[/ppp active find] do={ :set userX [/ppp active get $ii name];
/interface monitor-traffic [/interface find name=$userX] once do {:if ($sent-bits-per-second>=$ActiveThresholdup) do { :set onlineclientsup ($onlineclientsup+1);}} };

:if ($onlineclientsdown = 0) do {:set onlineclientsdown (1)};
:if ($onlineclientsup= 0) do {:set onlineclientsup (1)};

:local ratelimitdown ($MaxRateDownload/$onlineclientsdown)
:local ratelimitup ($MaxRateUpload/$onlineclientsup)

:foreach z in=[/ppp active find] do={ :set userX [/ppp active get $z name];
/queue tree set [/queue tree find name=($userX . "_down")] parent=$ParentDownload packet-mark=($userX . "_down") queue=hotspot-default priority=8 max-limit=$ratelimitdown

/queue tree set [/queue tree find name=($userX . "_up")] parent=$ParentUpload packet-mark=($userX . "_up") queue=hotspot-default priority=8 max-limit=$ratelimitup};
######################

######################
:local kbsmaxdown ($MaxRateDownload/1000);
:local kbsmaxup ($MaxRateUpload /1000);
:local kbsthr ($ActiveThresholddown/1000);
:local kbsdown ($ratelimitdown/1000);
:local kbsup ($ratelimitup/1000);

:log warning ("Shaper:");
:log info ("MaxRate Download : " . $MaxRateDownload . " bps /" . $kbsmaxdown . " kbs / Upload : " . $MaxRateUpload . " bps /" . $kbsmaxup . " kbs");
:log info ("Threshold: Download : " . $ActiveThresholddown . " bps /" . $kbsthr . " kbs / Upload : " . $ActiveThresholdup . " bps /" . $kbsthr . " kbs");
:log info ("Connected Users : " . $connected);
:log info ("Active Users : Download : " . $onlineclientsdown . " / Upload : " . $onlineclientsup);
:log info ("User Speed Download : " . $ratelimitdown . " bps /" . $kbsdown . " kbs / Upload : " . $ratelimitup . " bps /" . $kbsup . " kbs");
######################
# (C) Inlarion icq 429-587 Copyright!


Код скрипта для версии 3.22:

######################
:local MaxRateDownload ("2000000");
:local MaxRateUpload ("2000000");
:local ActiveThresholddown ("5000");
:local ActiveThresholdup ("5000");
:local ParentDownload ("Download");
:local ParentUpload ("Upload");
######################

######################
:local z;
:local i;
:local ii;
:local userX;
:global onlineclientsdown (0);
:global onlineclientsup (0);
:global connected (0);
######################

######################
:foreach i in=[/ppp active find] do={ :set userX [/ppp active get $i name];
:global connected ($connected+1);
/interface monitor-traffic [/interface find name=$userX] once do {:if ($"received-bits-per-second">=$ActiveThresholddown) do { :set onlineclientsdown ($onlineclientsdown+1);}} };

:foreach ii in=[/ppp active find] do={ :set userX [/ppp active get $ii name];
/interface monitor-traffic [/interface find name=$userX] once do {:if ($"sent-bits-per-second">=$ActiveThresholdup) do { :set onlineclientsup ($onlineclientsup+1);}} };

:if ($onlineclientsdown = 0) do {:set onlineclientsdown (1)};
:if ($onlineclientsup= 0) do {:set onlineclientsup (1)};

:local ratelimitdown ($MaxRateDownload/$onlineclientsdown)
:local ratelimitup ($MaxRateUpload/$onlineclientsup)

:foreach z in=[/ppp active find] do={ :set userX [/ppp active get $z name];
/queue tree set [/queue tree find name=($userX . "_down")] parent=$ParentDownload packet-mark=($userX . "_down") queue=hotspot-default priority=8 max-limit=$ratelimitdown

/queue tree set [/queue tree find name=($userX . "_up")] parent=$ParentUpload packet-mark=($userX . "_up") queue=hotspot-default priority=8 max-limit=$ratelimitup};
######################

######################
:local kbsmaxdown ($MaxRateDownload/1000);
:local kbsmaxup ($MaxRateUpload /1000);
:local kbsthr ($ActiveThresholddown/1000);
:local kbsdown ($ratelimitdown/1000);
:local kbsup ($ratelimitup/1000);

:log warning ("Shaper:");
:log info ("MaxRate Download : " . $MaxRateDownload . " bps /" . $kbsmaxdown . " kbs / Upload : " . $MaxRateUpload . " bps /" . $kbsmaxup . " kbs");
:log info ("Threshold: Download : " . $ActiveThresholddown . " bps /" . $kbsthr . " kbs / Upload : " . $ActiveThresholdup . " bps /" . $kbsthr . " kbs");
:log info ("Connected Users : " . $connected);
:log info ("Active Users : Download : " . $onlineclientsdown . " / Upload : " . $onlineclientsup);
:log info ("User Speed Download : " . $ratelimitdown . " bps /" . $kbsdown . " kbs / Upload : " . $ratelimitup . " bps /" . $kbsup . " kbs");
######################
# (C) Inlarion icq 429-587 Copyright!


Код скрипта для версий 3.30 — 4.x — 5.x:

######################
:local MaxRateDownload ("2000000");
:local MaxRateUpload ("2000000");
:local ActiveThresholddown ("5000");
:local ActiveThresholdup ("5000");
:local ParentDownload ("Download");
:local ParentUpload ("Upload");
######################

######################
:local z;
:local i;
:local ii;
:local userX;
:global onlineclientsdown (0);
:global onlineclientsup (0);
:global connected (0);
######################

######################
:foreach i in=[/ppp active find] do={ :set userX [/ppp active get $i name];
:global connected ($connected+1);
/interface monitor-traffic [/interface find name=$userX] once do {:if ($"rx-bits-per-second">=$ActiveThresholddown) do { :set onlineclientsdown ($onlineclientsdown+1);}} };

:foreach ii in=[/ppp active find] do={ :set userX [/ppp active get $ii name];
/interface monitor-traffic [/interface find name=$userX] once do {:if ($"tx-bits-per-second">=$ActiveThresholdup) do { :set onlineclientsup ($onlineclientsup+1);}} };

:if ($onlineclientsdown = 0) do {:set onlineclientsdown (1)};
:if ($onlineclientsup= 0) do {:set onlineclientsup (1)};

:local ratelimitdown ($MaxRateDownload/$onlineclientsdown)
:local ratelimitup ($MaxRateUpload/$onlineclientsup)

:foreach z in=[/ppp active find] do={ :set userX [/ppp active get $z name];
/queue tree set [/queue tree find name=($userX . "_down")] parent=$ParentDownload packet-mark=($userX . "_down") queue=hotspot-default priority=8 max-limit=$ratelimitdown

/queue tree set [/queue tree find name=($userX . "_up")] parent=$ParentUpload packet-mark=($userX . "_up") queue=hotspot-default priority=8 max-limit=$ratelimitup};
######################

######################
:local kbsmaxdown ($MaxRateDownload/1000);
:local kbsmaxup ($MaxRateUpload /1000);
:local kbsthr ($ActiveThresholddown/1000);
:local kbsdown ($ratelimitdown/1000);
:local kbsup ($ratelimitup/1000);

:log warning ("Shaper:");
:log info ("MaxRate Download : " . $MaxRateDownload . " bps /" . $kbsmaxdown . " kbs / Upload : " . $MaxRateUpload . " bps /" . $kbsmaxup . " kbs");
:log info ("Threshold: Download : " . $ActiveThresholddown . " bps /" . $kbsthr . " kbs / Upload : " . $ActiveThresholdup . " bps /" . $kbsthr . " kbs");
:log info ("Connected Users : " . $connected);
:log info ("Active Users : Download : " . $onlineclientsdown . " / Upload : " . $onlineclientsup);
:log info ("User Speed Download : " . $ratelimitdown . " bps /" . $kbsdown . " kbs / Upload : " . $ratelimitup . " bps /" . $kbsup . " kbs");
######################
# (C) Inlarion icq 429-587 Copyright!
Поделиться публикацией

Комментарии 11

    +8
    Как по заказу!
    Только дня четыре назад встала аналогичная задача — делим интернет с соседом.
    Вот это называется «качественный сервис». А вы говорите «телепатов нет» :)
      +1
      А разве это не решает поставленной задачи? Смотрите на картинку в разделе PCQ Rate Examples.
        +2
        Да, я понимаю о чем вы, но к сожалению это действительно не решает поставленной задачи.
        В теории конечно же все красиво и правильно при параметре pcq-rate=0, но на практике это выглядит приблизительно так:

        Клиент 1 активно закачивает файл или торрент, и занимает всю полосу пропускания.
        Клиент 2 пытается так же поставить на закачку что то тяжелое, тут возникает первая маленькая проблема, скорость разделения полосы путем удаления пакетов из очереди происходит не так быстро как хотелось бы, в итоге получаем небольшую потерю пакетов на втором клиенте которая проходит через 5-15 сек. А так же резкое увеличение времени пинга на первом клиенте. Частично эта проблема решаема с помощью Burst.
        Далее канал начнет делится на двух пользователей, и если внимательно мониторить клиентов и очереди, можно увидеть нехорошую картину:
        Для примера ширина канала 5 мегабит.
        Первому пользователю, будет отведена скорость приблизительно 2,1-2,3 мегабита.
        Второму пользователю, который только что подключился, будет выдано 2,7-2,9 мегабита.
        Нечестно!
        Данные скорости уравняются до честных пределов только через 5-10 минут! И это при довольно шустрой конфигурации.
        В конфигурациях с 10 и более пользователями все выглядит еще более печально, особенно если к качкам добавить серферов и геймеров, последние первыми забьют тревогу при узком канале. Разработчики Router OS об этом прекрасно знают еще с версии 2.х но по прежнему ничего нового не могут, или не хотят делать. Но самое удивительное что правила с жестко заданными Max limit работают как часы, никаких висяков и провалов по скорости.
        Я понимаю что мое решение не верх гениальности, т.к. с плюсами приходят и минусы в виде расточительного использования системных ресурсов, но альтернативного варианта, я к сожалению пока не нашел, или плохо искал :) На днях буду проверять RC7 возможно в этой версии будет что то более похожее на правильную реализацию pcq.
        +1
        tc из iproute2 и его HTB разве не проще и быстрее настроить на обычном линуксе ?)
          0
          Не могу адекватно ответить на ваш вопрос, обычный линукс еще нужно немного знать, наверно для тех кто хорошо шарит в линуксе скорее всего проще и быстрее.
          А для тех кто не шарит, и особо не хочет учится новому, проще и быстрее будет на микротике.
          У каждого способа реализации есть свои плюсы и минусы, минус микротика можно наблюдать выше в качестве построения заборов, грабель и костылей.
          Тем более что микротик это не только x86, но и routerboard и хочешь, не хочешь, а железка лежит и ее надо как то настроить.
          0
          Отлично!
            0
            Не хотите еще что-нить написать про некротик? Настройку QoS, например…
              0
              В принципе про QoS на микротике уже довольно много сказано на просторах всея интернета.
              Ссылка на сайт с данными статьями есть в моем профиле.
              Писать обязательно буду. В голове крутятся пара идей. Так же будет вторая версия данного поста после окончательного тестирования.
              –1
              В доме делим интернет 3.2 мбит на 10 человек. У нас в Иркутске этот канал стоит 1900 р.!

              Просто стоит модем Acorp Lan 422 на нем настроен шейпер вот так:


              Настраивал не я и но делали по инструкции c форума Acorp.
              В принципе работает. Но если, кто-то включает торренты пинг возрастает. Поэтому договрились днем не качать. Но бывает кто-то забывает и качает, ему ограничиваем порты, вот так:


              Тогда у него вообще торренты не качаются.

              Торренты можно качать с 2 до 10 am
              Еще у нас есть внутренний ресурс с фильмами и т.п. с которого скорость 10 Мбит.
              Поэтому шейпер вообще вырубается с помощью расширений для Firefox imcaros и my weekly browsing. Первое расширение — запись действий для снятия галки на странице настройки щейпера в модеме. Второе — запуск этого действия по-расписанию: в 2 и 10 am. Вот такое извращение. Может быть есть у кого идеи как это сделать менее извращенно? :)

              Когда перейдем на оптику поставим комп-роутер и воспользуемся Microtic Router OS. А может быть есть железное решение, т.е. роутер, который хорошо динамически делаит канал? Может что посоветуете?
                0
                а у нас стоит 625 рублей (в пересчете) — 100 мегабит анлим

                и какое это имеет отношение к статье?
                  0
                  Все будет зависеть от потребностей по передаче. Сколько мегабит планируете прокачивать через девайс?
                  Если железка слабая и нужно много прокачивать, начинайте изучать линукс.
                  Если железка будет мощной или поток небольшой, можно обойтись микротиком. Даже возможно на базе routerboard.
                  Что касается хардварных решений то были бы деньги а Cisco или ZyWall найдется. :)

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое