Skip to main content
RunBook Academy

← All break/fix scenarios in VyOS

advancedvyos-ospf~30 min

OSPF Neighbours Stuck in EXSTART/EXCHANGE

Reported symptoms

  • The area 0 adjacency between rtr-core-1 and rtr-dc-2 never reaches Full, and reports a different state almost every time it is polled - EXSTART at 09:12, EXCHANGE at 09:13, EXSTART again at 09:15
  • A second adjacency on the same physical circuit, in a stub area, has been Full for eighteen months and has not moved
  • The DC-hosted ERP is reachable and slow rather than broken, because a floating static route over the internet IPsec tunnel is carrying the traffic the IGP used to carry
  • SSH sessions from HQ to hosts on the DR management network connect, print the banner, and then hang the moment a command produces more than a screen of output
  • The nightly configuration archive job, which copies files to the DR site, has failed on each of the three nights since the maintenance window
  • Neither router has been committed to in five weeks; the only change in the estate was the carrier cutting the site-to-site circuit over from dark fibre to a managed Ethernet service, signed off as a like-for-like replacement

Evidence

  • · `show ip ospf neighbor` shows the rtr-dc-2 adjacency in EXSTART or EXCHANGE depending on when it is run, and the rtr-dr-3 adjacency in Full
  • · `show ip ospf neighbor detail` reports Interface MTU 1500 for the local side and 1500 for the neighbour, so the two routers agree and the protocol MTU check is not what is rejecting the packets
  • · `show ip ospf interface eth1.30` confirms MTU 1500 locally, and the same command on rtr-dc-2 confirms MTU 1500 there
  • · A default-size ping across the circuit succeeds with zero loss in both directions, which is what the maintenance hand-back test measured
  • · `ping -M do -s 1472 198.51.100.6` produces no reply at all - not an ICMP Fragmentation Needed message, just silence - while `ping -M do -s 1414` succeeds, putting the usable path MTU at 1442 bytes
  • · `ping -M dont -s 1472 198.51.100.6` also produces no reply, which rules out the ordinary PMTUD black hole where clearing the DF bit lets a router fragment the packet
  • · Simultaneous `tcpdump -ni eth1.30 proto ospf` on both routers shows Hello packets and the small initial Database Description packets crossing in both directions, and the large Database Description packets leaving rtr-core-1 and never arriving at rtr-dc-2
  • · `show interfaces ethernet eth1` on both routers shows no input or output errors and no drops, because the frames are being discarded by a device that is not on either router
  • · `show system commit` shows the last commit on either router was five weeks ago; the change record for the weekend shows the circuit cutover and a hand-back test consisting of an interface check and a default-size ping
Diagnosis and resolutionclick to reveal

Root cause

The managed Ethernet circuit that replaced the dark fibre delivers a usable MTU of 1442 bytes rather than 1500, because the carrier encapsulates the customer frame for transport across their network. Both routers still believe the link carries 1500 bytes, and nothing tells them otherwise: the bottleneck is a layer-2 device with no IP identity in the path, so it discards the oversized frame silently and never generates the ICMP Fragmentation Needed message that Path MTU Discovery depends on. Every symptom follows from that one fact. OSPF Hellos are small and cross, so the neighbours find each other and reach 2-Way. The initial Database Description packets that negotiate the master and slave roles are effectively empty and also cross, so the adjacency reaches EXSTART. The Database Description packets that carry the LSA headers are filled to the interface MTU, so on the backbone area they are close to 1500 bytes and are discarded in transit; the exchange cannot complete, the sequence number never advances, and the adjacency drops back to EXSTART to renegotiate and tries again. That loop is why the state is different every time it is polled: EXSTART and EXCHANGE are the same failure caught at two points in one cycle. The second adjacency on the same circuit survives because it is in a stub area whose LSDB holds a few dozen LSAs rather than several hundred, so its Database Description packets are a few hundred bytes and fit. And the data-plane symptoms - SSH sessions that hang once output grows, an archive job that fails - are the same 1442-byte ceiling seen by TCP, which negotiated its segment size from a 1500-byte MTU that no longer exists.

Remediation

Measure the number before changing anything, because the whole remediation is derived from it: a binary search with `ping -M do -s` between the two router interfaces gives the largest payload that crosses, and the path MTU is that value plus 28. Record it in the ticket and in the circuit record. Then decide who owns the fix. The correct fix is the carrier raising the circuit MTU so that a 1500-byte customer frame survives transport, which most carriers can provision and which restores the estate to the MTU it was designed around; raise it as a fault against the circuit with the measured number attached, because a fault report that says the link is broken will be closed and one that says the circuit delivers 1442 bytes will not. Lowering the MTU on both sub-interfaces to the measured value is the fix you own, it works, and it has a cost worth stating plainly: everything crossing that link is now limited to 1442 bytes, and you have accepted a carrier limitation as a permanent property of your network. It also has a benefit that is easy to miss, which is that a router with a smaller interface MTU is an IP hop that will generate ICMP Fragmentation Needed, converting a silent layer-2 black hole into a visible bottleneck that Path MTU Discovery can act on. Change both sides inside one window: an MTU lowered on one side only recreates the classic mismatch, where the protocol MTU check rejects the neighbour Database Description packet and the adjacency sticks in EXSTART for a different reason. Add MSS clamping on the interface so TCP is not relying on ICMP that may be filtered elsewhere. Remove the `mtu-ignore` that was applied during triage: it changed nothing here because it suppresses the protocol MTU check rather than making a packet fit, and leaving it behind disables a check you will want the next time the two ends genuinely disagree. Holding is defensible if the carrier can be pushed to fix the circuit inside a few hours, since the IGP failure is already being absorbed by the backup path and the visible cost is latency rather than an outage; a hold needs an owner, an end time, and a note to the server and backup teams so that the two tickets they are working stop being investigated as separate faults.

Verification

The adjacency must be Full and must stay Full for longer than the dead interval, checked twice with `show ip ospf neighbor` several minutes apart, because an adjacency caught between two resets can look healthy for a moment. `show ip ospf database` on both routers must show the same LSAs; a Full adjacency with a divergent LSDB means the exchange completed but flooding is still losing packets. Re-run the ping ladder afterwards, and read the failure mode rather than the pass: after the interface MTU is lowered, an oversized probe should come back as an ICMP Fragmentation Needed message naming the new MTU rather than disappearing into silence, and that change from silence to a named error is the evidence that the black hole is gone. Prove the data plane from a client rather than from the router: an SSH session to a DR host that produces a long output, and a run of the archive job that copies a real file rather than a test byte. Confirm the routing has returned to the IGP path with `show ip route` showing the DC prefixes learned by OSPF rather than the floating static, because the ERP being fast again is the symptom the business reported. Read the interface counters on both routers for errors introduced by the MTU change. If the carrier raised the circuit MTU instead, verify their claim with the same ping ladder rather than with their ticket update, and only then revert any local MTU reduction.

Prevention

Path MTU belongs in the acceptance test for every circuit hand-off. A like-for-like replacement is a claim made by a supplier, and the test that was actually run - interface up, default-size ping, no errors - measures almost nothing, since a 56-byte packet crosses a badly degraded path happily. The `ping -M do -s` ladder takes a minute, produces a number, and that number belongs in the circuit record next to the bandwidth so the next engineer inherits it rather than rediscovering it. Monitor OSPF neighbour state as a series and alert on any adjacency that is not Full for longer than a couple of polling intervals; the course covers the FRR JSON output that makes this a few lines of scripting, and it converts a Monday-morning three-team investigation into a notification on Saturday night while the change window is still open and the carrier engineer is still on the bridge. Treat MSS clamping as standard on any link whose MTU is not provably 1500 end to end, rather than as something applied to one tunnel years ago by someone who had learned this the hard way and never generalised it. And ban `mtu-ignore` as a reflex response to EXSTART. It is the right tool when the two ends must run different MTUs and you have independently established that no packet larger than the smaller one needs the link; used as a first move it hides the measurement that would have told you which of the two very different MTU failures you are looking at.

Reported symptoms

Three teams are working three tickets, and none of them has mentioned the others.

The server team has a ticket from an engineer who cannot get a useful SSH session to any host on the DR management network. The session connects. The banner prints. The prompt appears. Then the first command that produces more than a screen of output hangs and never returns. Smaller commands are fine. The engineer has tried three hosts and two jump boxes and concluded the DR site has a problem.

The backup team has a ticket that the nightly configuration archive to the DR site has failed on each of the last three nights. The job connects, transfers something, and stalls. It was fine on Wednesday.

The network team has a ticket that the DC-hosted ERP is slow. Not down. Slow. Users can work; page loads take several seconds instead of under one. Someone has already established that the traffic is crossing the internet IPsec tunnel rather than the site-to-site circuit, which explains the latency, and has filed it as a routing question.

The routing question turns out to be the interesting one. The area 0 adjacency between rtr-core-1 and rtr-dc-2 is not Full. It is also not consistently anything else:

  • 09:12 — show ip ospf neighbor reports EXSTART.
  • 09:13 — the same command reports EXCHANGE.
  • 09:15 — EXSTART again.

The second adjacency on the same physical circuit, to rtr-dr-3, has been Full for eighteen months and has not moved during any of this.

Neither router has been committed to in five weeks. The only change anywhere near this is the carrier work over the weekend, which replaced the dark fibre between the two sites with a managed Ethernet service. The window closed at 03:40 on Saturday. The hand-back test was an interface check and a ping, both of which passed, and the change was signed off as a like-for-like replacement.

The carrier portal shows the circuit up with no errors, and their first line will not escalate a circuit that is up.

The estate

rtr-core-1 is a VyOS 1.5 LTS router at the HQ campus. eth1 faces the site-to-site circuit as a trunk carrying two VLANs:

  • eth1.30, 198.51.100.5/30, to rtr-dc-2 at 198.51.100.6. This is area 0 — the backbone, several hundred LSAs, and the path the DC prefixes are learned over.
  • eth1.31, 198.51.100.9/30, to rtr-dr-3 at 198.51.100.10. This is area 3, configured as a stub, holding the DR management network and a few dozen LSAs.

Router IDs are 192.0.2.1, 192.0.2.2 and 192.0.2.3. Every interface in the estate is MTU 1500 and has been since it was built.

There is a floating static route to the DC prefixes over an internet IPsec tunnel, with an administrative distance high enough that it only takes effect when OSPF has nothing to offer. That tunnel has MSS clamping configured on it. Nobody currently on the team knows who added the clamping or why; it was there when they arrived.

Evidence provided

Read-only / Safesame circuit, two adjacencies, one of them fine
vyos@rtr-core-1:~$ show ip ospf neighbor
Neighbor ID     Pri State           Dead Time Address         Interface
192.0.2.2         1 ExStart/DROther   38.402s 198.51.100.6    eth1.30
192.0.2.3         1 Full/DROther      37.911s 198.51.100.10   eth1.31

Illustrative output

Read-only / Safethe two ends agree on 1500 - the MTU check is not rejecting anything
vyos@rtr-core-1:~$ show ip ospf neighbor detail
Neighbor 192.0.2.2, interface address 198.51.100.6
In the area 0.0.0.0 via interface eth1.30
Neighbor priority is 1, State is ExStart, 47 state changes
Interface MTU 1500, Neighbor Interface MTU 1500
Database Summary List 0
Link State Request List 0

Illustrative output

Read-only / Safesilence - not an ICMP Fragmentation Needed message
vyos@rtr-core-1:~$ ping -M do -s 1472 -c 3 198.51.100.6
PING 198.51.100.6 (198.51.100.6) 1472(1500) bytes of data.

--- 198.51.100.6 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2043ms

Illustrative output

Read-only / Safethe largest payload that crosses, after a binary search
vyos@rtr-core-1:~$ ping -M do -s 1414 -c 3 198.51.100.6
PING 198.51.100.6 (198.51.100.6) 1414(1442) bytes of data.
1422 bytes from 198.51.100.6: icmp_seq=1 ttl=64 time=1.11 ms

--- 198.51.100.6 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms

Illustrative output

Read-only / Safethe small ones are answered, the large ones are retransmitted
vyos@rtr-core-1:~$ tcpdump -ni eth1.30 proto ospf
09:31:02.114 IP 198.51.100.5 > 224.0.0.5: OSPFv2, Hello, length 48
09:31:02.219 IP 198.51.100.6 > 224.0.0.5: OSPFv2, Hello, length 48
09:31:04.882 IP 198.51.100.5 > 198.51.100.6: OSPFv2, Database Description, length 32
09:31:04.901 IP 198.51.100.6 > 198.51.100.5: OSPFv2, Database Description, length 32
09:31:05.117 IP 198.51.100.5 > 198.51.100.6: OSPFv2, Database Description, length 1452
09:31:10.118 IP 198.51.100.5 > 198.51.100.6: OSPFv2, Database Description, length 1452

Illustrative output

The same capture running on rtr-dc-2 at the same moment shows the Hellos and the 32-byte Database Description packets arriving, and no sign of the 1452-byte ones.

Work the evidence before reading on

Nothing on either router is misconfigured, and both routers agree about everything they can see.

  1. show ip ospf neighbor detail reports the same Interface MTU on both sides. That single line eliminates the failure everyone reaches for first. What class of MTU problem is left when both ends agree?
  2. The adjacency is EXSTART sometimes and EXCHANGE at others. Ask what is different about the packets sent in each of those states, rather than what is different about the states.
  3. The second adjacency on the same wire is Full. What property of an area — not of a link — decides how large a Database Description packet is?
  4. ping -M do gets silence rather than an ICMP Fragmentation Needed message, and ping -M dont fails too. The standard PMTUD black hole is a router that drops the packet and has its ICMP filtered. What kind of device drops an oversized frame and could not send ICMP even if nobody filtered it?
  5. Three tickets: an adjacency that will not form, SSH sessions that hang once output grows, and a file-copy job that stalls. What single quantity, if it were smaller than everyone believes, produces all three?

Before continuing: both routers say 1500, and one of them is describing a link that no longer exists.

Root cause

1. The circuit is not what it replaced

The managed Ethernet service carries the customer frame inside the carrier network, and that encapsulation costs bytes. The circuit delivers 1442 usable bytes. The dark fibre it replaced delivered 1500. Nothing in the hand-back test measured the difference, because the only packets it sent were small.

The routers were not told and cannot infer it. Both still claim MTU 1500 in their configuration, in show ip ospf interface, and in the Interface MTU field of every Database Description packet they send. Their agreement is genuine and completely irrelevant: they agree about a link neither of them can measure.

2. EXSTART and EXCHANGE are one failure caught twice

The OSPF adjacency states are not arbitrary; each one sends a different size of packet.

  • Hellos are tens of bytes. They cross. The neighbours find each other and reach 2-Way.
  • The Database Description packets that negotiate master and slave are effectively empty, around 32 bytes. They cross, so the adjacency reaches EXSTART and gets past it.
  • The Database Description packets that follow carry the LSA headers, twenty bytes each, and are filled up to the interface MTU. On the backbone, with several hundred LSAs, that means packets close to 1500 bytes.

Those are the packets the circuit discards. The exchange cannot complete, the sequence number never advances, and the adjacency resets and starts again. Poll it during the negotiation and it reads EXSTART; poll it during the doomed exchange and it reads EXCHANGE. The oscillation is not a second symptom to explain. It is the retry loop.

3. The stub area is the control experiment

rtr-dr-3 sits on the same physical circuit and is Full, which is the fact that makes the circuit look innocent.

It is in a stub area. A stub area does not carry the external LSAs that dominate a backbone LSDB, so its database is a few dozen entries rather than several hundred. Its Database Description packets are a few hundred bytes, and a few hundred bytes fit inside 1442.

That adjacency is not evidence that the circuit is healthy. It is evidence that the failure threshold is somewhere between the size of a stub area database and the size of the backbone one — which is a statement about the circuit, and one that would have been read that way by anyone who knew both areas were crossing the same wire.

4. The data-plane tickets are the same number

TCP endpoints on both sides derived their maximum segment size from their own 1500-byte interfaces. An SSH server sending a page of output fills a segment, the resulting packet exceeds 1442 bytes, and the circuit discards it. The session does not reset; it hangs, because TCP retransmits a segment that will never fit. The archive job stalls for the same reason on its first large write.

The ERP is slow rather than broken because OSPF failing on this path let the floating static route take over, and the IPsec tunnel it points at has MSS clamping configured. Somebody solved this problem once, on one interface, and the fix stayed where they put it.

Resolution

  1. Measure before you change anything. Binary-search the payload with ping -M do -s between the two router interfaces until you have the largest size that crosses. Path MTU is that payload plus 28. Everything below is derived from this number, and a fix applied without it is a guess.
  2. Put the number in the ticket and in the circuit record. A carrier fault that says the link is broken gets closed as no fault found; one that says the circuit delivers 1442 bytes where 1500 was ordered does not.
  3. Raise the fault with the carrier in parallel with anything you do locally. Raising the circuit MTU so a 1500-byte customer frame survives transport is the fix that restores the estate to the MTU it was designed around, and it is theirs to make.
  4. Decide explicitly whether to hold. The IGP failure is already being absorbed by the backup path, so the visible cost is latency rather than an outage, and waiting a few hours for the carrier is defensible. A hold needs an owner, an end time, and a message to the server and backup teams so they stop investigating their tickets as separate faults.
  5. If you are fixing it locally, lower the interface MTU on both sub-interfaces to the measured value, in one window. set interfaces ethernet eth1 vif 30 mtu 1442 on each end. One side alone recreates the classic mismatch and sticks the adjacency in EXSTART for a different reason.
  6. Understand what you have bought. Everything crossing that link is now limited to 1442 bytes. In exchange, the routers become IP hops with a smaller MTU, which means they generate ICMP Fragmentation Needed and turn a silent layer-2 black hole into a bottleneck that Path MTU Discovery can actually see.
  7. Add MSS clamping on the interface with the ip adjust-mss node so TCP does not depend on ICMP that some firewall between here and the far end may be dropping. Set it to the path MTU minus 40.
  8. Remove the triage mtu-ignore. It changed nothing here, and leaving it behind disables the check you will want the next time two ends genuinely disagree.
  9. Use compare to read the diff and commit-confirm to commit it. This is an MTU change on the interface carrying the IGP; if the number is wrong you want the router to undo it without you.

Verification

  1. The adjacency is Full and stays Full. Check show ip ospf neighbor twice, several minutes apart and longer than the dead interval. An adjacency caught between two resets looks healthy for a moment.
  2. The databases agree. show ip ospf database on both routers shows the same LSAs. A Full adjacency with a divergent LSDB means the exchange completed and flooding is still losing packets, which is the same cause not yet fully fixed.
  3. The failure mode of the ping has changed, not just its result. An oversized probe should now return an ICMP Fragmentation Needed message naming the new MTU instead of vanishing. Silence becoming a named error is the evidence that the black hole is gone.
  4. The data plane is proven from a client, not from the router. Open an SSH session to a DR host and run something with a long output. Run the archive job against a real file rather than a test byte.
  5. The routing has returned to the IGP. show ip route shows the DC prefixes learned by OSPF rather than via the floating static. The ERP being fast again is the symptom the business actually reported.
  6. Interface counters on both routers show no errors introduced by the change, read after the link has carried real traffic for a while rather than immediately after commit.
  7. If the carrier raised the circuit MTU instead, their claim is verified with your own ping ladder and not with their ticket update - and only then is any local MTU reduction reverted.

Prevention

  • Make path MTU an acceptance test for every circuit hand-off. The test that was run here — interface up, ping succeeds, no errors — measures almost nothing, because a 56-byte packet crosses a badly degraded path happily. The ping -M do -s ladder takes a minute and produces a number. That number belongs in the circuit record beside the bandwidth, so the next engineer inherits it instead of rediscovering it at 09:00 on a Monday.
  • Treat “like-for-like” as a supplier claim, not a measurement. It was true about the endpoints, the media and the bandwidth. It was false about the only property that mattered, and nobody involved was lying.
  • Alert on OSPF neighbour state. Any adjacency not Full for more than a couple of polling intervals deserves a notification. The course covers reading FRR JSON output, which makes this a few lines of scripting; it would have fired on Saturday night while the window was open and the carrier engineer was still on the bridge, instead of surfacing on Monday as three tickets in three queues.
  • Clamp MSS on any link whose MTU is not provably 1500 end to end. The estate already contained this fix on one tunnel. Fixes that live on one interface because one person once had a bad afternoon are not controls.
  • Do not reach for mtu-ignore first. It is the right tool when two ends must run different MTUs and you have independently established that nothing larger than the smaller one needs the link. Used as a reflex it skips the measurement that tells you which of the two MTU failures you have.