Час від часу було необхідно обмежити швидкість тим чи іншим клієнтам локальної мережі, які отримують адресу по DHCP.
Що робили?
По-перше, створювали чергу для локальної мережі, наприклад так:
/queue simple add burst-limit=200M/200M burst-threshold=2M/2M burst-time=5s/5s max-limit=198M/198M name=lan queue=pcq-upload-src/pcq-download-dst target=bridge-local total-queue=pcq-dst-src
По-друге, фіксували за mac-адресою ту чи іншу ip-адресу. По-третє, створювали чергу, яку через parent підв'язували до створеної черги локальної мережі і обмежували швидкість для саме цієї ip-адреси.
Така схема робоча, але не дуже зручна, коли треба обмежити швидкість, скажемо так, масово.
Припустимо купуємо у провайдера 100 мегабіт. У нас 10 робочих місць. Задача - кожному роздати по 10 мегабіт.
Звісно можна зафіксувати адреси, а можна…
Варіант 1. Старе рішення.
Перший варіант, який приходить на думку: обійти таблицю leases і під кожну виділену ip-адресу створити відповідне правило в черзі. Це вирішується якось так (позичено і перероблено з форуму MikroTIK):
/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.100.20 :local maxlimit 192.168.100.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 parent=lan 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\"" } } # 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 } } }
Це дійсно працює. Цей скрипт можна додати в Scheduler і насолоджуватися його роботою. Звісно за необхідності варто змінити на свій смак встановлення локальної змінної cmd.
Цей метод працює на будь-яких версіях RouterOS (правда на дуже старих не перевіряв, але має працювати, бо тут нічого складного і специфічного немає.
Явним недоліком є саме необхідність використання Scheduler, щоб підтримувати черги в актуальному стані.
Про те є інший, більш елегантний метод. Більш легкий метод.
Варіант 2. Lease Script.
В WinBox (або в WebFig, кому як подобається) переходимо в IP → DHCP Server. Відкриваємо налаштування свого DHCP. Переходимо у вкладку Script. Тут у нас велике поле для Lease Script, який буде виглядати приблизно так:
:local queueName "lan-$leaseActIP-$leaseActMAC"; :if ($leaseBound = "1") do={ :log info "DHCP Lease START: $queueName" :local hostName [/ip dhcp-server lease get [find where active-mac-address=$leaseActMAC && active-address=$leaseActIP] host-name] /queue simple add burst-limit=50M/50M burst-threshold=1M/1M burst-time=5s/5s max-limit=49M/49M total-burst-limit=50M total-burst-threshold=1M total-burst-time=5s total-limit-at=48M total-max-limit=49M total-queue=pcq-dst-src name=$queueName parent=lan target=($leaseActIP . "/32") comment="$leaseActIP [ $leaseActMAC ] $hostName"; } else={ :log info "DHCP Lease STOP: $queueName" /queue simple remove $queueName }
І все. Скрипт викликається DHCP-сервером коли він «видає» або «забирає» ip-адресу. Відповідним чином встановлюється змінн $leaseBound, коли сервер видає адресу вона дорівнює "1".
Звісно, що тут можна додати й інші умови, інші виключення, тощо. Можна зробити й іншу структуру самих черг. Але, сподіваюся, що все й без того прозоро й зрозуміло. Користуймося.