VyOSXVII · Routing Protocol FundamentalsControl plane
Adjacency — the neighbour relationship that has to exist before any routing can happen
What you'll learn
- Define a routing adjacency and explain why it must exist before routes can be exchanged
- Explain how the OSPF hello, dead, and retransmit intervals drive the adjacency state machine on FRR
- Read the OSPF neighbour state machine from Down through Attempt, Init, 2-Way, Exstart, Exchange, Loading, and Full
- Recognise the RFC 4271 BGP states Idle, Connect, Active, OpenSent, OpenConfirm, and Established
- Map each VyOS adjacency command onto the FRR line it renders, and name what VyOS does not expose
- Diagnose the production failure modes that keep an adjacency from reaching Full or Established
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)
A dynamic routing protocol is a conversation between two routers. No route is exchanged, no topology is learned, no failover happens until that conversation reaches the state where both sides agree they are talking to each other and that the conversation is healthy. That state is called an adjacency in OSPF and IS-IS, and an Established session in BGP. This lesson is about what an adjacency is, how it forms, how the routers on each end decide it is healthy enough to use, and the production failure modes that keep it from ever forming in the first place.
The lesson sits in Part XVII because every later protocol lesson in the course — OSPF, IS-IS, BGP, BFD — assumes an adjacency has formed. The operator who cannot read the adjacency state machine cannot tell whether a “missing route” is a missing route or an adjacency that never came up.
What an adjacency is
An adjacency is the protocol-level relationship between two routers that have agreed to exchange routing information with each other. It is more than a session: it is the state the session reaches after both sides have proven they can hear each other, agree on protocol parameters, and have synchronised whatever databases the protocol requires.
flowchart LR
A[Router R1] -->|Hello| B[Router R2]
B -->|Hello| A
A -->|DBD then LSR then LSU| B
B -->|DBD then LSR then LSU| A
A -->|Full state| B
B -->|Full state| A
Different protocols call the relationship different things and have different states for it. OSPF calls it an adjacency and the final state is Full. IS-IS calls it an adjacency and the final state is Up. BGP calls it a session and the final state is Established. The terminology differs; the concept is the same: the relationship is the precondition for route exchange, and it is held alive by periodic messages the two routers send each other.
OSPF neighbour discovery and the state machine
OSPF discovers neighbours by sending Hello packets out every interface that has OSPF enabled. The hello packet carries the router ID of the sending router, the area ID, the network mask, the hello interval, the dead interval, the OSPF priority, the list of neighbours the sender has already seen on that segment, and a few option bits.
stateDiagram-v2
[*] --> Down
Down --> Attempt: NBMA neighbour configured, hello sent
Down --> Init: Hello received
Attempt --> Init: Hello received
Init --> TwoWay: Peer hello lists my router ID
TwoWay --> Exstart: DR and BDR elected, or link is point-to-point
Exstart --> Exchange: Master and slave roles agreed
Exchange --> Loading: DBD exchange finished
Loading --> Full: Every outstanding LSR satisfied
Full --> Down: Dead interval expires
TwoWay --> Down: Dead interval expires
The neighbour state machine walks through eight states:
- Down — no hello received from the neighbour. The local router has not heard from the peer.
- Attempt — the local router is configured to peer on an
NBMA segment with
set protocols ospf neighborand is actively sending unicast hello packets, but has not received one yet. - Init — the local router has received a hello from the peer but the peer’s hello does not list the local router’s router ID in its neighbour list yet.
- 2-Way — both routers have seen each other in hello packets. Bidirectional communication is established. On broadcast and NBMA segments, the Designated Router (DR) election happens here. Only the DR and BDR go on to form adjacencies with all routers on the segment; other routers settle at 2-Way with each other, which is normal.
- Exstart — the two routers have started the database description exchange and are negotiating which one is the master. This is where MTU trouble first appears, because it is where the first DBD packets are sent.
- Exchange — the routers are exchanging DBD packets that describe their link-state databases. They are still building a list of LSAs they need.
- Loading — the routers are sending Link State Requests (LSR) and Link State Updates (LSU) to fill in the LSAs they identified as missing.
- Full — the databases are synchronised. From now on, only incremental LSAs flow. This is the state where routes can be installed.
The operator reads the state with show ip ospf neighbor. The
output is the canonical evidence: every neighbour, its state
and its role on the segment, the dead timer remaining, the peer
address, the local interface, and the three retransmission
queue depths that say whether the exchange is progressing.
Hello, dead, and retransmit intervals
Three per-interface timers drive the OSPF adjacency on VyOS. All
three are configured under set protocols ospf interface, and
the defaults below are the ones VyOS documents for 1.5:
- Hello interval — how often the router sends a hello packet on that interface. Default 10 seconds, range 1 to 65535. The value must be the same on every router attached to the segment.
- Dead interval — how long the router waits without hearing a hello before it declares the neighbour down. Default 40 seconds, range 1 to 65535. It is also the value used for the Wait Timer during DR election. It must match on every router attached to the segment. The familiar “four times the hello” is a convention, not a derivation: on FRR it is an independent setting and nothing recalculates it when the hello interval changes.
- Retransmit interval — how long the router waits before retransmitting an unacknowledged DBD or LSR packet. Default 5 seconds. This one does not have to match the peer; it is a local retry policy.
configure
set protocols ospf interface eth0 hello-interval 5
set protocols ospf interface eth0 dead-interval 20
set protocols ospf interface eth0 retransmit-interval 5
commit
save
For sub-second hellos without inventing a value the peer has to
agree with, VyOS exposes set protocols ospf interface eth0 hello-multiplier, which sends between 1 and 10 hellos per
second. FRR advertises a hello interval of 0 in that mode and
stops checking the received hello interval, so the multiplier
does not have to match across the link. That is the one
documented exception to “the hello interval must match”.
What VyOS renders into FRR
VyOS does not implement OSPF. It renders an FRR configuration from the configuration tree and hands it to FRR. Knowing the mapping turns “the CLI accepted it but nothing happened” into a one-command check.
| VyOS command | FRR line it renders |
|---|---|
set protocols ospf interface eth0 area 0 | ip ospf area 0 under interface eth0 |
set protocols ospf area 0 network 10.0.0.0/24 | network 10.0.0.0/24 area 0 under router ospf |
set protocols ospf interface eth0 hello-interval 5 | ip ospf hello-interval 5 under interface eth0 |
set protocols ospf interface eth0 network broadcast | ip ospf network broadcast under interface eth0 |
set protocols ospf interface eth0 hello-multiplier 5 | ip ospf dead-interval minimal hello-multiplier 5 |
set protocols ospf area 0 authentication md5 | area 0 authentication message-digest under router ospf |
set protocols ospf interface eth0 authentication plaintext-password s3cret | ip ospf authentication plus ip ospf authentication-key s3cret |
Two things fall out of that table. First, VyOS offers two ways
to put an interface into an area — the interface node and the
area network statement — and they render to different FRR lines.
Use one of them consistently. Second, OSPF authentication is
split: the area node selects the type for the area, and the
password itself lives on the interface. Setting only the area
node authenticates nothing, because there is no key.
BGP session establishment
BGP forms a session differently. There is no periodic hello on every interface — BGP is a TCP session on port 179 between two configured peers, and the state machine in RFC 4271 is about acquiring and holding that TCP connection.
stateDiagram-v2
[*] --> Idle
Idle --> Connect: ConnectRetry started, TCP initiated
Connect --> OpenSent: TCP completed, OPEN sent
Connect --> Active: TCP attempt failed
Active --> OpenSent: TCP completed on retry, OPEN sent
Active --> Connect: ConnectRetry timer expires
OpenSent --> OpenConfirm: Valid OPEN received
OpenConfirm --> Established: KEEPALIVE received
Established --> Idle: NOTIFICATION or hold timer expiry
The six states:
- Idle — BGP is administratively down, has just been reset, or is backing off after an error. No connection is being attempted.
- Connect — the router has started the ConnectRetry timer and is waiting for its outbound TCP handshake to complete.
- Active — the previous TCP attempt did not complete, so the router has fallen back to listening for an inbound connection while it waits to retry. This is the state most often misread: Active does not mean the TCP session is up. A peer parked in Active is a peer whose TCP connection is not being made.
- OpenSent — TCP is up, the local router has sent its OPEN message, and it is waiting for the peer’s OPEN.
- OpenConfirm — the peer’s OPEN has been received and accepted, and the local router is waiting for the first KEEPALIVE (or a NOTIFICATION that rejects the session).
- Established — OPENs have been exchanged, the KEEPALIVE and hold-time contract is in force, and UPDATE messages can flow.
BGP has its own timers. VyOS documents the hold time default as 180 seconds; the keepalive is conventionally a third of it. The hold time is negotiated down to the lower of the two values offered in the OPEN messages, so configuring 30 on one side and leaving 180 on the other yields 30 on both. If no KEEPALIVE or UPDATE arrives within the negotiated hold time, the peer is declared down and the session collapses to Idle.
The third timer matters when a session will not come up at all.
set protocols bgp neighbor 192.0.2.2 timers connect 5 sets the
ConnectRetry interval — how long the router waits between TCP
attempts while it is stuck in Connect and Active. Shortening it
makes a stuck session cycle visibly rather than sit still.
The canonical VyOS 1.5 LTS configuration
OSPF on an Ethernet segment, using the interface node:
configure
set protocols ospf parameters router-id 10.255.0.1
set protocols ospf interface eth0 area 0
set protocols ospf interface eth0 network broadcast
set protocols ospf interface eth0 hello-interval 10
set protocols ospf interface eth0 dead-interval 40
set protocols ospf log-adjacency-changes detail
commit
save
log-adjacency-changes detail is the single most useful line in
that block for anyone who will later have to explain a flap.
Without detail, FRR logs only transitions to Full and
regressions from it; with it, every state transition is logged,
which is what turns “the adjacency was down at 03:14” into
“it went Full to Init at 03:14:07, which means hellos stopped”.
The area network statement is the alternative to the interface node, and renders a different FRR line:
configure
set protocols ospf parameters router-id 10.255.0.1
set protocols ospf area 0 network 10.0.0.0/24
commit
save
A BGP session to a single peer, on the 1.5 tree where the local
ASN lives under system-as and peers are top-level:
configure
set protocols bgp system-as 65001
set protocols bgp parameters router-id 10.255.0.1
set protocols bgp neighbor 10.0.0.2 remote-as 65002
set protocols bgp neighbor 10.0.0.2 description 'Transit peer, ticket 1842'
set protocols bgp neighbor 10.0.0.2 timers keepalive 60
set protocols bgp neighbor 10.0.0.2 timers holdtime 180
set protocols bgp neighbor 10.0.0.2 password 'bgpauth'
commit
save
The keepalive and hold time are separate leaves on VyOS; there
is no single command that takes both numbers. A per-neighbour
value overrides the process-wide set protocols bgp timers
equivalent.
The two configurations are very different in size, but they share the same property: before they do anything, they must bring up an adjacency (OSPF) or an Established session (BGP). If the relationship is not at its final state, no route flows, no failover happens, and the protocol is effectively off.
How the result is validated
The OSPF neighbour table is the first stop. FRR 10 prints the neighbour ID, priority, state and role, dead time, peer address, the interface with the local address appended, and three queue depths — retransmission, request, and database summary:
$ show ip ospf neighborNeighbor ID Pri State Dead Time Address Interface RXmtL RqstL DBsmL
10.255.0.2 1 Full/DR 38.365s 10.0.0.2 eth0:10.0.0.1 0 0 0
10.255.0.3 1 Full/Backup 39.175s 10.0.1.3 eth1:10.0.1.1 0 0 0Illustrative output
The interface view is where an interval mismatch becomes visible. Run it on both routers and compare one line:
$ show ip ospf interface eth0eth0 is up
ifindex 2, MTU 1500 bytes, BW 4294967295 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 10.255.0.1, Network Type BROADCAST, Cost: 10
Transmit Delay is 1 sec, State DR, Priority 1
Backup Designated Router (ID) 10.255.0.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 4.470s
Neighbor Count is 1, Adjacent neighbor count is 1Illustrative output
For BGP, the summary table carries the state in its last column. FRR prints a prefix count there once the session is Established and the state name while it is not:
$ show bgp summaryIPv4 Unicast Summary:
BGP router identifier 10.255.0.1, local AS number 65001 vrf-id 0
BGP table version 11
RIB entries 5, using 920 bytes of memory
Peers 2, using 41 KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
10.0.0.2 4 65002 148 159 0 0 0 02:16:01 12
10.0.0.3 4 65003 0 0 0 0 0 never Active
Total number of neighbors 2Illustrative output
The fully qualified form of that command is
show bgp ipv4 summary; the short form defaults to the IPv4
unicast address family. show bgp neighbors 10.0.0.2 is the
detail view, and it carries the last reset reason and the
negotiated hold time, which the summary does not.
Two filters on the summary are worth memorising before an incident, because they turn a hundred-line table into the answer:
show bgp summary failed
show bgp summary established
failed lists only the sessions that are not Established, which
on a route reflector with sixty peers is the difference between
reading a screen and reading a page.
What VyOS does not expose
Being explicit about the gaps is what keeps an operator from inventing a command under pressure:
- There is no OSPF-level MTU setting. The MTU that OSPF
cares about is the interface MTU, set with
set interfaces ethernet eth0 mtu 1500. VyOS offersset protocols ospf interface eth0 mtu-ignore, which disables the MTU check in the DBD exchange so the adjacency can reach Full despite a mismatch. It suppresses the symptom; the underlying mismatch is still there, and an LSU larger than the smaller MTU can still be dropped. - There is no per-neighbour hello interval. OSPF timers are per-interface, because they are properties of the segment.
show ip ospf neighborhas no reason column. When a neighbour is stuck, the reason lives in the FRR log, which is whylog-adjacency-changes detailis worth configuring before the incident rather than during it. Read it on VyOS withshow log frr, or narrow it withshow log protocol ospfandshow log protocol bgp— FRR runs under systemd here, so its output is in the journal rather than in/var/log/frr/.- There is no single
timerscommand for BGP. Keepalive and hold time are separate leaves, at the process level and again per neighbour.
How it fails
The production failure modes the engineer must recognise:
- Adjacency stuck in Init. Hellos are arriving from the peer
but the peer’s hello does not list the local router ID. The
local router is being heard by nobody. Common causes: the
return path for the hello is blocked (a firewall rule on the
local zone, or OSPF’s multicast destination filtered), the
peer does not have that interface in OSPF at all, or an NBMA
segment where the peer needs an explicit
set protocols ospf neighborstatement. - Adjacency stuck in 2-Way between two DROther routers. Normal. Only the DR and BDR form full adjacencies on a broadcast segment. Confirm with the role suffix in the state column before treating it as a fault.
- Adjacency stuck in Exstart or Exchange with a rising RXmtL.
The classic MTU mismatch. The DBD packets one side sends do
not fit the other side’s interface MTU, so they are never
acknowledged and are retransmitted every retransmit interval.
The two MTU values are in the
ifindexline ofshow ip ospf interfaceon each router. - Adjacency never leaves Down while hellos are clearly being sent. Authentication mismatch, area ID mismatch, or a network mask mismatch on a broadcast segment. All three cause the hello to be discarded on receipt, so the receiving router reports nothing at all rather than a partial state.
- Adjacency oscillates between Full and Init. Hellos are arriving intermittently. The cause is under OSPF, not in it: packet loss on the segment, a saturated control plane on either router, or an interface flap. A timer mismatch does not oscillate — it never forms in the first place.
- BGP stuck in Active. The TCP connection is not completing.
Common causes: a firewall rule blocking TCP 179 in one
direction, the wrong neighbour address, the peer not
configured with this router at all, a TCP MD5 password on one
side only, or an eBGP peer more than one hop away without
ebgp-multihop. - BGP reaching OpenSent and dropping back to Idle. The OPEN
was rejected. The usual reasons are an AS number that does not
match the configured
remote-as, a router ID collision, or a capability the peer refuses.show bgp neighbors 10.0.0.2names the NOTIFICATION code. - BGP flaps on hold-time expiry. KEEPALIVE messages are being lost, the hold timer fires, the session collapses, reconnects, and repeats. This is a transport problem — an MTU black hole, a congested link, or unidirectional loss — wearing a BGP costume.
Rollback
Adjacency configuration rolls back cleanly, because deleting the node removes the rendered FRR line at the next commit:
- Wrong interface area:
delete protocols ospf interface eth0 areathencommitandsave. The interface stops participating and the adjacency tears down. - Wrong area network statement:
delete protocols ospf area 0 network 10.0.0.0/24thencommitandsave. - Wrong BGP peer:
delete protocols bgp neighbor 10.0.0.2thencommitandsave. The session tears down and its routes are withdrawn. - Peer you want to keep but stop talking to right now:
set protocols bgp neighbor 10.0.0.2 shutdown. The configuration survives; the session does not. Reverse it with thedeleteform of the same command.
For a change on the router that carries your own access path,
commit-confirm 5 commits for five minutes and reverts unless
you type confirm. Know which revert you have configured
before you rely on it: the default action is reboot to the
saved configuration, and
set system config-management commit-confirm action reload
switches it to reloading the last completed configuration
without a reboot. On a router with no out-of-band console, that
difference is the difference between a 40-second outage and a
site visit.
Production discipline
Additional discipline:
-
Document the hello, dead, retransmit, keepalive and hold values for every protocol, every interface, and every peer. The operator who inherits the network can then sanity-check in seconds instead of reading two configurations side by side.
-
Turn on
set protocols ospf log-adjacency-changes detailbefore you need it. A flap you did not log is a flap you cannot explain. -
Authenticate every dynamic protocol the platform supports it on. OSPF needs both halves — the area selects the type and the interface carries the key:
configure set protocols ospf area 0 authentication md5 set protocols ospf interface eth0 authentication md5 key-id 1 md5-key 's3cret' set protocols bgp neighbor 10.0.0.2 password 'bgpsecret' commit saveThe BGP line is TCP MD5 and must be identical on both ends; a password on one side only leaves the peer stuck in Active, because the TCP handshake itself is rejected.
-
Run BFD on links where sub-second tear-down matters. BFD complements the OSPF dead interval and the BGP hold time rather than replacing them:
set protocols ospf interface eth0 bfdandset protocols bgp neighbor 10.0.0.2 bfd.
Cross-course references
The OSPF course’s XVIII-VyOS-OSPFFund covers the OSPF
neighbour state machine in depth. The BGP course’s
XXIII-VyOS-BGPFund and XXIV-VyOS-BGPSession cover the BGP
state machine and session establishment, and
XXIV-VyOS-BGPSession covers the timer leaves in detail. The
BFD part XXXII-VyOS-BFD covers sub-second detection. The
OPNsense course’s XXX-OPNsense-DynamicRouting covers the same
FRR-managed adjacencies from the BSD platform. The Linux
course’s XXII-Linux-NetTroubleshoot covers the host-side
neighbour table that sits below the protocol-layer adjacency.
Quiz
Knowledge check · 4 questions
Q1. An OSPF neighbour sits in `Init` state and never advances. The local router is receiving hellos from the peer. What does that state mean?
Q2. A BGP session in `Active` state means the TCP three-way handshake has completed and the two peers are negotiating OPEN parameters.
Q3. An OSPF adjacency between two VyOS 1.5 routers is stuck in Exstart. The hello and dead intervals are the defaults on both sides. The operator has confirmed the area IDs match, the network masks match, and the authentication matches. What is the most likely cause, how is it confirmed, and what are the two real fixes on VyOS?
Exstart is where the two routers begin exchanging database description packets. If the DBD one router sends does not fit the receiving interface MTU, the receiver drops it, nothing is acknowledged, and the sender retransmits every retransmit-interval seconds. The state machine never advances. The production shape is an MTU mismatch: one router has eth1 at 1500 while the transit between them, or the peer interface itself, is at 1400 because of a tunnel or a provider handoff.
Q4. A BGP session between two VyOS 1.5 routers flaps roughly every 90 seconds. `show bgp summary` shows the peer alternating between a prefix count and a state word. The peer answers ping, and a capture on TCP 179 shows the three-way handshake completing each time. Where should the operator look, and what should they not do?
The session reaches Established, so TCP, the OPEN exchange, the AS numbers and any MD5 password are all correct. It then collapses roughly every 90 seconds. With the default 180-second hold time a clean silence would take 180 seconds to be detected, so a 90-second cycle means the session is being torn down and rebuilt, not timing out once. Something is dropping the KEEPALIVE and UPDATE traffic in at least one direction.
Passing score: 75%. Answers are checked in this browser.