VyOSXXXIV · Route RedistributionOSPF redistribution
Redistributing OSPF into BGP — what survives the boundary, the MED, and feedback prevention
What you'll learn
- Configure `set protocols bgp address-family ipv4-unicast redistribute ospf` with a metric and a route-map on VyOS 1.5 LTS
- State which OSPF properties survive redistribution into BGP and which are lost at the boundary
- Explain E1 versus E2 and identify the node that actually sets it
- Break an OSPF-into-BGP-into-OSPF feedback loop with a community tag or an OSPF route tag
- Diagnose why an OSPF route is, or is not, advertised into BGP
Prerequisites
- Ethernet, MAC and ARP — the Layer 2 the routing engineer must read
- Redistributing OSPF into BGP — E1/E2 metric types, route-maps, and feedback
- Redistribution concept — why redistribute, route-map filtering, metric preservation, seed metric
- Route-map composition — match and set clauses, sequence ordering, implicit deny
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-19
Redistributing OSPF into BGP copies OSPF routes out of the RIB and into the BGP Loc-RIB, where they become locally originated paths that BGP can advertise to its peers.
The word “copies” is doing a lot of work in that sentence, and getting precise about what is copied — and what is not — is most of this lesson. The rest is the loop that mutual redistribution creates between OSPF and BGP, which is the single most common way this feature takes a network down.
What the redistribution actually reads
redistribute ospf does not read the OSPF link-state database. It
reads zebra’s RIB, and it takes the OSPF routes zebra selected.
Two consequences follow immediately, and both surprise people:
- Only best routes are redistributed. An OSPF route that lost to a static route or to eBGP for the same prefix is in the RIB but not selected, so it is not redistributed. The prefix silently does not appear in BGP, and nothing in the BGP configuration explains why.
- Everything OSPF-specific has already been discarded. By the time a route reaches the RIB it is a prefix, a next-hop, a distance and a metric. The area it came from, whether it was intra-area, inter-area or external, and whether an external was E1 or E2 are LSDB properties, and the LSDB is not what redistribution reads.
What crosses the boundary
| OSPF property | Survives into BGP? |
|---|---|
| The prefix | Yes — this is the point |
| The next-hop | Recomputed. The route is locally originated, so the next-hop advertised to a peer is set by normal BGP next-hop rules, not by OSPF |
| The OSPF metric | Only as a number, and only as the MED — unless you set the seed metric explicitly, in which case yours replaces it |
| Metric-type E1 / E2 | No. There is no BGP attribute that can carry it |
| The area | No |
| Intra-area / inter-area / external | No. Every redistributed route arrives in BGP identically |
| A 32-bit route tag | Yes — the tag travels in the RIB and can be matched with match tag in the redistribution route-map |
| Origin | Not carried, assigned: redistributed routes take origin incomplete, printed as ? |
The last row is worth internalising. ? in a BGP table is not a
diagnostic complaint; it is the origin code that means “this route
entered BGP by redistribution”, and it is what you should expect to
see for every prefix this lesson produces.
E1 and E2, and why you still need to understand them here
The metric-type does not cross into BGP, but it decides what the OSPF side of a mutual redistribution does with the routes coming back — so it belongs in this lesson even though it is configured elsewhere.
- E1 (External Type 1) — the receiving router’s cost is the external metric plus its own OSPF cost to the ASBR. The metric accumulates as the route propagates.
- E2 (External Type 2) — the cost is the external metric alone. The cost to reach the ASBR is ignored, so every router in the domain sees the same number. E2 is the default.
The configuration
Filter first, then redistribute. The order matters operationally: a
redistribute statement committed before its route-map exists is a
brief window in which everything OSPF knows is in your BGP table and
on its way to a peer.
# 1. What is allowed out
set policy prefix-list OSPF-TO-BGP rule 10 action 'permit'
set policy prefix-list OSPF-TO-BGP rule 10 prefix '10.0.0.0/8'
set policy prefix-list OSPF-TO-BGP rule 10 le '24'
set policy prefix-list OSPF-TO-BGP rule 20 action 'permit'
set policy prefix-list OSPF-TO-BGP rule 20 prefix '192.168.0.0/16'
set policy prefix-list OSPF-TO-BGP rule 20 le '24'
# 2. The route-map: filter, seed the MED, and stamp the loop tag
set policy route-map OSPF-TO-BGP rule 10 action 'permit'
set policy route-map OSPF-TO-BGP rule 10 match ip address prefix-list 'OSPF-TO-BGP'
set policy route-map OSPF-TO-BGP rule 10 set metric '100'
set policy route-map OSPF-TO-BGP rule 10 set community add '64512:400'
# 3. The redistribution
set protocols bgp system-as 64512
set protocols bgp address-family ipv4-unicast redistribute ospf route-map 'OSPF-TO-BGP'
commit
save
Three notes on the shapes above, each of which moved between releases or is easy to get wrong:
- The redistribution lives under the address family. In the 1.4/1.5
tree it is
set protocols bgp address-family ipv4-unicast redistribute ospf, not a top-level node, and the local AS is declared once withsystem-asrather than repeated in every line. - The prefix-list needs no trailing deny. A prefix-list ends in an
implicit deny; a prefix that matches no rule is denied. A rule with
an
actionand noprefixis not a catch-all, it is an incomplete node. set community addis the 1.4+ spelling of what 1.3 wrote as a value withadditivebaked into the string. Runset policy route-map NAME rule 10 set community ?on the box if you are unsure — the completion menu is the authority.
You can seed the MED either in the route-map (set metric) or on the
redistribution statement (redistribute ospf metric 100). Use one or
the other rather than both, and prefer the route-map when the value
differs per prefix.
Reading the result
vyos@r1:~$ show ip bgpBGP table version is 5, local router ID is 10.255.0.1, vrf id 0
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete
Network Next Hop Metric LocPrf Weight Path
*> 10.10.0.0/16 0.0.0.0 100 32768 ?
*> 192.168.0.0/19 0.0.0.0 100 32768 ?
Displayed 2 routes and 2 total pathsIllustrative output
The three columns that confirm the redistribution did what you asked:
Next Hop 0.0.0.0— locally originated. This is the local view; the peer receives a real next-hop chosen by BGP’s next-hop rules.Weight 32768— the weight FRR assigns to routes this router originated. It is local-only and never advertised.?— origin incomplete, the signature of redistribution.
If the metric column does not show your seed value, the route-map is
not being applied to that prefix — check which rule matched before
assuming the set metric is broken.
The feedback loop
R1 redistributes OSPF into BGP. Its eBGP peer R2 redistributes BGP back into OSPF. R1 now learns its own prefix from R2 as an OSPF external.
flowchart LR
R1I["R1 OSPF domain<br/>10.10.0.0/16 internal, cost 50"]
R1B["R1 BGP<br/>redistribute ospf<br/>MED 100"]
R2B["R2 BGP AS 64513<br/>receives 10.10.0.0/16"]
R2O["R2 OSPF<br/>redistribute bgp<br/>Type 5, metric 50, E2"]
R1L["R1 LSDB<br/>Type 5 for 10.10.0.0/16<br/>originated by R2"]
R1I --> R1B
R1B -->|eBGP| R2B
R2B --> R2O
R2O -->|"flooded back into the shared OSPF domain"| R1L
What happens next depends on the topology, and neither outcome is acceptable:
- If R1’s internal route for the prefix is still present, it wins. Intra-area beats external in OSPF’s route-type ordering, before any metric is compared. The Type 5 sits unused in the LSDB, generating flooding and SPF work for every router in the area, and it re-floods whenever R2’s metric changes.
- If R1’s internal route goes away — the link fails, the area is restructured — the Type 5 becomes the best path. R1 now routes the prefix towards R2, R2 routes it back towards R1 on the basis of the BGP route it learned from R1, and the traffic loops until the TTL expires. This is the outcome that takes the network down, and it arrives at the worst possible moment, because it is triggered by an unrelated failure.
Breaking it with a community
The route is stamped on the way out and refused on the way back:
# On R1 — already in the route-map above
set policy route-map OSPF-TO-BGP rule 10 set community add '64512:400'
# On R2 — refuse anything carrying the tag
set policy community-list FROM-R1 rule 10 action 'permit'
set policy community-list FROM-R1 rule 10 regex '64512:400'
set policy route-map BGP-INTO-OSPF rule 10 action 'deny'
set policy route-map BGP-INTO-OSPF rule 10 match community community-list 'FROM-R1'
set policy route-map BGP-INTO-OSPF rule 20 action 'permit'
set protocols ospf redistribute bgp metric 50 metric-type 2 route-map 'BGP-INTO-OSPF'
Rule 10 denies the tagged routes; rule 20 permits what is left. Note that rule 20 is required here — a route-map ends in an implicit deny, so without it nothing at all would be redistributed. That is the opposite of the situation in the outbound route-map above, where a trailing permit would have destroyed the filter. Read every route-map by asking what happens to a route that matches no rule.
Breaking it with an OSPF route tag
Where both directions are yours, the OSPF route tag is simpler, because it needs no BGP attribute and no agreement about community values:
# On R2, tag everything redistributed from BGP into OSPF
set protocols ospf redistribute bgp metric 50 metric-type 2 route-tag '65001'
# On R1, refuse to redistribute anything carrying that tag back into BGP
set policy route-map OSPF-TO-BGP rule 5 action 'deny'
set policy route-map OSPF-TO-BGP rule 5 match tag '65001'
The tag rides in the RIB, so match tag in the outbound route-map sees
it. Rule 5 sits ahead of the permit rule, which is where a deny has to
be — route-map rules are evaluated in numeric order and the first
match decides.
Operational commands
# Is the OSPF route selected in the RIB? Only selected routes redistribute.
show ip route ospf
show ip route 10.10.0.0/16
# Is it in the BGP table, with the right origin and metric?
show ip bgp
show ip bgp 10.10.0.0/16
# Is it actually being advertised to the peer?
show ip bgp neighbors 10.0.0.2 advertised-routes
# Is something feeding our own prefixes back as OSPF externals?
show ip ospf database external
show ip ospf database external self-originate
# The policy as the routing engine sees it
show configuration commands | match 'route-map OSPF-TO-BGP'
vtysh -c 'show route-map OSPF-TO-BGP'
advertised-routes is the one that settles arguments with a peer.
A prefix present in show ip bgp and absent from advertised-routes
is being stopped by outbound policy on the session, which is a
different problem from a redistribution that never happened.
Failure modes
The OSPF route never reaches the BGP table
Work down, not across:
- Is the route selected?
show ip route 10.10.0.0/16. If the OSPF entry is present but not marked best, redistribution will not see it. This is the failure with no error message. - Does the route-map permit it? Walk the rules in order and find the first that matches. Remember the implicit deny at the end — a prefix that matches no rule is dropped, and nothing logs it.
- Does the prefix-list permit it? Check the
leandgequalifiers as carefully as the prefix.10.0.0.0/8 le 24does not match10.10.0.0/25. - Is outbound policy on the session blocking it?
show ip bgp neighbors <peer> advertised-routes.
A new prefix leaked to the peer
An area is added, or a new prefix appears in OSPF, and the peer reports receiving something they should not have. In almost every case the route-map’s last rule is a permit with no match clause — added out of ACL habit, and it turns the filter into a pass-through for everything that did not match earlier.
A route-map already ends in an implicit deny. A trailing permit does not “finish” the policy; it removes it.
The peer ignores your MED
The seed metric is set, the MED is visible in your table, and the peer routes as though it were not there. MED comparison across an AS boundary is a policy decision made by the receiver, and many providers strip or overwrite it on ingress.
This is not a bug to fix on your side. Confirm what the peer’s policy does with MED before designing traffic engineering around it, and use AS-path prepending or a community the peer documents if MED is not honoured.
Own prefixes appear as OSPF externals
show ip ospf database external lists prefixes that originate inside
your own OSPF domain, with an ASBR that is not you. The loop is active,
whether or not it is currently changing anything.
Do not wait for it to cause an incident: the trigger is the disappearance of an internal route, which is exactly what happens during the unrelated failure you will be busy with at the time.
Rollback
# Stop the redistribution entirely — the fastest way to break a loop
delete protocols bgp address-family ipv4-unicast redistribute ospf
commit
# Or remove just the route-map binding, leaving the redistribution unfiltered
delete protocols bgp address-family ipv4-unicast redistribute ospf route-map
# Or return to a previous revision
rollback N
commit
Removing the route-map binding leaves the redistribution running with no filter, which is worse than either the problem or the fix. If the route-map is the suspect, delete the redistribution and re-add it with a corrected map.
When the redistribution stops, the peer withdraws the prefixes on the next update, and on the OSPF side the ASBR floods its Type 5 LSAs with MaxAge so the receiving routers purge them. Neither waits for the 30-minute LSA refresh interval — an LSA that is being withdrawn is aged out deliberately rather than left to expire.
Production discipline
Cross-course references
XIX-VyOS-OSPFConfig(vyos-xix-04-ospf-redistribute) is this lesson’s mirror image: redistribution into OSPF, where themetric-typeandroute-tagnodes live.XXV-VyOS-BGPAdvertise(vyos-xxv-04-bgp-redistribute-ospf) covers the same redistribution from the BGP advertisement side.XXVI-VyOS-BGPAttributescovers MED and origin, the two attributes this lesson assigns.XXIX-VyOS-BGPCommunities(vyos-xxix-05-community-routing) covers the community tagging idiom used here for loop prevention.XXXIII-VyOS-RoutePolicycovers route-map and prefix-list evaluation order, including the implicit deny that decides both examples above.
Quiz
Knowledge check · 4 questions
Q1. An OSPF E2 external route with metric 50 is redistributed into BGP by a route-map that sets metric 100. What does the eBGP peer receive?
Q2. The OSPF-BGP-OSPF feedback loop is a real production failure mode caused by unfiltered mutual redistribution between OSPF and BGP.
Q3. R1's own prefix is appearing in its OSPF database as an external LSA originated by its BGP peer. Explain the mechanism and stop it.
R1 (AS 64512) has `set protocols bgp address-family ipv4-unicast redistribute ospf route-map OSPF-TO-BGP`. R2 (AS 64513) shares the same OSPF domain and has `set protocols ospf redistribute bgp metric 50 metric-type 2 route-map BGP-INTO-OSPF`. Neither route-map applies a loop tag. R1's internal OSPF has 10.10.0.0/16 at cost 50. After 30 minutes an operator finds 10.10.0.0/16 in R1's OSPF database as a Type 5 external with R2 as the ASBR, alongside R1's own internal route for the same prefix. Traffic is currently unaffected.
Q4. A new OSPF area brings a prefix that the filter should have stopped, and the peer receives it. Find the defect in the route-map.
R1 redistributes OSPF into BGP with `route-map OSPF-TO-BGP`. The map is: rule 10 `action permit` with `match ip address prefix-list INTERNAL-NETWORKS`, and rule 20 `action permit` with no match clause, added by a previous operator. The prefix-list INTERNAL-NETWORKS permits 10.10.0.0/16 only. A new area is brought up and R1 begins learning 172.16.0.0/16 over OSPF. Within minutes the peer at 10.0.0.2 reports 172.16.0.0/16 in their table.
Passing score: 75%. Answers are checked in this browser.