OSPFv3 route redistribution

  • We have two entry points into the network that receive default routes via bgp.
  • I want to redistribute default routes to the rest of the network via ospfv3 and different weights.
  • We have two versions of Vyos installed to gateway routers - 1.3.5 and Stream 2025.11.
  • In version 1.3.5 I use set ospfv3 redistribute bgp … configuration command and assign metric of 50 to the route and it works fine.
  • In the version 2025.11 ospfv3 behaves differently and it seems has two options available default-information originate ... and redistribute bgp ….
  • I tried both but neither of them does what I need.
    • default-information originate … is configured with route-map that allows only bgp routes and this works except that when bgp is down - it still publishes the default route (always option is not set).
    • redistribute bgp … does not do anything at all
  • I could not find an easy way to troubleshoot since vyos tools are rather basic and half of them don’t work at all (try executing monitor protocol ospfv3 enable route… for yourself…).

Here are some configuration snippets:

# show policy
 prefix-list6 DEFAULT-ROUTE-IPV6 {
     rule 10 {
         action permit
         prefix ::/0
     }
 }
 route-map OSPFv3-ORIGINATE {
     rule 10 {
         action permit
         match {
             ipv6 {
                 address {
                     prefix-list DEFAULT-ROUTE-IPV6
                 }
             }
             protocol bgp
         }
     }
 }
 route-map OSPFv3-REDISTRIBUTE {
     rule 10 {
         action permit
         match {
             ipv6 {
                 address {
                     prefix-list DEFAULT-ROUTE-IPV6
                 }
             }
             protocol bgp
         }
     }
 }

version with originate:

 # show protocols ospfv3 
 default-information {
     originate {
         metric 10
         metric-type 1
         route-map OSPFv3-ORIGINATE
     }
 }
 interface eth1 {
     area 0
     passive
 }
 interface lo {
     area 0
     passive
 }
 interface tun51 {
     area 0
     cost 10
 }
 interface tun523 {
     area 0
     cost 10
 }
 interface tun524 {
     area 0
     cost 50
 }

version with redistribute:

# show protocols ospfv3 
 interface eth1 {
     area 0
     passive
 }
 interface lo {
     area 0
     passive
 }
 interface tun51 {
     area 0
     cost 10
 }
 interface tun523 {
     area 0
     cost 10
 }
 interface tun524 {
     area 0
     cost 50
 }
 redistribute {
     bgp {
         metric 10
         metric-type 1
         route-map OSPFv3-REDISTRIBUTE
     }
 }

here is portion of a routing table for good measure:

Codes: K - kernel route, C - connected, L - local, S - static,
       R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric, t - Table-Direct,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

O   ::/0 [110/60] via fe80::f50f:75ff:fef4:dcda, tun51, weight 1, 00:05:25
B>* ::/0 [20/0] via fe80::5287:89ff:fe1b:4435, br0, weight 1, 00:50:55
S   ::/0 [250/0] via xxxx:xxxx:3:3::1, br0, weight 1, 02:54:11
...

and just in case - ospfv3 area info:

# run show ipv6 ospfv3 area | strip-private 
+-xxx.xxx.128.17 [0]
   +-xxx.xxx.128.1 [10]
   +-xxx.xxx.128.133 [10]
      +-xxx.xxx.128.129 Net-ID: xxx.xxx.0.2 [11]
         +-xxx.xxx.128.129 [11]
         +-xxx.xxx.128.134 [11]

Any guidance?

Update

I’ve just discovered that even though I provided route-map with default information originate … option and it clearly specifies bgp as protocol - it actually picks up a static route instead. I discovered it by disabling the static route and the route disappeared from the list of OSPFv3 routes instantly. It appears that default-information originate … ignores the route map.

The default route not being redistrubuted when doing redistribute bgp is expected behavior for current FRR versions. It may have changed from older versions that would be present on 1.3. The expected solution is to use default-information originate

The route-map applied to default-information originate is for conditionally routing the default, and you would more typically match a route separate from the default. For instance, if you wanted a default to be advertised for IPv4, but only when the upstream peering is receiving routes, you may match 1.1.1.1/32 in the route-map So if 1.1.1.1/32 is no longer present, then the default is withdrawn. This works correctly for IPv4, but it didn’t seem to work for IPv6. In fact, a lot of OSPFv3 seemed a little buggy in my recent testing. There may be upstream bugs in FRR (known or unknown).

The monitor protocol implementation seems to have incorrect logic for a lot of the commands. If you ever need to enable that debugging, you can always drop into vtysh by typing sudo vtysh in VyOS. Then enable the debugging there. I’ve created a bug report for the incorrect command parsing in monitor protocol: ⚓ T8070 "Monitor protocols" commands broken

2 Likes

Thanks for clarifying about the default-information originate it kind of makes sense in general terms as long as route-map handled properly.

when it comes to route flittering for default-information originate I do exactly as you mentioned with addition of protocol type, so does specifying protocol bgb expected to work?

If it only picks up an address then that would be a problem since as you can see I have multiple default routes from different protocols, but I only want to inject one that comes from BGP. I will try to do the similar configuration for ipv4/ospf tonight and will report back if it works any better.

…and here is some rant (feel free to ignore):

Broken IPv6 implementation is a big problem for us - I will need to consider a different IGP or replace Vyos with something else. I’ve been experimenting with Vyos for several years now and even though I like simplicity, I spend too much time dealing with bugs and workarounds. I’m still considering one of your subscriptions but it is hard to justify it in the current state.

In your example, you had this:

You’d typically not match the default route, but another route to track. So, from BGP, you could advertise something like 2001::102/128 in addition to the default, and then your route-map would match that. If that were withdrawn, the default would also be withdrawn. It’s the same conceptually as conditional routing in BGP. A default from BGP doesn’t necessarily guarantee upstream reachability, which is why you want to match some upstream prefixes as your routes to track over just a default.

As far as protocol bgp, it’s possible that option is only for filtering to/from zebra (or some other contexts). Of course all of the possible options in a route-map won’t work for every section…kind of the downside to using a general use object container for everything. People have run into that issue with Cisco forever. I haven’t tested if matching the source-protocol when applying a route-map to default-information originate is contextually valid. If it works for IPv4, then it is and appears to be broken for ospf6 in FRR (at least in the version of FRR in use). I did find this old issue for ospf, it’s possible the same fix was just never implemented for ospf6: default-information originate route-map problem · Issue #5665 · FRRouting/frr · GitHub

Unfortunately, in this regard, any issue you find within VyOS will likely be in any other open-source project. The issues would reside in FRR. And since pretty much every project will use FRR, fixes would need to occur upstream. Some commercial products even use FRR like Nvidia or Juniper(HPE) SSR.

The best thing would be to submit a bug report at https://vyos.dev/. Without that, this issue would just remain broken. It’s possible it’s a known bug in FRR and is fixed in a different version, which could help scope the VyOS’ maintainers decision in which version of FRR to use. Or the VyOS maintainers can work towards an upstream fix in FRR.

The forwarding plane of Linux is solid, so you may just need to find a good solution within the control-plane (FRR) that works for you.

Thank you for the reply. In my setup addresses are defined in the prefix list as you shown above biyt in the actual route map I add a protocol selector in addition to the addresses like so:

 route-map OSPFv3-ORIGINATE {
     rule 10 {
         action permit
         match {
             ipv6 {
                 address {
                     prefix-list DEFAULT-ROUTE-IPV6
                 }
             }
             protocol bgp
         }
     }
 }

…so I will try to experiment with ospf and ospv3 to see if this selector is respected and will report back.

We use Vyos in conjunction with Juniper SRXes and on Juniper side the initial setup is way more complicated for my liking but then most of the functionality works when properly set. In the last 10 years I had maybe half a does support tickets opened with JTAC and only discovered one or two bugs that had been fixed since. Vyos is rapidly improving but not at the same level just yet.

@L0crian Just checked OSPF and it seems it behaves the same - route-map in default-information originate picks up highest priority default route and ignores the explicit protocol selector (bgp in my case). Should this be considered a bug?

I can work around it by removing those low priority default routes. However, they are quite useful as they they supposed to help bootstrapping dynamic protocols after reboot. Without them, I would likely need to bootstrap manually after each reboot which is bad.

Being able to match on source-protocol in this context would likely be more a feature request, since it’s just not contextually applicable in this use case.

With that said, if used correctly, the conditional advertising 100% works for IPv4. I’ve mentioned it a few times, but you’re trying to match on the default route in your prefix-list, which isn’t how the conditional advertising works when using a route-map on default-information originate in OSPF. You need to match a more specific upstream prefix that OSPF has in its database. When that is withdrawn, then the default is withdrawn. Here’s a simple example:

rtr1 (ASBR):

set policy route-map default_conditionally_adv rule 10 action 'permit'
set policy route-map default_conditionally_adv rule 10 match tag '100'

set policy route-map bgp_to_ospf rule 10 action 'permit'
set policy route-map bgp_to_ospf rule 10 set tag '100'

set protocols ospf default-information originate route-map 'default_conditionally_adv'
set protocols ospf redistribute bgp route-map 'bgp_to_ospf'

set protocols static route 0.0.0.0/0 blackhole

vyos@rtr1# run show ip bgp
     Network          Next Hop            Metric LocPrf Weight Path
 *>  0.0.0.0/0        10.1.2.1                               0 1 i
 *>  1.1.1.1/32       10.1.2.1                 0             0 1 ?

vyos@rtr1# run show ip route
S>* 0.0.0.0/0 [1/0] unreachable (blackhole), weight 1, 00:06:52
B   0.0.0.0/0 [20/0] via 10.1.2.1, eth0, weight 1, 00:19:09
B>* 1.1.1.1/32 [20/0] via 10.1.2.1, eth0, weight 1, 00:05:15

rtr2:

vyos@rtr2# run show ip route ospf
O>* 0.0.0.0/0 [110/10] via 10.2.3.2, eth1, weight 1, 00:00:12
O>* 1.1.1.1/32 [110/20] via 10.2.3.2, eth1, weight 1, 00:00:12
O   10.2.3.0/24 [110/1] is directly connected, eth1, weight 1, 00:20:48

vyos@rtr2# run show ip route tag 100
O>* 1.1.1.1/32 [110/20] via 10.2.3.2, eth1, weight 1, 00:04:05

If I lost my upstream BGP peering, then the 1.1.1.1/32 prefix is withdrawn, causing the default to be withdrawn from OSPF, even though the static default route still exists:

rtr1:

vyos@rtr1# run show ip bgp
No BGP prefixes displayed, 0 exist

vyos@rtr1# run show ip route
S>* 0.0.0.0/0 [1/0] unreachable (blackhole), weight 1, 00:09:11

rtr2:

vyos@rtr2# run show ip route ospf
O   10.2.3.0/24 [110/1] is directly connected, eth1, weight 1, 00:21:16

vyos@rtr2# run show ip route tag 100
...no output

This did not work when I tested yesterday for IPv6, so that may very well be a bug. I verified your findings that source-protocol doesn’t impact the route-map in this context, so that may be a feature request.

Thank you, this is very helpful. I did some digging of my own and what I found so far is that the default-information originate concept comes from Cisco (not the best approach if you ask me, I would prefer how Juniper does it but it is just my opinion). So, according to Cisco this method will create a default route in OSPF if any default route is present… and then they add route-map to apply additional conditions. Once this clicked, I started experimenting with conditions and as expected - filtering by protocol doesn’t work. My suspicion is that FRR may be looking for default route in FIB instead of RIB and at this point origin info gets lost. I have no way of validating how it would behave in Cisco vs FRR but if this is true than it is likely a bug in FRR.

I like your idea with using tags and I will try it tonight but I have suspicion that it may not work for me since I only have a single default route coming from BGP and redistribute logic will likely filter it out before applying the map. I will see if I can tag the route in BGP somehow or inject non-default blackhole route… not sure if it is going to work but worth a try.

I will report back the findings. And thanks again for all your help.

This likely isn’t a bug, it’s just that the section in the route-map isn’t contextually valid. It’s like a route-map setting a local-preference, that is only contextually valid for BGP policy, but I can apply a route-map setting local-pref for almost any section. This is why I said it’d be a feature request. The good news is a solution may just be as simple as porting over code where the source-protocol section is contextually valid, so it could be an easy addition.

If you only have a default route from BGP, you can still do this by making a route you want to track need to recurse via the BGP default. You can do something like this (eth0 is my BGP peering):

rtr1:

set protocols static route 5.5.5.5/32 next-hop 5.5.5.4 interface 'eth0'

vyos@rtr1# run show ip bgp
     Network          Next Hop            Metric LocPrf Weight Path
 *>  0.0.0.0/0        10.1.2.1                               0 1 i

vyos@rtr1# run show ip route 5.5.5.5/32 longer-prefixes 
S>  5.5.5.5/32 [1/0] via 5.5.5.4, eth0 (recursive), weight 1, 00:02:28
  *                    via 10.1.2.1, eth0, weight 1, 00:02:28

rtr2:

vyos@rtr2# run show ip route ospf
O>* 0.0.0.0/0 [110/10] via 10.2.3.2, eth1, weight 1, 00:01:08
O>* 1.1.1.1/32 [110/20] via 10.2.3.2, eth1, weight 1, 00:04:38
O>* 5.5.5.5/32 [110/20] via 10.2.3.2, eth1, weight 1, 00:01:08
O   10.2.3.0/24 [110/1] is directly connected, eth1, weight 1, 12:23:05

If the default is withdrawn, the 5.5.5.5/32 prefix becomes inactive since it can’t recurse, and if the route-map for default-information originate matches that prefix, the default in OSPF is withdrawn:

rtr1:

vyos@rtr1# run show bgp ipv4 0.0.0.0/0
% Network not in table

vyos@rtr1# run show ip route 5.5.5.5/32 longer-prefixes 
S   5.5.5.5/32 [1/0] via 5.5.5.4, eth0 inactive, weight 1, 00:00:35

rtr2:

vyos@rtr2# run show ip route ospf
O>* 1.1.1.1/32 [110/20] via 10.2.3.2, eth1, weight 1, 00:11:13
O   10.2.3.0/24 [110/1] is directly connected, eth1, weight 1, 12:29:40

I think I got it working based on your suggestions for both ospf and ospfv3… ended up injecting tags in bgp and then filtering by them in ospf/ospfv3 default-info originate … doing some testing and cleanup now and will post the solution shortly.

So, we can drop the topic whether filtering by protocol is a bug or not - filtering by tags is much cleaner. I haven’t used tags before so there was some learning curve involved but now it looks so obvious :slight_smile:

Here is a description of the final solution that we tested and implemented and it works for bot protocols OSPF and OSPFv3:

Environment

  • We have network with two entry points at different locations and from different providers.
  • We operate out own ASN and use BGP to advertise our address ranges.
  • We only receive default routes from our providers at each location.
  • We use active/backup setup for our uplinks with all traffic routed via primary PoP and we only switch to secondary if primary BGP session goes down.
  • We use OSPF and OSPFv3 as IGPs and we want to inject default route from each location if BGP default route is present and assign route metrics to prioritize the primary PoP.
  • Vyos is used for BGP/OSPF/OSPFv3 in each PoP.
  • Vyos instances configured with multiple default routes from different protocols:
Codes: K - kernel route, C - connected, L - local, S - static,
       R - RIP, O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric, t - Table-Direct,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

B>* xxx.xxx.0.0/0 [20/0] via xxx.xxx.216.113, br0, weight 1, 12:23:15
O   xxx.xxx.0.0/0 [110/150] via xxx.xxx.128.174, tun524, weight 1, 12:39:21
S   xxx.xxx.0.0/0 [250/0] via xxx.xxx.216.113, br0, weight 1, 16:19:17
...
  • OSPF/OSPFv3 implementations in FRR provide default-information originate option similar to one provided by Cisco.
  • The default-information originate statement will create default route in OSPF/OSPFv3 if ANY default route is present in the system.
  • In order to provide additional flexibility the default-information originate will also take a route-map as an option.

Problem

  • It appears that specifying protocol bgp in route-map has no effect and this statement cannot be used for route detection.
  • Vyos/FRR also provide redistribute option that may seem as alternative solution, however this option cannot redistribute the default route and this is by design.

Solution

After some experimentation and invaluable help from Vyos community we develop a working solution that satisfies all the requirements.
The general idea to use tags for labeling routes received from BGP and the detect route presence by checking for specific tags in the default-information originate route-map and here are step-by-step instructions:

  • Use an import route-map in BGP to label all received routes with a specific tag:
r5# show policy route-map BGP-IPv4-IMPORT
 rule 10 {
     action permit
     match {
         ip {
             address {
                 prefix-list DEFAULT-ROUTE-IPV4
             }
         }
     }
     set {
         tag 100
     }
 }

and

r5# show protocols bgp | strip-private 
 address-family {
     ipv4-unicast {
         network xxx.xxx.128.0/24 {
         }
     }
 }
 neighbor xxx.xxx.216.113 {
     address-family {
         ipv4-unicast {
             route-map {
                 import BGP-IPv4-IMPORT
             }
             soft-reconfiguration {
                 inbound
             }
         }
     }
     remote-as XXXXXX
     update-source xxx.xxx.216.114
 }
 ...

validation:

r5# run show ip route tag 100
Codes: K - kernel route, C - connected, L - local, S - static,
       R - RIP, O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric, t - Table-Direct,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

B>* 0.0.0.0/0 [20/0] via 104.167.216.113, br0, weight 1, 12:57:15
  • Create another route-map and use it with OSPFs default-information originate to detect presence of BGP default route:
r5# show policy route-map OSPF-ORIGINATE 
 rule 10 {
     action permit
     match {
         tag 100
     }
 }

and finally:

r5# show protocols ospf | strip-private 
 ...
 default-information {
     originate {
         metric 10
         metric-type 1
         route-map OSPF-ORIGINATE
     }
 }
 ...

Validation (from a different node running Juniper SRX):

r7> show route protocol ospf          

inet.0: 24 destinations, 24 routes (24 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

0.0.0.0/0          *[OSPF/150] 11:56:36, metric 30, tag 100
                    >  to xxx.xxx.128.183 via irb.100
...

(also note that tag 100 has been propagated to OSPF route from BGP)

Testing

The testing methodology would be as follows

  • shutdown BGP session and make sure that BGP route is gone
r5# set protocols bgp neighbor xxx.xxx.216.113 shutdown
r5# commit

make sure BGP route is gone:

5# run show ip route | strip-private 
Codes: K - kernel route, C - connected, L - local, S - static,
       R - RIP, O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric, t - Table-Direct,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

O>* 0.0.0.0/0 [110/150] via xxx.xxx.128.174, tun524, weight 1, 13:25:48
S   0.0.0.0/0 [250/0] via xxx.xxx.216.113, br0, weight 1, 17:05:44
...

now check OSPF routes from a different node:

r7> show route protocol ospf    

inet.0: 24 destinations, 24 routes (24 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

0.0.0.0/0          *[OSPF/150] 00:02:56, metric 110, tag 200
                    >  to xxx.xxx.128.184 via irb.100

…and observe that the default route has been replaced with a new one from the backup router with different weight and tag.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.