Skip to content

OSPF

Open Shortest Path First (OSPF) is a link-state interior gateway protocol that builds a complete topology map of the network and computes shortest paths using Dijkstra’s algorithm. RouterOS implements OSPFv2 (RFC 2328) for IPv4 and OSPFv3 (RFC 5340) for IPv6, with a unified configuration model in RouterOS v7.

OSPF divides a routing domain into areas to limit the scope of topology flooding. Routers within an area share a complete link-state database (LSDB); only summarised information crosses area boundaries via Area Border Routers (ABRs). The backbone area (0.0.0.0) connects all other areas and carries inter-area traffic.

Key advantages of OSPF over distance-vector protocols:

  • Fast convergence via incremental LSA flooding rather than periodic full-table updates
  • Loop-free by design (SPF algorithm)
  • Hierarchical scaling through area segmentation and route summarisation
  • Rich external route redistribution with metric and type control

OSPF routers exchange Link-State Advertisements (LSAs) to build a consistent topology database. Each LSA type carries different information and has a defined flooding scope.

TypeNameGenerated byFlooding scope
1Router LSAEvery OSPF routerWithin the originating area
2Network LSADesignated Router (DR)Within the originating area
3Summary LSA (network)ABRInto adjacent areas
4Summary LSA (ASBR)ABRInto adjacent areas
5AS External LSAASBREntire OSPF domain (blocked by stub areas)
7NSSA External LSAASBR inside NSSANSSA only; translated to Type 5 at ABR

Key implications:

  • Type 3 LSAs are how inter-area routes cross area boundaries. An ABR generates one Type 3 per prefix it summarises from each attached area.
  • Type 5 LSAs flood everywhere except stub and NSSA areas. Large external routing tables bloat the LSDB domain-wide — use stub/NSSA area types to contain this.
  • Type 7 LSAs allow an NSSA to host an ASBR while still blocking domain-wide Type 5 flooding. The ABR translates Type 7 → Type 5 before advertising toward the backbone.

Inspect the LSDB:

# All LSAs
/routing ospf lsa print detail
# Filter by type
/routing ospf lsa print detail where type=external
/routing ospf lsa print detail where type=nssa
/routing ospf lsa print detail where type=inter-area-prefix
  • RouterOS v7 (this guide uses the v7 routing configuration model)
  • Package: routing (included in all RouterOS builds)
  • At least one configured IP address per OSPF-enabled interface

RouterOS v7 OSPF uses a three-layer configuration hierarchy:

  1. Instance — process-wide settings (router-id, version, redistribution)
  2. Area — area-id, type, and association with an instance
  3. Interface template — binds interfaces or subnets to an area with per-link settings

Minimal two-router OSPF configuration in backbone area only:

# Router A
/routing ospf instance
add name=ospf1 version=2 router-id=1.1.1.1
/routing ospf area
add name=backbone instance=ospf1 area-id=0.0.0.0
/routing ospf interface-template
add area=backbone interfaces=ether1 type=ptp
# Router B
/routing ospf instance
add name=ospf1 version=2 router-id=2.2.2.2
/routing ospf area
add name=backbone instance=ospf1 area-id=0.0.0.0
/routing ospf interface-template
add area=backbone interfaces=ether1 type=ptp

Verify the adjacency:

/routing ospf neighbor print detail

A healthy neighborship shows state: full.

OSPF defines area types to control LSA flooding scope and reduce memory/CPU on stub routers.

Every non-backbone area must be directly connected to 0.0.0.0. The backbone carries Type-3 (inter-area) LSAs between areas and may not be configured as stub or NSSA.

/routing ospf area
add name=backbone instance=ospf1 area-id=0.0.0.0 type=default

A stub area blocks Type-5 external LSAs. The ABR automatically injects a default route into the stub area. Use this for branch sites that should reach external destinations via the ABR default, not via individual external prefixes.

Restrictions: no ASBRs inside, no virtual links through the area.

/routing ospf area
add name=branch-stub instance=ospf1 area-id=0.0.0.10 type=stub
/routing ospf interface-template
add area=backbone interfaces=ether1 type=ptp
add area=branch-stub interfaces=ether2 type=ptp

An NSSA allows an ASBR inside the area to redistribute external routes as Type-7 LSAs. The ABR translates Type-7 to Type-5 when flooding toward the backbone. Use this when a branch site needs to inject external routes (e.g., a connected ISP link) while still limiting Type-5 flooding from the rest of the domain.

Restrictions: no virtual links through the area.

/routing ospf area
add name=branch-nssa instance=ospf1 area-id=0.0.0.20 type=nssa
/routing ospf interface-template
add area=backbone interfaces=ether1 type=ptp
add area=branch-nssa interfaces=ether3 type=ptp
# Enable redistribution on the ASBR inside the NSSA
/routing ospf instance
set [find name=ospf1] redistribute=connected,static

Interface templates control how each link participates in OSPF. They match by interfaces= (interface name) and bind the link to an area with per-link parameters.

Key parameters:

ParameterDescription
areaArea this template assigns interfaces to
interfacesInterface name(s) to match
typeNetwork type: broadcast, ptp, nbma, ptmp, ptmp-broadcast
priorityDR election priority (0 = ineligible)
costInterface cost metric
networksMatch interfaces by subnet prefix (e.g. 10.0.0.0/24) instead of by name
hello-intervalHello packet interval (default 10 s)
dead-intervalNeighbor timeout (default 40 s)
/routing ospf interface-template
# Core uplink: point-to-point, no DR election
add area=backbone interfaces=ether1 type=ptp cost=10
# LAN segment: broadcast, participate in DR election with high priority
add area=backbone interfaces=bridge-lan type=broadcast priority=100
# Loopback/stub network: advertise but no OSPF neighbors
add area=backbone interfaces=lo type=ptp cost=1

On broadcast and NBMA segments, OSPF elects a Designated Router (DR) and Backup Designated Router (BDR) to reduce the number of adjacencies from O(n²) to O(n). All routers form full adjacency with the DR/BDR only.

Election rules:

  1. Highest priority wins (range 0–255; 0 = ineligible)
  2. Tie broken by highest router-id
  3. Election is non-preemptive: a new router with higher priority does not replace an active DR until the DR fails or adjacencies are reset

Set the router-id explicitly to ensure deterministic election:

/routing ospf instance
set [find name=ospf1] router-id=10.255.255.1
/routing ospf interface-template
# High priority: preferred DR candidate on this LAN
add area=backbone interfaces=bridge-lan type=broadcast priority=200
# Low priority: BDR candidate
add area=backbone interfaces=ether2 type=broadcast priority=50
# Zero priority: never becomes DR/BDR
add area=backbone interfaces=ether3 type=broadcast priority=0

Point-to-point links skip DR/BDR election entirely and form a direct Full adjacency, making them preferred for WAN links and tunnels:

/routing ospf interface-template
add area=backbone interfaces=ether4 type=ptp

To force re-election on a broadcast segment (e.g., after changing priority):

/routing ospf interface-template disable [find interfaces=bridge-lan]
/routing ospf interface-template enable [find interfaces=bridge-lan]

A virtual link provides a logical connection to the backbone (0.0.0.0) for an area that cannot connect physically. It is tunnelled through a transit area (a normal area that already connects to the backbone) between two ABRs.

Virtual links should be treated as a temporary workaround, not a permanent design choice. They increase troubleshooting complexity and depend on transit area stability.

When to use a virtual link:

  • An acquired or remote network segment cannot physically reach Area 0.
  • The backbone has partitioned and requires immediate repair while a physical link is arranged.

Configuration — both ABRs must create mirror-image virtual link entries:

# ABR-1 (router-id 1.1.1.1): connects backbone + transit Area 2
/routing ospf instance
add name=ospf1 version=2 router-id=1.1.1.1
/routing ospf area
add name=backbone area-id=0.0.0.0 instance=ospf1
add name=transit area-id=0.0.0.2 instance=ospf1
/routing ospf interface-template
add interfaces=ether1 area=backbone type=ptp
add interfaces=ether2 area=transit type=ptp
# Virtual link to ABR-2 through Area 2
add type=virtual-link area=backbone vlink-transit-area=transit vlink-neighbor-id=2.2.2.2
# ABR-2 (router-id 2.2.2.2): connects transit Area 2 + remote Area 3
/routing ospf instance
add name=ospf1 version=2 router-id=2.2.2.2
/routing ospf area
add name=backbone area-id=0.0.0.0 instance=ospf1
add name=transit area-id=0.0.0.2 instance=ospf1
add name=area3 area-id=0.0.0.3 instance=ospf1
/routing ospf interface-template
add interfaces=ether1 area=transit type=ptp
add interfaces=ether2 area=area3 type=ptp
# Virtual link back to ABR-1 through Area 2
add type=virtual-link area=backbone vlink-transit-area=transit vlink-neighbor-id=1.1.1.1

Requirements:

  • Transit area must be a normal (non-stub, non-NSSA) area.
  • Both endpoints must use the same vlink-transit-area.
  • vlink-neighbor-id is the remote ABR’s router-id, not its IP address.
  • If authentication is configured on the backbone, ensure the virtual-link template uses matching authentication settings.

Verify:

/routing ospf neighbor print detail where type=virtual

The virtual neighbor should reach state: full. The transit area entry in /routing ospf lsa print will show a Type 1 LSA for the virtual link.

OSPF can redistribute routes from connected interfaces, static routes, and BGP into the OSPF domain as Type-5 external LSAs (or Type-7 inside NSSA).

Enable redistribution and set per-protocol metrics via an out-filter-chain. RouterOS v7 does not support per-protocol metric parameters directly on the instance; metrics and type are set in routing filter rules.

/routing ospf instance
set [find name=ospf1] redistribute=connected,static,bgp out-filter-chain=ospf-redistribute
/routing filter rule
# Connected routes: type2, metric 20
add chain=ospf-redistribute rule="if (protocol connected) { set ospf-ext-metric 20; set ospf-ext-type type2; accept }"
# Static routes: type1, metric 10
add chain=ospf-redistribute rule="if (protocol static) { set ospf-ext-metric 10; set ospf-ext-type type1; accept }"
# BGP routes: type2, metric 50
add chain=ospf-redistribute rule="if (protocol bgp) { set ospf-ext-metric 50; set ospf-ext-type type2; accept }"
add chain=ospf-redistribute rule="accept"
  • type1: external metric is added to internal OSPF cost (comparable across areas)
  • type2: external metric is used as-is (default; simpler but less accurate across areas)

Use a routing filter chain to control exactly which routes are exported and with what attributes:

/routing ospf instance
set [find name=ospf1] \
redistribute=connected,static,bgp \
out-filter-chain=ospf-export
/routing filter rule
# Advertise default route as type1 with tag 100
add chain=ospf-export rule="if (protocol static && dst == 0.0.0.0/0) { \
set ospf-ext-type type1; set ospf-ext-metric 5; set ospf-ext-tag 100; accept }"
# Advertise specific static summary
add chain=ospf-export rule="if (protocol static && dst in 10.10.0.0/16) { \
set ospf-ext-metric 30; accept }"
# Advertise connected loopbacks
add chain=ospf-export rule="if (protocol connected && dst in 172.16.0.0/12) { \
set ospf-ext-metric 25; accept }"
# Drop everything else
add chain=ospf-export rule="reject"
/routing ospf neighbor print detail

Expected end state is state: full. Intermediate states indicate where adjacency formation is stuck:

StateMeaning
downNo hellos received
initHello received but own router-id not seen in neighbor’s hello
2-wayBidirectional hello; DR/BDR election complete (non-DR pairs stop here)
exstartMaster/slave negotiation for database exchange
exchangeDatabase Description packets exchanged
loadingLSA requests outstanding
fullLSDB synchronised; healthy adjacency
# All LSAs in all areas
/routing ospf lsa print detail
# Filter by area
/routing ospf lsa print detail where area=backbone
# Filter by type (e.g., external LSAs)
/routing ospf lsa print detail where type=external
# Only self-originated LSAs
/routing ospf lsa print detail where self-originate=yes

Filter routes by OSPF instance name (replace ospf1 with your instance name):

/routing route print where belongs-to=ospf1

To list all routes and identify OSPF entries by their distance (110 by default):

/routing route print where distance=110
/system logging
add topics=route,ospf,debug action=memory
/log print where topics~"ospf"

Neighbors stuck in Init

  • Mismatch in area-id on the shared segment
  • Hello/dead interval mismatch (must match on both sides)
  • Firewall blocking OSPF multicast (224.0.0.5 / 224.0.0.6) or IP protocol 89

Neighbors stuck in ExStart/Exchange

  • MTU mismatch between interfaces; align MTU on physical interfaces to match across the OSPF segment
  • Authentication mismatch (key, type, or timing)

Neighbors Full but no routes installed

  • Area type mismatch (e.g., one side configured as stub, other as default)
  • Route filtered by out-filter-chain on the originating router
  • Missing redistribute= on the ASBR for external routes

Expected external routes missing

  • Confirm redistribute= includes the source protocol on the ASBR
  • Check out-filter-chain is not rejecting the route
  • In NSSA: verify the ABR is translating Type-7 to Type-5 (check LSA types in backbone area)

All routers in 0.0.0.0. Simple to configure and troubleshoot. Appropriate when the network has fewer than ~50 routers and LSA flooding overhead is acceptable.

Core routers form the backbone; branch sites each get a dedicated stub or NSSA area.

Internet
Core (Area 0)
/ \
Area 1 Area 2
(stub) (nssa)
branch branch+asbr
  • Use stub areas for branches that only need connectivity through the core; they receive a single default route instead of all external LSAs.
  • Use NSSA for branches that also inject external routes (a second ISP or a local connected subnet) into the domain.
  • Set type=stub or type=nssa on the area and use interface-template to assign the ABR’s branch-facing interface to that area.

Route summarisation at the ABR reduces the number of Type 3 LSAs flooded into the backbone:

# Summarise Area 1's prefixes at the ABR before advertising to the backbone
/routing ospf area range
add area=area1 prefix=10.1.0.0/16 advertise=yes
# Optionally suppress more-specifics from the backbone
/routing ospf area range
add area=area1 prefix=10.1.0.0/16 advertise=no

Two ABRs between the backbone and a non-backbone area provide redundancy. Both ABRs generate Type 3 LSAs for the same prefixes; OSPF path selection uses the lowest inter-area cost.

To ensure predictable path preference, set a higher cost on the secondary ABR’s interface-template.

Network scaleRecommended structure
< 50 routersSingle area (Area 0 only)
50–500 routersHub-and-spoke, 5–20 areas
500+ routersMulti-level hierarchy; consider BGP for inter-DC routing

Key constraints:

  • All non-backbone areas must connect to Area 0 (directly or via virtual link).
  • Avoid virtual links in production — they are a workaround, not a design pattern.
  • Keep areas to fewer than 100–150 routers to limit SPF recalculation scope.
  • On loopbacks and access-layer interfaces, use type=ptp with a high cost to advertise the network without forming unnecessary neighbors.
  • Route Filters — routing filter rule syntax for redistribution policy
  • BFD — sub-second failure detection for OSPF neighbors
  • BGP — BGP route redistribution into OSPF