Sorry if it has been answered, I couldn’t find it in a google query…
What happened with the
/ip route check <address>
command?
I was using it in a few scripts and they are broken on upgrade to 7.1beta1…
Sorry if it has been answered, I couldn’t find it in a google query…
What happened with the
/ip route check <address>
command?
I was using it in a few scripts and they are broken on upgrade to 7.1beta1…
Check is not implemented in ROS v7.
What does check give you that “/routing route print” does not?
Well, I use it in scripts to get the nexthop of the route to a given address or, using something global like 1.1.1.1, of “the internet”. Something like:
:local gateway ([/ip route check [:resolve my.vpn.server] once as-value]->"nexthop")
I’m not aware of a good alternative, that works when there are host rules in addition to default rules, etc
It would be nice to have something like linux’s
ip route get <host>
in scripting… is there a reasonable alternative?
You can get route that resolves specified destination:
/ip route print detail where x.x.x.x in dst-address and active
DAd dst-address=0.0.0.0/0 routing-table=main pref-src="" gateway=10.155.101.1 immediate-gw=10.155.101.1%bridge
type=unicast distance=1 scope=30 target-scope=10
From there you can read immediate-gw which shows out interface and gateway IP.
Cool! I was not aware of the use of “ipv4-address in ipv5-address” for the routing table. So this will be enough for what i’m doing:
:put (([/ip route print detail as-value where 1.1.1.1 in dst-address and active]->0)->"gateway")
192.168.88.1
# or
:put (([/ip route print detail as-value where 1.1.1.1 in dst-address and active]->0)->"immediate-gw")
192.168.88.1%wan-bridge
Thanks! I’m editing the scripts to “migrate” to 7
It was working for the particular case when I asked but it does not work for all cases. A simple non-functional example follows.
Take a machine connected to a ONT on ether1. The router has 192.168.1.33/24 and the ONT 192.168.1.1/24, both in ether1. Both addresses are in the untagged VLAN, and then some VLANs. On one of them, named “inet”, there is a pppoe tunnel through the ONT into the provider network. The pppoe-client interface is called “movi”. I also usually set unreachable routes for rfc1918 addresses, and the router uses the standard 192.168.88.0/24 addressing scheme in the “bridge”. It has a ikev2 VPN set up.
The configuration is working perfectly, all is reachable (192.168.1.1 works, public internet works, unreachable blocks illegal addresses from going through the pppoe tunnel,…)
What happens when I try to query for the gateway corresponding to the ONT the way you told me?
[admin@Mikrotik] > /routing/route/print detail where 192.168.1.1 in dst-address and active
Flags: X - disabled, I - inactive, F - filtered, U - unreachable, A - active;
c - connect, s - static, r - rip, b - bgp, o - ospf, d - dhcp, v - vpn, m - modem, a - ldp-address, l - ldp-mapping; + - ecmp
Av afi=ip4 contribution=active dst-address=0.0.0.0/0 routing-table=main pref-src="" gateway=movi immediate-gw=movi distance=1
scope=30 target-scope=10 belongs-to="VPN route"
debug.fwp-ptr=0x20242514
As afi=ip4 contribution=active dst-address=192.168.0.0/16 routing-table=main pref-src="" gateway=unreachable immediate-gw=""
distance=5 scope=250 target-scope=10 belongs-to="Static route"
debug.fwp-ptr=0x20242000
Ac afi=ip4 contribution=active dst-address=192.168.1.0/24 routing-table=main gateway=ether1 immediate-gw=ether1 distance=0
scope=10 belongs-to="Connected route" local-address=192.168.1.33%ether1
debug.fwp-ptr=0x20242578
Three different routes are given. For strange reasons, the default route given first belongs-to=“VPN route”, maybe because there is a IKEv2 VPN set up in the router.
The second one is the “unreachable” route. Only the third one is the real route that will be used.
/routing/route/print does not work as a replacement for /ip route check. It seems to print the relevant routes in the opposite sorting order
I still need a replacement for scripting of the old classic
:put ([/ip route check x.x.x.x as-value once ]->"interface")
to identify the parameters of the first hop that will be used. As I told, the analogue of linux “ip route get x.x.x.x”
Are there any plans to implement this feature?
default route is installed by this interface, that is the reason for having VPN flag.
And regarding other routes it is obvious, that 192.168.1.0/24 will be used. More specific route is always preferred.
It can’t be used in scripts now. If there are ≥ 2 routes, then just count the masks in your head?
+1 on re-implementing /ip/route/check
In addition to losing its functionality for scripting, its absence is a big loss for human troubleshooting. Even though it’s possible to inspect the routing table in close detail to determine the next hop yourself, I submit that this is missing the point. Arguably, one of the main goals of “show”-type commands is to allow the operator to compare their mental model for what they intended to configure against the decision that the router has made as-configured.
Every major networking operating system I’ve worked with (Cisco, Juniper, Arista) has this as part of their routing “show” commands. Linux even has this capability via the iproute2 utilities. See examples below.
Is this actually a difficult ask in terms of implementation? Especially considering v7.1 is running Linux 5.6.3 and presumably there is less Mikrotik-custom packet handling internally, shouldn’t getting accurate information about forwarding decisions be easier than its ever been? Maybe not.
Cisco/Arista:
======
show ip route [address [mask] [longer-prefixes]] | [protocol [process-id]]
Juniper:
========
show route
<all>
<destination-prefix>
<logical-system (all | logical-system-name)>
[omitted extra options]
Linux:
======
testhost> ip route show to match 1.1.1.1
default via 2.2.2.2 dev ens5 proto dhcp src 2.2.2.24 metric 100
testhost> ip route get 1.1.1.1
1.1.1.1 via 2.2.2.2 dev ens5 src 2.2.2.24 uid 1000
cache
What you have shown in your examples is exactly what routing/route/print does.
How do I check longer prefixes or resolve a shorter route? It would be nice to resolve 172.23.253.1 to a route in the table.
[olof@80003p-cpe002] /ip/route> print where dst-address=172.23.253.0/24
Flags: A - ACTIVE; s, y - COPY
Columns: DST-ADDRESS, GATEWAY, DISTANCE
# DST-ADDRESS GATEWAY DISTANCE
1 As 172.23.253.0/24 172.24.1.113 1
[olof@80003p-cpe002] /ip/route> print where dst-address=172.23.253.1
As mentioned earlier in this topic “print where x.x.x.x in dst-address” returns all the routes that particular address can be resolved.
/ip/route/check gives you one answer. While “as-value” of the above “where in dst-adress” returns an array.
While script can replicate this, it’s not as clear or reliable, like quick $ipcheck function I wrote:
:global ipcheck
:set $ipcheck do={
:local ip2check [:toip $1]
:local typeip [:typeof $ip2check]
:if (typeip~"ip|ip6") do={
:local lookup [/ip/route/find where $ip2check in dst-address and active]
:local lastone ($lookup->([:len $lookup]-1))
:local rv [/ip/route/get $lastone immediate-gw]
:return $rv
} else={
:error "\$ipcheck requires an IP address/range as input"
}
}
# TEST
:put [$ipcheck 1.1.1.1]
e.g. I’m assuming it’s the most specific route is last one returned – if not, be more even complex to replicate /ip/route/check.
Or, as a feature request, perhaps allow monkey-patching missing commands like this with script functions like:
:set [/ip/route/check] do={...}
I know what “check” command does. If it is used in scripts anyway then replacing it with routing print can be done (as you demonstrated yourself). More specific route from the array can also be retreived easily by comparing netmask values.
And provided examples from Juniper, Cisco, etc, does not return single entry either. Probably in the future we will add “check” command, but right now you will either need to use ROS v6 or do a bit of scripting.
I wasn’t saying you didn’t – Just saying it does do :nothing in v7, and did do something in v6. And, the OP wanted the routing decision from ROS POV, not all the possible ones.
Also pointing out it this isn’t a big deal since if your already using scripts, using a function can solve this pretty easily.
IMO, the improved routing in V7 is likely worth the little annoyance of stuff like thing going missing. I don’t think cisco “ip show” is a good example. In fact, I’d suggest trying to using functions in Cisco’s CLI, or the fact the cisco “show” cmd is a s#!tshow of inconsistency when it comes to filtering depending on where it’s used. In ROS it’s always the same filter syntax, columns, etc.
I would also like to add my voice for adding back ip route check. Its disappearance is really an unfortunate regression.
I’m sure he meant “ip route get” under Linux:
ip route get
get a single route
this command gets a single route to a destination and
prints its contents exactly as the kernel sees it.
fibmatch
Return full fib lookup matched route. Default is to
return the resolved dst entry
to ADDRESS (default)
the destination address.
from ADDRESS
the source address.
tos TOS
dsfield TOS
the Type Of Service.
iif NAME
the device from which this packet is expected to
arrive.
oif NAME
force the output device on which this packet will
be routed.
mark MARK
the firewall mark (fwmark)
vrf NAME
force the vrf device on which this packet will be
routed.
ipproto PROTOCOL
ip protocol as seen by the route lookup
sport NUMBER
source port as seen by the route lookup
dport NUMBER
destination port as seen by the route lookup
connected
if no source address (option from) was given,
relookup the route with the source set to the
preferred address received from the first lookup.
If policy routing is used, it may be a different
route.
Note that this operation is not equivalent to ip route
show. show shows existing routes. get resolves them and
creates new clones if necessary. Essentially, get is
equivalent to sending a packet along this path. If the
iif argument is not given, the kernel creates a route to
output packets towards the requested destination. This is
equivalent to pinging the destination with a subsequent ip
route ls cache, however, no packets are actually sent.
With the iif argument, the kernel pretends that a packet
arrived from this interface and searches for a path to
forward the packet.
I would say that the most obvious reason for bringing back /ip route check is that performing searches on a large routing table is borderline unusable.
I have a CCR1072 running ROS7.6 that has 3 full table peers (we have other routers that are also part of peering LANs, so have larger route tables). Performing searches on this takes so long as to be of very little help in a diagnostic scenario:
I’ve run the below commands and timed how long it took to get a result:
/ip route print detail where dst-address=8.8.8.0/24 # 1:25
/ip route print detail where dst-address=8.8.8.0/24 and active # 1:15
/ip route print detail where 8.8.8.8 in dst-address # 1:33
/ip route print detail where 8.8.8.8 in dst-address and active # 1:31
/routing route print detail where dst-address=8.8.8.0/24 # 1:42
/routing route print detail where dst-address=8.8.8.0/24 and active # 1:11
/routing route print detail where 8.8.8.8 in dst-address # 1:21
/routing route print detail where 8.8.8.8 in dst-address and active # 1:46
I should point out that I have had instances where results have been returned much faster than above (probably around 15 seconds, which still isn’t great), but these instances are completely erratic and I’ve had just just as many instances where the command never completes at all (I’ve literally gone away to do something else and returned 15mins later) forcing me to cancel the search.
ouch baby, very ouch
How can I catch event of changing immediate-gw for a route on failover and send notification via tg?