🔌 Script to periodically check link-speed of Ethernet ports

A rather common issue is negotiated Ethernet link-speeds dropping due to cable issues, bad electrical connections etc. (a very common case is link-speeds dropping to 100 Mbps).
Often such network degradation take a lot of time to be noticed (especially if no packet loss is observed, especially on less-utilized links).
Here is a simple script that checks link-speed of Ethernet/SFP interfaces against a predefined list and sends e-mail about any interfaces not matching the listed link-speeds.

:local ifspeeds {"ether1"="1Gbps-full";"ether2"="1Gbps-full";"ether5"={"1Gbps-full";"no-link"}}
:local recipient "recipient@example.test"
:local recipientscc ""
:local routername "$[/system identity get name]"

:local eb ""
:foreach interf,speeds in=$ifspeeds do={
  :local status
  :local speed
  :onerror e in={
    :set status [/interface/ethernet/monitor $interf proplist=status,rate,full-duplex once as-value]
    :set speed ($status->"status")
  } do={ :set speed "interface-error" }
  :if ($speed = "link-ok") do={
    :if ($status->"full-duplex") do={
      :set speed (($status->"rate")."-full")
    } else={
      :set speed (($status->"rate")."-half")
    }
  }
  :if ($speed != $speeds && !($speed in $speeds)) do={
    :set eb ($eb."Interface ".$interf." has incorrect speed: ".$speed."\r\n")
    /log/error "Incorrect interface speed $speed for $interf"
  }
}
:if ($eb != "") do={
  /tool e-mail send to="$recipient" cc="$recipientscc" subject="Incorrect interface speed(s) on $routername" body="$eb"
} else={
  /log/info "All checked interface speeds are OK"
}

The script needs read and test permissions (policy), email enabled in device mode, and e-mail sending configured.
Likely this script needs RouterOS 7.24.2 or newer.

As seen in the example ifspeeds is an array with interface names as keys and link-speeds as values. Each value can either be a string (if only a single speed is allowed) or an array of strings (if multiple speeds are allowed).

To install the script in /system/script (with name check-interface-speeds) and schedule it to run twice a day (e.g. at 07:05 - 07:15 and at 19:05 - 19:15) commands like these can be used:

/system/script/add name=check-interface-speeds policy=read,test
/system/script/edit check-interface-speeds source
/system/scheduler/add interval=12h name=check-interface-speeds on-event=":delay [:rndnum from=0 to=599]\n/system script run check-interface-speeds" policy=read,test start-date=2026-01-01 start-time=07:05:00

Comments, suggestions and questions are welcome!

Something to check: I think a script gets terminated if it exceeds 120 seconds...

I do not think this is the case (at least not on current RouterOS versions).
I have tested this script and the scheduler part has waited for more than 5 minutes on RouterOS 7.24.2.
Can you reproduce this behavior?

.....

@rextended Please red my previous message in full! I have tested and not observed the behavior you mentioned. If you can reproduce it, please share a reproduction scenario!

Is it annoying to take just a part of the sentence? That’s what you did in your reply.

@rextended Edited my answer to include your full message.
Can you share a reproduction scenario or not (i.e. can you please check, because I was not able to reproduce the thing you were concerned about)?

Quoting myself here: just because I’m checking and thinking about it doesn’t mean that’s exactly how things are.
There used to be a limit in older versions of RouterOS,
if they’ve removed it.. well, maybe that’s for the best, or maybe not...
but we’d need to verify when that change was made.

Nice script! This is a useful way to catch unexpected link-speed drops before they cause network performance issues. Adding it to the scheduler with email alerts makes monitoring much easier. Thanks for sharing!

BTW this interface will always be "Incorrect interface speed(s) on...

@aldek
Can you explain?

Yes, my mistake.
I missed the terminal and tested it on version 23.8.
Without "in", the script works well on 23.8 too.