📜 ⬆️ ⬇️

Mikrotik Router OS, script for dynamic speed division

Mikrotik Router OS, a script for dynamic speed division.



The other day, the following problem arose: to divide the speed equally between all users, so that the speed was not allocated to customers who currently do not use the Internet, but to give to everyone else, so that with a large number of customers and a narrow channel, they get some kind of “buffering” channel.

Having carefully studied a handful of manuals, I came to the conclusion that without raising the script in the internal language of Router OS can not do.
')
The script works only with VPN clients, since I did not find a way to work with individual IP.

So let's go!

An example of three PPTP users, primary configuration

Addresses of users 192.168.70.10-192.168.70.12
Server address 192.168.70.1

Add three users:

/ 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


Add to each of the users on the interface, the interface name and user name must match!

/ 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, I don’t know why, but in all examples the specialists first mark the connection, and then mark the packages in it, maybe I don’t quite understand the whole depth of thought, but I don’t see a special point in this and mark the packages right away in the general stream, because . every extra rule noticeably slows down the system. Attention! the value of new-packet-mark should be “username / server” + “_ down” and “_up”, respectively.

/ 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


The next step is to build a tree in Queue. All traffic restrictions will occur in it.

/ 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


The last step is to configure the computational part of the script and place it in the system scheduler, with an interval of 10-60 seconds. depending on the performance of your microtic, the smaller the interval - the better.

Variables and some features of the computing part

MaxRateDownload - ()
MaxRateUpload - ()
ActiveThresholddown - ()
ActiveThresholdup - ()
ParentDownload - ()
ParentUpload - ()


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


It should be set slightly less than the width of your channel in order to avoid brakes when another user is active, who has not consumed the Internet before.

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


Set these values ​​according to your needs, but based on the calculation: the number of users multiplied by Thresholddown = should not exceed MaxRateDownload otherwise your users will always be inactive! Naturally users * ActiveThresholdup = should not exceed MaxRateUpload. Always leave some stock.

The principle of the script

The script measures how fast the client is running and if it exceeds ActiveThresholddown, adds it as an active one to receive,
it also increases the counter if the user is connected to his account's PPTP.
Next, the script checks ActiveThresholdup, if the user has exceeded this mark, then adds it as active for feedback.

If the number of active clients is zero, it changes it to one, for later to make mathematical calculations, and then something is not divided by zero :)

Calculates:
MaxRateDownload divides by the number of active users to receive, displays the speed per user.
MaxRateUpload divides by the number of active users per share, displays the speed per user.

Next, it sets a limit to all users in the Queue Tree, as calculated above.

Next, it calculates the value in kilobits and displays statistics in the log.

Script code

For different versions of Router OS, you need your own version of the script. This is due to the fact that the internal syntax of the language gradually evolves and thus does not always please users.

Script code for versions 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!


Script code for version 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!


Script code for versions 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!

Source: https://habr.com/ru/post/110745/


All Articles