There have been a number of improved netwatch scripts listed on the mikrotik wiki in the past however many of these are hard to understand, broken or both.

I had a request from an associate to assist them finding a solution to fall over VPN traffic from one link to another in the event of an outage; in a network configuration where it wasn’t possible to use the local upstream router as an indication of the VPNs status, so I took the opportunity to revise a netwatch script based loosely on the one located here: http://wiki.mikrotik.com/wiki/Improved_Netwatch_II

My rewrite of this allows both the “up” and “down” scripts to be called from the same place (preferably a scheduler entry) and to be extra nice I’ve commented the whole script so you’re all welcome to modify as you see fit.

Pre-requisites:
– Script has been tested on v4.13
– Requires 2 routes to a set address/address range, one with a distance of 1 (preferred route) the other with a distance of 2

Note: If the address you’re trying to test to lies within the range you’re wanting to route to (eg: 192.168.1.1 and 192.168.1.0/24 as the test address and route respectively) you’ll want to add a static route for the test address (eg: 192.168.1.1 via 192.168.2.1) to ensure you always try the primary path to get to it (otherwise the testing would flap back and forth between the 2 links!)

Example configuration:

The netwatch route in this case would be:


/ip route add dst-address=192.168.2.0/24 gateway=192.168.4.2 distance=1 comment="Netwatch-Route"

The script:


#define variables

:local i 0



#Check for specific route with distance of 1

:if ([/ip route find comment="Netwatch-Route" distance=1]!="") do={



#add +1 to $i while checking that $i is lower than 5 and there is no ping response (ping command returns 0)

#if either of the 2 clauses are not met, the command will terminate - that is if a ping response is received (breaking one of the clauses), it'll terminate before 5 loops

	:do {:set i ($i + 1)} while  ($i < 5 &&  ([/ping 192.168.2.1 interval=3 count=1]=0))



#when this point is reached check if $i=5 and if so do the following

	:if ($i=5) do={

#add a log entry

		:log info "Netwatch-Route has gone down"

#set the route distance to 5 (putting it at a lower priority than the alternative)

		/ip route set [find comment="Netwatch-Route"] distance=3

	}

#route not found, so...

} else={

#Check for specific route with distance of 3

	:if ([/ip route find comment="Netwatch-Route" distance=3]!="") do={

#add +1 to $i while checking that $i is lower than 10 and there is a ping response (ping command returns 0)

#if either of the 2 clauses are not met, the command will terminate - that is if a ping response is received (breaking one of the clauses), it'll terminate before 10 loops

		:do {:set i ($i + 1)} while  ($i < 10 &&  ([/ping 192.168.2.1 interval=3 count=1]=1))



#when this point is reached, check if $i=10 and if so do the following

		:if ($i=10) do={

#add a log entry

			:log info "Netwatch-Route is back up"

#set the route distance to 1 (putting it back to the higher priority)

			/ip route set [find comment="Netwatch-Route"] distance=1

		}

#no matching route found

	} else={

#log failure of script

		:log info "Route Required does not exist"

#log failure to terminal (helpful for testing purposes)

		:error "Route Required does not exist"

	}

}

For Mikrotik 2, the check address would be 192.168.1.1 and route would be


/ip route add dst-address=192.168.1.0/24 gateway=192.168.4.1 distance=1 comment="Netwatch-Route"

Uncommented/untabbed version of the script for those copy-paste fanatics:


:local i 0

:if ([/ip route find comment="Netwatch-Route" distance=1]!="") do={

:do {:set i ($i + 1)} while  ($i < 5 &&  ([/ping 192.168.1.1 interval=3 count=1]=0))

:if ($i=5) do={

:log info "Netwatch-Route has gone down"

/ip route set [find comment="Netwatch-Route"] distance=3

}

} else={

:if ([/ip route find comment="Netwatch-Route" distance=3]!="") do={

:do {:set i ($i + 1)} while  ($i < 10 &&  ([/ping 192.168.1.1 interval=3 count=1]=1))

:if ($i=10) do={

:log info "Netwatch-Route is back up"

/ip route set [find comment="Netwatch-Route"] distance=1

}

} else={

:log info "Route Required does not exist"

:error "Route Required does not exist"

}

}

Advertisement