VyOSXVIII · OSPF FundamentalsOSPF
OSPF neighbours and adjacency — the hello protocol and the eight-state machine
What you'll learn
- Describe every state in the OSPF neighbour FSM and what triggers each transition
- Configure hello/dead intervals, priority and authentication on a VyOS 1.5 LTS OSPF interface
- Distinguish a neighbour that is missing entirely from one that is stuck part-way, and diagnose each
- Recognise why a 2-Way state is correct on a broadcast segment but a failure on a point-to-point link
Prerequisites
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-15
OSPF does not route anything until two routers have completed a defined handshake on every shared interface. The handshake has eight states (Down, Attempt, Init, 2-Way, ExStart, Exchange, Loading, Full) and a short list of parameters that must agree before a single LSA is exchanged. Getting this right is the foundation of every later OSPF lesson; getting it wrong is the most common reason OSPF does not come up in production.
The view the engineer holds:
vyos@r1:~$ show ip ospf neighborNeighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL
2.2.2.2 1 Full/DR 2m52s 38.480s 10.0.0.2 eth0:10.0.0.1 0 0 0
3.3.3.3 1 Full/Backup 2m50s 37.222s 10.0.0.3 eth0:10.0.0.1 0 0 0
4.4.4.4 1 2-Way/DROther 2m48s 39.001s 10.0.0.4 eth0:10.0.0.1 0 0 0Illustrative output
A production OSPF engineer reads this the way a database engineer reads a connection pool — line by line, every cell a diagnostic. Read the header rather than counting columns: FRR has added fields to this table across releases, so a script that indexes by position will break on an upgrade while a human reading the header will not.
State carries two halves separated by a slash: the FSM state, then
the neighbour’s role on that segment (DR, Backup, DROther).
Up Time is how long the adjacency has held; a value that keeps
returning to seconds is a flap, whatever the state column says at the
instant you looked. Dead Time counts down and is reset by every Hello
received, so with the default hello 10 and dead 40 it oscillates
between roughly 30 and 40 seconds; a value that regularly dips well
below that is Hellos being lost, not a timer problem. The Interface
column names the local interface and the local address on it. RXmtL
is the retransmission list — LSAs this router has sent and not yet had
acknowledged. A persistently non-zero RXmtL on a Full adjacency means
flooding is being lost, and it is one of the earliest warnings
available.
The single most important reading skill here is negative: a neighbour that never appears in this table at all is a different failure from a neighbour that appears and is stuck. Nothing in the table means the Hello packets are being rejected or never arriving. A row that is stuck means Hellos are fine and the problem is further along.
The state machine
Every OSPF neighbour on every interface walks the FSM independently. Two neighbours on the same segment can sit in different states at the same time:
stateDiagram-v2
[*] --> Down
Down --> Attempt : NBMA only, send unicast Hello
Attempt --> Init : Hello received
Down --> Init : Hello received
Init --> TwoWay : own router-id seen in the neighbour's Hello
TwoWay --> ExStart : this pair is supposed to be adjacent
ExStart --> Exchange : master/slave and DD sequence agreed
Exchange --> Loading : DD exchange done, LSAs still to request
Loading --> Full : every requested LSA received
TwoWay --> TwoWay : two DROthers stay here by design
Full --> Down : dead timer expired
Full --> [*]
Each state means something the engineer must understand:
- Down — no Hello has been heard from this neighbour within the dead interval. Either it never existed or it has just been lost.
- Attempt — NBMA (non-broadcast) networks only. There is no multicast to discover with, so the local router polls a manually-configured neighbour address with unicast Hellos.
- Init — a Hello has arrived from the neighbour, but that Hello did not list our router-id. We can hear them; they cannot hear us, or they are discarding what they hear. This state is the signature of a one-way path.
- 2-Way — each side has seen its own router-id in the other’s Hello. Bidirectional reachability is proven. On a broadcast segment, only pairs involving the DR or BDR go further; two DROthers stop here deliberately.
- ExStart — the two routers negotiate which is master for the Database Description exchange and agree the starting sequence number. The DD packets exchanged here also carry each side’s interface MTU, which is why this is where an MTU mismatch bites.
- Exchange — DD packets carrying LSA headers flow in both directions. Each side compares the headers with its own database and builds a request list of what it is missing or holds a stale copy of.
- Loading — Link State Requests go out and Link State Updates come back, until the request list is empty.
- Full — the two databases are synchronised for this area, and the adjacency is usable. Both routers now describe the link in their Router LSAs.
The parameters that must agree
RFC 2328 section 10.5 defines what a router checks in a received Hello before it will accept the sender as a neighbour. A packet that fails any of these is discarded, which is why the failure mode is silence rather than an error state.
- Area ID — both ends must place the interface in the same area.
- Network mask — both ends must agree on the prefix length of the shared subnet. This check is skipped on point-to-point and virtual links, where the mask is not meaningful. A /24 facing a /25 on the same Ethernet is a real and frequently-missed cause of “no neighbour at all”.
- HelloInterval — must be identical.
- RouterDeadInterval — must be identical.
- The E-bit (external routing capability) in the options field — both ends must have the same idea of whether this area accepts AS-external LSAs. This is what stops a stub-area router from becoming adjacent with a neighbour that has not been told the area is a stub.
- Authentication — the type and, for MD5, the key-id and key must match. Authentication is validated before the packet reaches the neighbour state machine at all.
FRR does report these. Its Hello-processing path logs the specific
mismatch it found and the two values involved — a hello-interval
mismatch, a dead-interval mismatch, a network mask mismatch — and those
lines are the fastest way to close out the “why is there no neighbour”
question. Look for them with show log, or turn on debug ospf packet recv inside vtysh if the log is quiet.
Parameters that do not stop adjacency but do cause damage
- Network type.
broadcaston one end andpoint-to-pointon the other is not checked in the Hello, so the adjacency can come up. What breaks is downstream: the two Router LSAs then describe the same link in incompatible terms — one as a transit link into a Network LSA that the other end never joins, the other as a point-to-point link. SPF only follows a link it can confirm from the far end’s LSA as well, so the link is dropped from the tree. The symptom is the memorable one: aFulladjacency with no route across it. Confirm by reading both ends’show ip ospf database routerandshow ip ospf route. - MTU. Not checked in the Hello, checked explicitly in the DD packet. See “stuck in ExStart” below.
- Priority. Not required to match, and does not affect adjacency formation. It affects only which router wins the DR election, which is the subject of a later lesson in this part.
Configuration — interface-level OSPF parameters
On VyOS 1.5 the interface knobs live under set protocols ospf interface, while area membership is decided by the network
statements under set protocols ospf area:
# Put the 10.0.0.0/24 interfaces into area 0
set protocols ospf area 0 network 10.0.0.0/24
# Tune the timers (both ends must match)
set protocols ospf interface eth0 hello-interval 5
set protocols ospf interface eth0 dead-interval 20
# Influence the DR election on this segment
set protocols ospf interface eth0 priority 200
# Force the network type: two routers on a dedicated Ethernet
set protocols ospf interface eth0 network point-to-point
# Explicit cost, overriding the bandwidth-derived value
set protocols ospf interface eth0 cost 10
# MD5 authentication: the key-id and the key must match the far end
set protocols ospf interface eth0 authentication md5 key-id 1 md5-key SHAREDSECRET
# Skip the DD MTU check on this interface (see the warning below)
set protocols ospf interface eth0 mtu-ignore
Ethernet interfaces default to the broadcast network type, and
interfaces that are point-to-point at the link layer default to
point-to-point. The default hello and dead intervals are 10 and 40
seconds — and unlike some vendors, FRR applies those same two defaults
to every network type rather than using the RFC’s suggested 30/120 on
NBMA and point-to-multipoint. If you are interoperating with a platform
that does default to 30/120, one end will have to be configured
explicitly. Read the effective values from show ip ospf interface
rather than assuming either convention.
| Network type | DR election | Type 2 (Network) LSA | Typical use |
|---|---|---|---|
broadcast | Yes | Yes, from the DR | Ethernet with three or more routers |
point-to-point | No | No | A link between exactly two routers |
point-to-multipoint | No | No | Hub-and-spoke over a partial mesh |
non-broadcast | Yes, with configured neighbours | Yes, from the DR | NBMA fabrics with no multicast |
Production guidance:
- Use the default timers unless there is a documented reason. Faster hellos detect failure sooner and cost stability; if sub-second detection is the goal, BFD is the right tool and OSPF timers are not.
- Change timers on both ends in the same window. A mismatch does not degrade the adjacency, it removes it entirely.
- Use
point-to-pointon a two-router Ethernet. It removes the DR election, removes the Network LSA, and removes the 2-Way-as-DROther confusion — but it must be set on both ends, or you get the Full adjacency with no route described above.
What the operational commands show
vyos@r1:~$ show ip ospf interface eth0eth0 is up
ifindex 2, MTU 1500 bytes, BW 1000 Mbit <UP,BROADCAST,RUNNING,MULTICAST>
Internet Address 10.0.0.1/24, Broadcast 10.0.0.255, Area 0.0.0.0
MTU mismatch detection: enabled
Router ID 1.1.1.1, Network Type BROADCAST, Cost: 10
Transmit Delay is 1 sec, State DR, Priority 1
Backup Designated Router (ID) 2.2.2.2, Interface Address 10.0.0.2
Multicast group memberships: OSPFAllRouters OSPFDesignatedRouters
Timer intervals configured, Hello 10s, Dead 40s, Wait 40s, Retransmit 5
Hello due in 7.667s
Neighbor Count is 3, Adjacent neighbor count is 2Illustrative output
Reading it, in the order that matters when something is wrong:
MTU 1500 bytesandMTU mismatch detection: enabled— the value the DD packet will advertise, and whether this router will enforce the check.mtu-ignoreturns the second line todisabled.Internet Address 10.0.0.1/24…Area 0.0.0.0— the mask and the area, two of the must-match items, straight from the router rather than from the configuration you think you committed.Network Type BROADCAST— decides whether a DR is elected at all, and therefore whether2-Wayis healthy on this segment.Cost: 10— the effective cost. It is not a constant: FRR divides the reference bandwidth (default 100 Mbit, changed withset protocols ospf auto-cost reference-bandwidth) by the interface bandwidth, and a manualcostoverrides the result. Read it here rather than predicting it.Timer intervals configured, Hello 10s, Dead 40s— the other two must-match items. Compare this line between the two ends and half the “no neighbour” cases close themselves.Neighbor CountvsAdjacent neighbor count— how many neighbours this interface knows, and how many of those reached Full. On a broadcast segment with a DR, a BDR and two DROthers, a DROther sees four neighbours and two adjacencies, and that is correct. On a point-to-point link the two numbers must be equal.
For the per-neighbour detail — including the DD sequence number, the
retransmission list and the neighbour’s options — use show ip ospf neighbor detail.
Why adjacency gets stuck — the production failure modes
No neighbour at all
The table is empty, or missing the router you expected. Hellos are being discarded or never arriving.
Work through the discard list from RFC 2328 in the order that costs
least to check: area, mask, hello interval, dead interval, area type
(the E-bit), authentication. show ip ospf interface on both ends
shows the first four directly. Then check delivery: tcpdump -nn -i eth0 proto 89 on each end shows whether the other’s Hellos physically
arrive. A firewall rule, an access port in the wrong VLAN, or a switch
that filters multicast all present as “my Hellos leave, none arrive”.
Also check the obvious one that is not a mismatch at all: an interface that has been made passive sends no Hellos and forms no neighbour. It is not stuck — it is not participating.
Stuck at Init
We hear the neighbour; the neighbour’s Hellos do not list our router-id. The path is one-way at some layer.
Causes: a genuinely unidirectional link (a broken fibre strand, a failing SFP on the transmit side), a firewall rule applied in one direction only, an authentication or parameter mismatch that makes the far end discard our Hellos while we accept theirs, or the far end having our interface passive.
The asymmetry is the diagnostic. Init means our receive path works, so concentrate on our transmit path and on the far end’s discard rules.
Stuck at ExStart or Exchange
The neighbour is heard and confirmed two-way, but the database exchange does not complete. The classic cause is an IP MTU mismatch, and the mechanism is explicit rather than accidental: every Database Description packet carries the sending interface’s MTU. A router that receives a DD advertising an MTU larger than its own interface MTU rejects the packet, so the negotiation never finishes and the pair oscillates in ExStart or Exchange.
Diagnostic: show ip ospf interface on both ends and compare the
MTU line; ospfd logs an explicit MTU-mismatch message naming the
expected and received values.
Fix: make the MTUs equal — set interfaces ethernet eth0 mtu 9000 on
the smaller side, or bring the larger side back to 1500. Watch for the
asymmetry a tunnel introduces: a GRE or VTI interface has a lower MTU
than the Ethernet under it, and an OSPF adjacency across the tunnel
must be compared against the tunnel’s MTU, not the physical one.
Stuck at Loading
The request list is not emptying: this router has asked for LSAs and is not getting usable answers.
The signal to read is RXmtL and RqstL in show ip ospf neighbor —
a request list that never drains, or a retransmission list that keeps
growing, means Link State Requests or the Updates answering them are
being lost. A lossy or heavily congested link does this, and so does a
path that passes small packets (the Hellos and DDs) while dropping
large ones — which is the MTU problem again, one stage later.
There is one protocol-level cause worth knowing: if a router requests an LSA the neighbour cannot supply, the neighbour responds with a BadLSReq event and the adjacency resets to ExStart to start over. An adjacency that repeatedly climbs to Loading and drops back is showing you that, not a timer problem.
How to diagnose — a production flow
# 1. Is there a neighbour at all, and what state is it in
show ip ospf neighbor
# 2. The must-match parameters, from the router rather than the config
show ip ospf interface eth0
# 3. Per-neighbour detail: DD sequence, request and retransmit lists
show ip ospf neighbor detail
# 4. What the daemon has been saying
show log | match ospfd
# 5. Layer 1 and 2
show interfaces ethernet eth0
# 6. Are the packets physically arriving
tcpdump -nn -i eth0 proto 89
Run step 2 on both ends and compare, before doing anything else. The great majority of adjacency faults are a difference between two outputs that each look perfectly reasonable on their own.
A canonical stuck neighbour reads:
vyos@r1:~$ show ip ospf neighborNeighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL
2.2.2.2 1 Init/DROther 0s 33.219s 10.0.0.2 eth0:10.0.0.1 0 0 0Illustrative output
Dead Time is counting down and being reset by each arriving Hello, so
the row will persist rather than disappear — the neighbour is not going
away, it is simply never going to advance. Up Time at or near zero on
a row that has been there for minutes is the confirmation: no adjacency
has ever been established.
Rollback
There is no single “undo” for an adjacency change, and the safe path depends on how far the change has got.
Before committing, in configuration mode:
compare
discard
Committing a change to the interface you are connected through — which an OSPF timer or authentication change on an uplink usually is:
commit-confirm 5
commit
The first command commits and arms a five-minute revert. If the change locks you out, doing nothing restores the previous configuration. The second confirms it once you have verified the adjacency.
To back a committed change out, delete the specific nodes and commit again — this returns the interface to the platform defaults rather than to some remembered value:
delete protocols ospf interface eth0 hello-interval
delete protocols ospf interface eth0 dead-interval
delete protocols ospf interface eth0 priority
commit
Two rollbacks that are not symmetric with the change that caused them:
- Network type. Going back from
point-to-pointtobroadcastreintroduces the DR election and a new Network LSA. The adjacency will drop and reform, and the area will run SPF. Plan for a flap. - Priority. Lowering the priority on the current DR does not demote it. OSPF’s election is deliberately non-preemptive: the sitting DR stays DR until it loses its adjacencies. The rollback looks like it did nothing until the next time the segment restarts.
Production discipline
Cross-course references
- RFC 2328 section 10 — the canonical neighbour FSM, and section 10.5 for the Hello discard rules that produce “no neighbour at all”.
- The Linux course’s
XX-Linux-NetConfigcovers the multicast mechanics OSPF relies on for Hello delivery. - Part XVII (
XVII-VyOS-RoutingFund) lesson 1 covers adjacency in generic terms; this lesson specialises it to OSPF. - Part XVIII lesson 5 covers the DR/BDR election that decides which pairs on a broadcast segment go past 2-Way.
- Part XIX (
XIX-VyOS-OSPFConfig) covers the interface configuration tree, passive interfaces and authentication in depth. - Part XXII (
XXII-VyOS-OSPFTroubleshoot) covers the stuck-neighbour workflow as a troubleshooting exercise.
Quiz
Knowledge check · 4 questions
Q1. An OSPF adjacency reaches 2-Way and then oscillates in ExStart without ever reaching Full. What is the most likely cause?
Q2. When OSPF authentication fails, the adjacency appears in `show ip ospf neighbor` with a state that identifies the authentication problem.
Q3. R1 and R2 face each other on 10.0.0.0/24. R1 shows R2 in Init and never advances. R2 shows no neighbour at all. What does this asymmetry tell you, and how do you close it out?
R1: `show ip ospf neighbor` lists 2.2.2.2 in Init/DROther with Dead Time counting down and resetting, and Up Time at zero. R2: `show ip ospf neighbor` is empty. Both interfaces are up, both are in area 0, and tcpdump on each end shows the local router transmitting Hellos.
Q4. R2 was configured with `hello-interval 30` and `dead-interval 120` to match a legacy platform. A VyOS router R1 on the same segment uses the defaults. The operator reports the adjacency is 'flapping'. What is actually happening?
R1 runs the defaults, hello 10 and dead 40. R2 has `set protocols ospf interface eth0 hello-interval 30` and `set protocols ospf interface eth0 dead-interval 120`. Both interfaces are up, both are in area 0 on the same /24, and tcpdump on each end shows the other's Hello packets arriving. `show ip ospf neighbor` is empty on both routers.
Passing score: 75%. Answers are checked in this browser.