Script - DHCP Lease to Simple Queues

Why?

Simple way for someone non tech savvy to figure out who or what is using bandwidth on the router. Individual computers / devices can be rate limited with ease. Virtually maintenance free as script keeps the simple queue table up to date and cleans up after itself.

What it does:

This script scans over the dhcp lease table in ROS to create simple queue entries for each item. It keeps the entries up to date and cleans up stale leases.

Usage:

Copy the below raw text into a new script entry within routeros.
Schedule the script to run at desired frequency in the routeros scheduler.

For devices shown as just a MAC address within simple queue list you can create a custom name under the dhcp lease table using the comment field.

# DHCP Lease to Simple Queues
# 2014 Lonnie Mendez (lmendez@anvilcom.com)
#
# Mikrotik RouterOS v6.9
 
/ip dhcp-server lease
:foreach x in=[find] do={
 
# grab variables for use below
:local leaseaddr ([get $x address]."/32")
:local leasemacaddr [get $x mac-address]
:local leasehostname [get $x host-name]
:local leasename [get $x comment]
:local queuecomment
 
:local leaseinqueue false
 
/queue simple
:foreach y in=[find] do={
 
#grab variables for use below
:local queuetargetaddr [get $y target]
:set queuecomment [get $y comment]
 
# Isolate information  from the comment field (MAC, Hostname)
:local queuemac [:pick $queuecomment 4 21]
:local queuehostname [:pick $queuecomment 22 [:len $queuecomment]]
 
# If MAC from lease matches the queue MAC then refresh the queue item
:if ($queuemac = $leasemacaddr) do={
# build a comment field
:set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)
 
set $y target=$leaseaddr comment=$queuecomment
:if ($leasename != "") do= {
set $y name=($leasename . " (" . $leasemacaddr . ")")
} else= {
:if ($leasehostname != "") do= {
set $y name=($leasehostname . " (" . $leasemacaddr . ")")
} else= {
set $y name=$leasemacaddr
}
}
:set leaseinqueue true
} else= {
# if ip exists for this lease but mac is different then update mac/hostname and reset counter
:if ($queuetargetaddr = $leaseaddr) do={
# build a comment field
:set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)
 
set $y comment=$queuecomment
reset-counters $y
:if ($leasename != "") do= {
set $y name=($leasename . " (" . $leasemacaddr . ")")
} else= {
:if ($leasehostname != "") do= {
set $y name=($leasehostname . " (" . $leasemacaddr . ")")
} else= {
set $y name=$leasemacaddr
}
}
:set leaseinqueue true
}
}
}
 
# There was not an existing entry so add one for this lease
:if ($leaseinqueue = false) do={
# build a comment field
:set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)
# build command
:local cmd "/queue simple add target=$leaseaddr max-limit=100M/100M comment=$queuecomment"
:if ($leasename != "") do={ 
:set cmd "$cmd name=\"$leasename ($leasemacaddr)\"" 
} else= {
:if ($leasehostname != "") do={
:set cmd "$cmd name=\"$leasehostname ($leasemacaddr)\""
} else= {
:set cmd "$cmd name=\"$leasemacaddr\""
}
}
 
:execute $cmd
}
}
 
# Cleanup Routine - remove dynamic entries that no longer exist in the lease table
/queue simple
:foreach z in=[find] do={
:local queuecomment [get $z comment]
:local queue1stpart [:pick $queuecomment 0 3]
:local queue2ndpart [:pick $queuecomment 4 21]
:if ( $queue1stpart = "dtq") do={
:if ( [/ip dhcp-server lease find mac-address=$queue2ndpart] = "") do={
:log info ("DTQ: Removing stale entry for MAC Address - " . $queue2ndpart)
remove $z
}
}
}

I see many errors, like “set alredyexistentvariable value”: miss $ in front of alreadyexistingvariable

When I have time, and if I remember it, I fix this script.

Hi dignome, your script is flawless… I made a small addition to discriminate between a range (minimum and maximum) of ip’s to thereby able to make different rules to different customers.

P.S.: I tried to do with network mask but I have not succeeded

Thanks, Bernardo.

# DHCP Lease to Simple Queues
# 2014 Lonnie Mendez (lmendez@anvilcom.com)
#
# Mikrotik RouterOS v6.9
 
/ip dhcp-server lease
:foreach x in=[find] do={
 
# grab variables for use below
:local leaseaddr ([get $x address])
:local leasemacaddr [get $x mac-address]
:local leasehostname [get $x host-name]
:local leasename [get $x comment]
:local queuecomment

:local minlimit 192.168.88.20
:local maxlimit 192.168.88.100
 
:local leaseinqueue false
 
/queue simple
:foreach y in=[find] do={
 
#grab variables for use below
:local queuetargetaddr [get $y target]
:set queuecomment [get $y comment]
 
# Isolate information  from the comment field (MAC, Hostname)
:local queuemac [:pick $queuecomment 4 21]
:local queuehostname [:pick $queuecomment 22 [:len $queuecomment]]
 
# If MAC from lease matches the queue MAC then refresh the queue item
:if ($queuemac = $leasemacaddr) do={
# build a comment field
:set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)
 
set $y target=$leaseaddr comment=$queuecomment
:if ($leasename != "") do= {
set $y name=($leasename . " (" . $leasemacaddr . ")")
} else= {
:if ($leasehostname != "") do= {
set $y name=($leasehostname . " (" . $leasemacaddr . ")")
} else= {
set $y name=$leasemacaddr
}
}
:set leaseinqueue true
} else= {
# if ip exists for this lease but mac is different then update mac/hostname and reset counter
:if ($queuetargetaddr = $leaseaddr) do={
# build a comment field
:set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)
 
set $y comment=$queuecomment
reset-counters $y
:if ($leasename != "") do= {
set $y name=($leasename . " (" . $leasemacaddr . ")")
} else= {
:if ($leasehostname != "") do= {
set $y name=($leasehostname . " (" . $leasemacaddr . ")")
} else= {
set $y name=$leasemacaddr
}
}
:set leaseinqueue true
}
}
}
 
# There was not an existing entry so add one for this lease
:if ($leaseinqueue = false) do={
# build a comment field
:set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)
# build command
:local cmd "/queue simple add target=$leaseaddr max-limit=128k/2M comment=$queuecomment"
:if ($leasename != "") do={ 
:set cmd "$cmd name=\"$leasename ($leasemacaddr)\"" 
} else= {
:if ($leasehostname != "") do={
:set cmd "$cmd name=\"$leasehostname ($leasemacaddr)\""
} else= {
:set cmd "$cmd name=\"$leasemacaddr\""
}
}
 
# If within the range is executed
:if ($leaseaddr >= $minlimit && $leaseaddr <= $maxlimit) do={
:execute $cmd
}
}
}
 
# Cleanup Routine - remove dynamic entries that no longer exist in the lease table
/queue simple
:foreach z in=[find] do={
:local queuecomment [get $z comment]
:local queue1stpart [:pick $queuecomment 0 3]
:local queue2ndpart [:pick $queuecomment 4 21]
:if ( $queue1stpart = "dtq") do={
:if ( [/ip dhcp-server lease find mac-address=$queue2ndpart] = "") do={
:log info ("DTQ: Removing stale entry for MAC Address - " . $queue2ndpart)
remove $z
}
}
}

I recently needed to create queues for DHCP entries, and I used a much simpler solution… The following script is applied as lease-script:

:local queueName "Guest $leaseActMAC";

:if ($leaseBound = "1") do={
    /queue simple add name=$queueName parent=GUESTS place-before="Guest STATIC" target=($leaseActIP . "/32") max-limit=10M/10M comment=[/ip dhcp-server lease get [find where active-mac-address=$leaseActMAC && active-address=$leaseActIP] host-name];
} else={
    /queue simple remove $queueName
}

Where the parent queue “GUESTS” contains the total to be divided between users. And as you can see, each user gets 10Mbps upload and download… Adjust accordingly ifyou prefer some other rates.

Whenever a DHCP entry expires (or is forcefully removed), the lease-script is invoked with $leaseBound set to “0”, so this takes care of both adding and removing queues.

Can you please specify how to add a lease script?

From Winbox (or AFAIK, in WebFig it’s the same…), go to the “IP > DHCP Server” menu, and at the “DHCP” tab, double click on the DHCP server you want to add a script to. Paste/write the script into the text box at the bottom (where just above it, it says “Lease script:”).

Hello, I´m just trying to excute the script manually to test it, but unfortunatelly aparently do nothing. The simple queues list don´t have nothing to show. What are the correct policies to run this script? Is compatible with routeros 6.34.4?. I´m trying that one of the users of the local network don´t use all the bandwith and the rest won´t have internet.

Thanks

Hello, I´m just trying to excute the script manually to test it, but unfortunatelly aparently do nothing.

This script requires the DHCP variables injected when the lase-script is ran, so you can’t just run this from terminal. You need values for $leaseActMAC and $leaseActIP, which actually correspond with a pre-existing lease.

I’d suggest that to test that, you apply it to a real DHCP server, but if you want to make sure limitations don’t go into effect, just create queues that are disabled on their creation, i.e.:

/queue simple add disabled=yes ...

try this
http://forum.mikrotik.com/t/make-automatic-static-dhcp-leases/101221/1

Hello

I am curious about this script,

Does any one know if the Queues will limit the Target immediately or only if there are many other leases assigned ?

Any info will be hugely appreciated.
Thanks in advance

Thank bro for this scrip I needed this script 1 month ago when I had to create several individual queues ,:-((((((
I can confirm that it works perfectly in 6.43.4.
by the way, I upload the post because the scrip is very interesting and very simple.

Greetings and thanks again

edit: speak too fast, , seems to add the queues well but does not eliminate the queue when the entires expires o forced :frowning: . any help :slight_smile:

TYVM
Saved me Hours trying to do this myself
The remove at the end is Genius
Kudos, Upvotes and Gold to you Sir

wait…with /22 no work. help please.

Woooow this works perfectly thanks!!!

Please help to modifying script “DHCP Lease to Simple Queues” to work on Mikrotik RouterOS v7.13
Note that the script worked well on the previous version Mikrotik RouterOS v6.9