RouterOS and MTU - a collection of useful scripts

MTU on MikroTik's RouterOS is something you usually don't deal with - that is until you have to deal with it because things stopped working. Alternatively, you decide to implement MPLS in your network, and then usually MTU becomes one of the things you deal with daily.

In this post, I want to share a few useful MikroTik scripts for dealing with MTU.

1. Auditing L2 MTU

Let's start by looking into how you can find out what's the max L2 MTU your network can currently safely transit. Please note the script below will check only physical interfaces, if you already have some virtual interfaces (like VPLS or any PPP-type interfaces) you would like to check, you will need to adjust the script.

I will assume you already calculated the maximum size of L2 frames you need on your network. In this case, checking if they can safely transit your RouterOS devices is fairly simple:

{
:local minimalMtu 1600

:local mtuCheck do={
  :if ([/interface get $1 l2mtu] < $2) do={
    :put ("Interface " . [/interface get $1 name] . " has MTU under " . $2)
  }
}

# ethernet
:foreach i in=[/interface ethernet find running] do={
  $mtuCheck $i $minimalMtu
}

# wireless
:foreach i in=[/interface wireless find disabled=no] do={
  $mtuCheck $i $minimalMtu
}
}

The script does some filtering - such as only checking running ethernet interfaces and non-disabled wireless interfaces. Adjust as required.

2. Setting max L2 MTU on all ports

This would be an equivalent of enabling jumbo frames on other vendor's gear. If you are asking "how do I enable jumbo frames on MikroTik / RouterOS", this is the answer. We simply allow as large L2 frames on all physical interfaces as our hardware allows.

# ethernet - set maximum supported L2MTU by hardware
/interface ethernet
:foreach i in=[find] do={
  set $i l2mtu=[/interface get $i max-l2mtu]
}

# wireless - max supported L2MTU is 2290
/interface wireless
:foreach i in=[find] do={
  set $i l2mtu=2290
}

Please note this will flap each port affected by an MTU change. This may result in traffic getting dropped for a few seconds, OSPF sessions droping their state, etc.

This should be safe to run on your devices (other than the above mentioned link flap), as it simply sets maximum allowed L2 frame size, without doing anything to L3 packet MTUs.

3. Auditing L3 MTU

Now let's jump into setting L3 MTU. The issue with L3 MTU is usually oposite to L2 MTU. In most cases, you want to keep L3 MTU at 1500 (however much we wish we could transit larger packets over the internet...).

{
:local targetMtu 1500

:foreach i in=[/ip address find] do={
  :local iface [/ip address get $i interface]

  :if ([/interface get $iface actual-mtu] != $targetMtu) do={
    :put ("L3 MTU on interface " . [/interface get $iface name] . " is not " . $targetMtu)
  }
}
}

PPP-like interfaces might be an exception from the 1500 L3 MTU rule for you. If so, adjust the script as required.

We use the actual-mtu property of interfaces for checking. This is useful because some protocols (PPP-like and VPN interfaces) support MTU negotiation, so even if you configure mtu at 1500, the other side might not support this, and actual-mtu might be lower.

4. Setting L3 MTU

Here we will set all interfaces with non-1500 L3 MTU to 1500. I included filtering of EoIP and PPP-like interfaces here as an example.

{
:local targetMtu 1500
:local filterTypes "eoip|ppp-out|l2tp-out"

:foreach i in=[/ip address find] do={
  :local iface [/ip address get $i interface]

  :if ([/interface get $iface type] ~ $filterTypes) do={
    :put ("Ignoring interface " . [/interface get $iface name] . " due to filter")
  } else={
    :if ([/interface get $iface mtu] != $targetMtu) do={
      :put ("Updating MTU to " . $targetMtu . " on " . [/interface get $iface name])
      /interface set $iface mtu=$targetMtu
    }
  }
}
}

You can notice we filtered based on interface type. You can see types of interfaces like this:

/interface
:foreach i in=[find] do={
  :put ("Type of interace " . [get $i name] . " is " . [get $i type])
}

5. Checking and setting MPLS MTU

Finally let's see how to check, and set, the MPLS MTU. Here we have 2 simple scripts. One to check MPLS MTU:

{
:local targetMtu 1550

:if ([/mpls interface get [/mpls interface find default=yes] mpls-mtu] = $targetMtu) do={
  :put "MPLS default interface MTU is CORRECT"
} else={
  :put "MPLS default interface MTU is WRONG"
}
}

We structure the commands in an if-else block on purpose, so Unimus' Config Push output grouping will nicely group all devices with correct (and incorrect) MTU into 2 groups.

And finally here is a small script to set MPLS MTU:

{
:local targetMtu 1580

/mpls interface
set [ find default=yes ] mpls-mtu=$targetMtu
}

Outro

I hope these scripts can make dealing with MTU a little easier for you. If you want to discuss the scripts (or anything related to this topic), please check the forum topic corresponding to this blog post on our forums.