When I heard that they're gonna make LEDs non-programmable I was like HELL NO. And decided to do what MikroTik probably should do from very beginning - simulate faster LEDs in software to keep best of both worlds - programmable LEDs AND fast blinking LEDs. I'm aware it's not really "correct" solution because it kinda... makes up data basing on 1s interval read but I hope many people will still find it useful. Current implementation of LEDs in CRS3xx switches blinks like once every 2 seconds so sometimes it's really hard to tell whether there's actually any traffic since it's easy to miss that 1 blink every 2 seconds lol...
So here's code. LED blinker for sfp ports (CRS317, CRS326)
Code: Select all
add name=ledblinkersfp source="/interface ethernet\
\n\
\n:local cycletime 1000\
\n:local cyclenum 2\
\n:local blinkpercycle 8\
\n:local blinkparts 3\
\n:local ifmatch \"sfp-sfpplus\"\
\n:local instance \"ledblinkersfp\"\
\n:local ledsuffix \"-led1\"\
\n\
\n######\
\n\
\n\
\n:local pstat ({})\
\n\
\n:while ([:len [/system script job find script=\$instance]] = 1) do={\
\n\
\n :local iflst [find name~(\$ifmatch) running=yes]\
\n :local ledlst ({})\
\n\
\n :local blinkshort (\$cycletime / \$blinkpercycle)\
\n :local blinkshortoff (\$blinkshort / \$blinkparts)\
\n :local blinkshorton (\$blinkshortoff * (\$blinkparts -1))\
\n\
\n :local realblinkshorton (\$blinkshorton - 50)\
\n :if (\$realblinkshorton < 0) do={\
\n :set realblinkshorton 0\
\n }\
\n\
\n /system leds set [find name~(\$ifmatch) running=no] type=interface-activity\
\n :if ([:len \$iflst] != [:len \$pstat]) do={\
\n :set pstat ({})\
\n :foreach counter=i in=\$iflst do={\
\n :set pstat (\$pstat,\"0/0\")\
\n }\
\n }\
\n\
\n :foreach counter=k,i in=\$iflst do={\
\n :local iname [get \$i name] \
\n :local iled [/system leds find leds=(\$iname.\$ledsuffix)]\
\n :set ledlst (\$ledlst, \$iled)\
\n }\
\n\
\n\
\n :for counter=loop from=1 to=\$cyclenum do={ \
\n :local cstat ({})\
\n :local blinklst ({})\
\n\
\n :foreach counter=k,i in=\$iflst do={\
\n :local istat ([get \$i rx-bytes].\"/\".[get \$i tx-bytes])\
\n :local iled (\$ledlst->\$k)\
\n :set cstat (\$cstat, \$istat)\
\n :if (\$istat != (\$pstat->\$k)) do={\
\n :set blinklst (\$blinklst, (\$iled))\
\n }\
\n }\
\n :for counter=i from=0 to=(\$cycletime / \$blinkshort - 1) do={\
\n :if (\$i = 0) do={\
\n :delay delay-time=((\$realblinkshorton).\"ms\")\
\n } else={\
\n :delay delay-time=((\$blinkshorton).\"ms\")\
\n }\
\n\
\n :foreach counter=j in=\$blinklst do={\
\n /system leds set \$j type=off\
\n }\
\n :delay delay-time=((\$blinkshortoff).\"ms\")\
\n :foreach counter=j in=\$blinklst do={\
\n /system leds set \$j type=on\
\n }\
\n }\
\n :set pstat \$cstat\
\n }\
\n}"
For LED blinker for ether ports (CRS326 only) you only need to change script name to "ledblinkereth" and change variables on top of script to:
Code: Select all
\n:local ifmatch \"ether\"\
\n:local instance \"ledblinkereth\"\
\n:local ledsuffix \"-led\"\
Here's script to reset all LEDs back to "interface-activity" type if someone doesn't want to use script anymore:
Code: Select all
add name=ledreset source="/interface ethernet\
\n\
\n:local ledsuffix \"-led1\"\
\n:local iflst [find name~\"sfp-sfpplus\"]\
\n\
\n:foreach counter=k,i in=\$iflst do={\
\n :local iname [get \$i name]\
\n :local iled [/system leds find leds=(\$iname.\$ledsuffix)]\
\n :put (\"Reset: \".[/system leds get \$iled leds])\
\n /system leds set \$iled type=interface-activity\
\n}\
\n"
Script comes with some defaults I found reasonable but if you want, blinking speed and behavior is configurable. How to configure it:
- :local cycletime 1000 <- time between interface stats probing. By default 1000ms since CRS3xx chip reports rx and tx bytes only once every second
- :local cyclenum 2 <- how many probe cycles will be performed before interface details will be refreshed (number of cycles before eg. interface down will be noticed. By default 2 seconds)
- :local blinkpercycle 8 <- how many times LED will blink during single cycle (during 1 second by default)
- :local blinkparts 3 <- ratio of LED on / LED off for each blink. By default 1/3 time LED is off and 2/3 time it's on
- :local ifmatch "sfp-sfpplus" <- pattern for interface match
- :local instance "ledblinkersfp" <- name of script as you added it in /system script (script uses it to determine whether script is already running as job. Each instance of blinker has to use unique name eg. ledblinkersfp and ledblinkereth for CRS326)
- :local ledsuffix "-led1" <- suffix that has to be added to interface name to find matching LED.