BGP routing decision ignores IGP metric

Hi,

I am experiencing a pretty frustrating behavior where the BGP Best Path Selection algorithm appears to completely ignore the IGP (OSPF) metric to the BGP next-hop when breaking a tie for iBGP routes.

Topology

  • CHR running ROS 7.23.1

  • Two iBGP sessions (BorderGate1-1 and BorderGate2-1) established to two separate upstream routers over WireGuard tunnels.

  • Internal routing to the BGP next-hops is handled dynamically by OSPF (as IGP)

The Problem

Both BGP peers are sending the default route (0.0.0.0/0). The BGP attributes (local-pref=100, med=0, and as-path="64515") are completely identical on both candidates.

According to the documentation, Step 9 in the route decision algorithm should pick the path with the lowest IGP metric to the BGP next-hop (everything equal). To my understanding, Steps 1-8 should be identical between my two routes.

My OSPF routing table shows a clear, definitive difference in metrics to reach the next hops (ospf.metric 10 vs 75):

[admin@SunGate2] > /routing/route/print detail where dst-address=172.20.215.129/32 or dst-address=172.20.215.130/32
Flags: X - DISABLED, F - FILTERED, U - UNREACHABLE, A - ACTIVE; c - CONNECT, o - OSPF, b - BGP
 
 Ao   afi=ip contribution=active dst-address=172.20.215.129/32 routing-table=main gateway=192.0.2.184%wg-bg1-ftth 
       immediate-gw=192.0.2.184%wg-bg1-ftth distance=110 scope=20 target-scope=10 belongs-to="ospf-instance-1" 
       ospf.metric=75 .type=intra 

 Ao   afi=ip contribution=active dst-address=172.20.215.130/32 routing-table=main gateway=192.0.2.176%wg-bg2-ftth 
       immediate-gw=192.0.2.176%wg-bg2-ftth distance=110 scope=20 target-scope=10 belongs-to="ospf-instance-1" 
       ospf.metric=10 .type=intra 

Despite 172.20.215.130 having a significantly lower OSPF metric (10), RouterOS installs the route via 172.20.215.129 (OSPF metric 75) as the active route:

[admin@SunGate2] > /routing/route/print detail where dst-address=0.0.0.0/0 and routing-table=default_uplinks              
Flags: X - DISABLED, F - FILTERED, U - UNREACHABLE, A - ACTIVE; c - CONNECT, b - BGP

  b   afi=ip contribution=candidate dst-address=0.0.0.0/0 routing-table=default_uplinks gateway=172.20.215.130 immediate-gw=192.0.2.176%wg-bg2-ftth 
       distance=200 scope=40 target-scope=30 belongs-to="bgp-IP-172.20.215.130" 
       bgp.session=BorderGate2-1 .as-path="64515" .local-pref=100 .med=0 .origin=igp 

 Ab   afi=ip contribution=active dst-address=0.0.0.0/0 routing-table=default_uplinks gateway=172.20.215.129 immediate-gw=192.0.2.184%wg-bg1-ftth 
       distance=200 scope=40 target-scope=30 belongs-to="bgp-IP-172.20.215.129" 
       bgp.session=BorderGate1-1 .as-path="64515" .local-pref=100 .med=0 .origin=igp 

Is this a bug?

If not, how is this supposed to work?

In the case it just uses administrative distance as a discriminator, this is the wrong property because ospf.metric is what defines the cost to the respective default gateway.

I know I can overwrite these manually with route filters and such but it's important that the preference of this default route is really set by the cost of the underlying IGP (OSPF).

Thanks in advance!

There is a parameter bgp.igp-metric which is not set in your case. That parameter can be set with routing filters.

Oh I see, so this is not done automatically but I need to set this myself via route filters?

Do you mean something like this?

/routing/filter/rule
add chain=bgp-in-ospf-metric rule="if (dst == 0.0.0.0/0) { set bgp.igp-metric [:to-num [/[/routing/route/get [find dst-address="$gateway/32"] ospf.metric]]]; accept; } else { accept; }"

(EDIT: above doesn’t work anyway, seems it has to be a static value??)

Then my concern is that this evaluates only at the beginning when the route is imported via BGP, but not when there are changes in the underlying IGP (OSPF costs change).

For example, once 172.20.215.129 gets a lower OSPF metric than 172.20.215.130, the BGP route should change.

Is there a way to accomplish this this?