enhance "check-gateway" feature - use arbitrary check IP

I’m new to Mikrotik, and I was happy to see so many ways to load-balance and failover traffic when there are multiple upstream connections. However it seems like performing a real check beyond “is the upstream router powered up” involves delving into scripting, which is a real pain, especially if you’re trying to use more than two upstream connections.

Many DSL, cable, EoC, T1, etc. connections will have a separate LAN block, so simply pinging the upstream router’s IP that you use as a default gateway tells you nothing about whether you have connectivity. Being able to specify say, the first hop IP beyond your upstream router, or a server upstream would be much more “real world” friendly.

For example, how much easier would this be:

ip route add dst-address=0.0.0.0/0 gateway=10.111.0.1 check-gateway=ping check-address=10.110.0.99

No scripting, no netwatch, just enter the IP you wish to monitor to confirm connectivity via that IP.

+10

+100

It really would be nice if we could do that per route.

Dreaming, and applying to one of my real situations, that might look like:

/ip route
add check-gateway=ping check-address=A.B.C.1 comment=Wireless distance=10 dst-address=0.0.0.0/1 gateway=\
    H.I.J.225
add check-gateway=ping comment=DSL distance=20 dst-address=0.0.0.0/1 gateway=\
    H.I.K.237
add distance=1 dst-address=A.B.C.1/32 gateway=H.I.J.225
add comment="open vpn server" distance=1 dst-address=D.E.F.9/32 gateway=pppoe-out1
add comment="make sure open vpn server is unreachable when pppoe-out1 is dead" \
    distance=200 dst-address=D.E.F.9/32 type=unreachable
add check-gateway=ping check-address=A.B.C.1 comment=Wireless distance=10 dst-address=128.0.0.0/1 gateway=\
    H.I.J.225
add check-gateway=ping comment=DSL distance=20 dst-address=128.0.0.0/1 gateway=\
    H.I.K.237

Maybe behind the scenes, MikroTik would be creating netwatch entries to disable the routes automagically like the mangle rules which get created to set MSS for tunnel interfaces.

Until then we have to settle for netwatch.

So, I have all of the above plus :

/tool netwatch
add comment="If reachable via wireless prefer wireless for default routes.  If not, prefer DSL for default routes." \
    host=A.B.C.1 \
    down-script="/ip route set [/ip route find comment=\"DSL\"] distance=5" \
    up-script="/ip route set [/ip route find comment=\"DSL\"] distance=20"

Which means there are more places to forget dependencies and generally make more mistakes. Netwatch would still have lots of other uses.

Maybe I’m misunderstanding your request, but this type of check exists already using recursive routing. I’m monitoring my upstreams DNS servers as a connection check. If I can’t ping my upstream DNS, the routes are marked as offline/down and use the next available route.

Basically, create a route with the IP you want to use to check connectivity and set the gateway as your default gateway/next hop. Then, for your default route, specify the IP you are checking as the default route.

Here’s an example based off my config. 1.2.3.4 would be my “gateway” while 2.3.4.5 is the upstream device I am checking to verify connectivity. 3.4.5.6 would be a secondary route if your primary is down.

/ip route
add check-gateway=ping comment=“Primary Default Route - Midco” distance=1 gateway=2.3.4.5
add check-gateway=ping comment=“Backup Default Route - Midco” distance=2 gateway=3.4.5.6
add comment=“Validate Route” distance=1 dst-address=2.3.4.5/32 gateway=1.2.3.4 scope=10

If you are unable to reach 2.3.4.5 via 1.2.3.4, the route is disabled and it uses 3.4.5.6 for connectivity.

wow, this my page is 3,2 years old :slight_smile: http://wiki.mikrotik.com/wiki/Advanced_Routing_Failover_without_Scripting

The bug is when you have a problem after your gateway, ie, your gateway answer normally, but link is down 2/3/etc routers after. Only through a script to check if a option like “check-address=10.110.0.99” is not created!

Bwhaha, 5 years xD

Have you read that article?

+10 for feature request!

Hello,
On my point of view this feature enhancement would simplify configuration of route checking removing many configuration lines and making configuration easier to do and read.
Very similar to what already happens with “ARP IP targets” on ARP bond checking.

Thanks
David

+1 for this feature request. would be quite useful.

I wrote some code a few years ago that I have been running to do per-route checking along with distance adjustments (weighting for different lines).

You can use any RouterOS command for the route check by creating a comment on the route that starts with “ROUTE_CHECK:”. This allows you to use specific routing tables and have compound statements. On my systems, I ping two addresses and sum their status (which gives either a 0, 1, or 2) and anything other than 0 will be success. If it returns 0, it will either be disabled or have the distance adjusted depending on the variables minDistance/maxDistance being there. All of this can be tied together to give “priorities” for lines that are up, such that there can always be a last resort available.

This is all run via the scheduler every 5s.

add check-gateway=ping comment="ROUTE_CHECK: :global minDistance 5; :global maxDistance 55; return ([/ping PUBLICIP1 count=1 interface=OutsideComcast routing-table=Comcast]+[/ping PUBLICIP2 count=1 interface=OutsideComcast routing-table=Comcast])" distance=5 gateway=GATEWAYMASKED routing-mark=PhoneInternet
add check-gateway=ping comment="ROUTE_CHECK: :global minDistance 10; :global maxDistance 50; return ([/ping PUBLICIP1 count=1 interface=OutsideVerizon routing-table=Verizon]+[/ping PUBLICIP2 count=1 interface=OutsideVerizon routing-table=Verizon])" distance=10 gateway=GATEWAYMASKED routing-mark=PhoneInternet
add check-gateway=ping comment="ROUTE_CHECK: :global minDistance 5; :global maxDistance 50; return ([/ping PUBLICIP1 count=1 interface=OutsideVerizon routing-table=Verizon]+[/ping PUBLICIP2 count=1 interface=OutsideVerizon routing-table=Verizon])" distance=5 gateway=GATEWAYMASKED pref-src=SRCMASKED
add check-gateway=ping comment="ROUTE_CHECK: :global minDistance 10; :global maxDistance 55; return ([/ping PUBLICIP1 count=1 interface=OutsideComcast routing-table=Comcast]+[/ping PUBLICIP2 count=1 interface=OutsideComcast routing-table=Comcast])" distance=10 gateway=GATEWAYMASKED

If anyone wants to try it - add this scheduler/script. I’m pasting a more readable version below as well.

/system script add name=route_check owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive source=":foreach k in [/ip route find comment~\"ROUTE_CHECK\"] do={\
    \n:local actualroute [:tostr [/ip route get \$k]]\
    \n:local disabled [/ip route get \$k disabled]\
    \n:local comment [/ip route get \$k comment]\
    \n:local distance [/ip route get \$k distance]\
    \n:local cmd [:pick \$comment 13 [:len \$comment]]\
    \n:local parsedcmd [:parse \"\$cmd\"]\
    \n:global minDistance \"\"\
    \n:global maxDistance \"\"\
    \n:global stepDistance 5\
    \n:local status [\$parsedcmd]\
    \n:set minDistance [:tonum \$minDistance]\
    \n:set maxDistance [:tonum \$maxDistance]\
    \n#:put \"STATUS: \$status \$[:type \$status]\"\
    \n:if ([:type \$status] != \"num\") do={\
    \n\t:error \"\$comment returned non-number type (need return on expression\?)\"\
    \n}\
    \nif ([:type \$minDistance] != \"nil\" && [:type \$maxDistance] != \"nil\") do={\
    \n\tif (\$minDistance >= \$maxDistance) do={\
    \n\t\t:error \"minDistance >= maxDistance\"\
    \n\t}\
    \n\t:local newDistance \$distance\
    \n\tif (\$status = 0) do={\
    \n\t\t:set newDistance (\$distance + \$stepDistance)\
    \n\t}\
    \n\tif (\$status != 0) do={\
    \n\t\t:set newDistance (\$distance - \$stepDistance)\
    \n\t}\
    \n\tif (\$newDistance < \$minDistance) do={ :set newDistance \$minDistance; }\
    \n\tif (\$newDistance > \$maxDistance) do={ :set newDistance \$maxDistance; }\
    \n\tif (\$newDistance != \$distance) do={\
    \n\t\t/log warning \"distance (\$status): \$distance [\$minDistance, \$maxDistance] -> \$newDistance - \$actualroute\"\
    \n\t\t/ip route set \$k distance=\$newDistance\
    \n\t}\
    \n} else {\
    \n\t:if (\$status = 0 && !\$disabled) do {\
    \n   \t\t/ip route disable \$k\
    \n\t\t/log warning \"Command: \$cmd status=\$status\"\
    \n\t\t/log warning \"distance (\$status): \$distance DISABLE - \$actualroute\"\
    \n\t} else {\
    \n\t\t:if (\$status != 0 && \$disabled) do {\
    \n\t\t\t/ip route enable \$k\
    \n\t\t\t/log warning \"distance (\$status): \$distance ENABLE - \$actualroute\"\
    \n\t\t}\
    \n\t}\
    \n}\
    \n}"
    
/system scheduler add interval=5s name=route_check on-event=route_check policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive start-date=feb/09/2016 start-time=03:39:20



:foreach k in [/ip route find comment~"ROUTE_CHECK"] do={
:local actualroute [:tostr [/ip route get $k]]
:local disabled [/ip route get $k disabled]
:local comment [/ip route get $k comment]
:local distance [/ip route get $k distance]
:local cmd [:pick $comment 13 [:len $comment]]
:local parsedcmd [:parse "$cmd"]
:global minDistance ""
:global maxDistance ""
:global stepDistance 5
:local status [$parsedcmd]
:set minDistance [:tonum $minDistance]
:set maxDistance [:tonum $maxDistance]
#:put "STATUS: $status $[:type $status]"
:if ([:type $status] != "num") do={
	:error "$comment returned non-number type (need return on expression?)"
}
if ([:type $minDistance] != "nil" && [:type $maxDistance] != "nil") do={
	if ($minDistance >= $maxDistance) do={
		:error "minDistance >= maxDistance"
	}
	:local newDistance $distance
	if ($status = 0) do={
		:set newDistance ($distance + $stepDistance)
	}
	if ($status != 0) do={
		:set newDistance ($distance - $stepDistance)
	}
	if ($newDistance < $minDistance) do={ :set newDistance $minDistance; }
	if ($newDistance > $maxDistance) do={ :set newDistance $maxDistance; }
	if ($newDistance != $distance) do={
		/log warning "distance ($status): $distance [$minDistance, $maxDistance] -> $newDistance - $actualroute"
		/ip route set $k distance=$newDistance
	}
} else {
	:if ($status = 0 && !$disabled) do {
   		/ip route disable $k
		/log warning "Command: $cmd status=$status"
		/log warning "distance ($status): $distance DISABLE - $actualroute"
	} else {
		:if ($status != 0 && $disabled) do {
			/ip route enable $k
			/log warning "distance ($status): $distance ENABLE - $actualroute"
		}
	}
}
}

Does anyone know: is there any way to control the rate at which pings are issued when Check-gateway features is turned on in a route definition? By default, it now looks to be about 1 ping every 10 seconds. i would like to slow this rate down.
thanks in advance.

Currently there is no way to control this.

Strange. I could imagine that I would need it only faster, what is the reason to slow it down?

Out situation:

The Mikrotik device receives status data from local sensors connected to it via ethernet. This data needs to be reliably sent to a data center.
The Mikrotik router has two available connections to the data center

  1. a primary, ISP land based, hard wired connection, with no reasonable data transfer cost implications
  2. a backup cellular connection to be used in the event of a failure of the ISP connection. Cellular data is billed by data bytes transferred per month
    We use recursive routes to verify both are available, and report to the data center if either datapath fails. This is to expedite repair in the event of a failure.
    Considering the backup, cellular connection, the recursive routing sends a 70 byte ping and gets a response every 10 seconds.
    70 bytes/datagram * 2 (ping + response) * 6 (pings / minute) * 1440 (minutes / day) * 30 (days/month) = 36 megabytes/month

This merely provides status information to allow us to initiate repairs if a failure occurs

The ability to shorten the ping to a minimum size and slow down the ping frequency would reduce the cost of providing this status information. Thus my question/request…

Ok. Switch off the gateway ping and use netwatch instead.

nowadays in Russia many home and SMB provider’s gateways answer arp-ping with losses close to 50% so it is reasonible to add some smoothing and packet loss thresholds for check-gateway=arp

How anyone who looses pings inside his network could be isp?

In soviet russia, Internet surfs you. That’s how.