OSPF Micro-loops: Transient Loops During SPF Convergence
After a link fails, every router in the area floods the same LSAs and runs the same SPF. They agree on the answer. They just don't reach it at the same moment, and for those few milliseconds traffic can loop.
Five Steps, Five Clocks
Every router walks the same five steps after a topology change. A micro-loop forms whenever two adjacent routers are on different sides of step 5 at the same time.
- Detect the event: loss of light, BFD timeout, or dead-interval expiry. Only routers attached to the failure learn locally; everyone else learns through flooding.
- Originate a new Router LSA (Type 1), plus a Network LSA (Type 2) if a DR is involved. Gated by
timers throttle lsa. - Flood hop by hop. Each hop adds receive processing,
timers lsa arrivalchecks and flood pacing. A router five hops away hears later than a direct neighbour. - Run SPF, gated by
timers throttle spf(initial wait / hold / max wait). Run time grows with LSDB size. - Update RIB, then FIB. Often the longest and least predictable step: thousands of prefixes, distributed CEF, line-card and TCAM programming.
| Skew source | Typical spread | Why it differs per router |
|---|---|---|
| Detection | 0 ms to 40 s | Only attached routers detect locally; BFD vs hello timers |
| Flooding distance | ~1–30 ms per hop | Hops from the originator, pacing timers, CPU load |
| SPF initial wait | 0–5000 ms | Mismatched throttle timers or platform defaults |
| SPF run time | 1–100+ ms | LSDB size, CPU generation |
| RIB/FIB programming | 10 ms to seconds | Prefix count, distributed vs centralised forwarding, ASIC |
These are typical orders of magnitude, not measurements. Measure your own with the commands in section 04.
Worked Example: One Failure, Two Loops
Four routers in a ring, all in Area 0. The prefix 10.3.3.0/24 is attached to R3. The R2–R3 link fails.
Shortest paths before and after
| Router | Next-hop before | Cost | Next-hop after | Cost |
|---|---|---|---|---|
| R2 | R3 (direct) | 10 | R1 | 60 (R1–R4–R3) |
| R1 | R2 | 20 | R4 | 50 (R4–R3) |
| R4 | R1 | 30 | R3 (direct) | 40 |
R2 used to be downstream of R1; now R1 is downstream of R2. R1 used to be downstream of R4; now R4 is downstream of R1. Any pair that reverses direction can loop if the new downstream router updates first.
Timeline
Illustrative, with BFD detection and timers throttle spf 50 200 5000 on all routers. Times are from R2's detection; R1 and R4 differ only in flooding distance and FIB speed.
| Time | Event | R2 → | R1 → | R4 → | Traffic from R1 |
|---|---|---|---|---|---|
| 0 ms | R2, R3 detect loss and originate LSAs | R3 (dead) | R2 | R1 | Dropped at R2 |
| ~80 ms | R2 SPF done, FIB updated | R1 | R2 | R1 | Loop R1 ↔ R2 |
| ~150 ms | R1 SPF done, FIB updated | R1 | R4 | R1 | Loop R1 ↔ R4 |
| ~250 ms | R4 gets the LSA two hops later, FIB updated | R1 | R4 | R3 | Delivered via R4–R3 |
While looping, each packet circulates until TTL reaches zero. The routers generate a burst of ICMP time-exceeded, and the looping link's utilisation spikes, which can delay unrelated traffic on R1–R2 and R1–R4.
The Cross-Point Case
A micro-loop needs one condition: X forwards to Y for a prefix while Y forwards to X for the same prefix. That crossing point is always a pair of routers whose next-hops reverse between the old and new SPF trees. It lasts exactly as long as the gap between their two FIB updates.
Predicting the cross-points
- Compute the SPF tree toward the destination before the change, and again after it.
- List every link whose direction of use flips (X→Y before, Y→X after).
- Each flipped link is a candidate. If the new downstream router is likely to converge first (closer to the failure, fewer prefixes, faster hardware), expect a loop there.
In the example both R1–R2 and R1–R4 flip, so both loop. R3–R4 does not flip; it simply starts carrying traffic, so it never loops.
| Local micro-loop | Remote micro-loop | |
|---|---|---|
| Where | Next to the failure, involving the point of local repair (R2) | Between routers that never saw the failure (R1–R4) |
| Cause | The repairing router updates before its upstream neighbour | Flooding distance and FIB speed differ between two remote routers |
| LFA / rLFA | Masks it while the repair path is in use | No effect |
| Local delay (RFC 8333) | Removes it | No effect |
| SR micro-loop avoidance | Removes it | Removes it |
max-metric router-lsa, not hard shut / no shut.
Detection and Reporting
You prove a micro-loop by lining up three things on one NTP-synchronised clock: when each router ran SPF, when each FIB entry changed, and when traffic saw TTL expiry or loss. Without millisecond timestamps, the evidence can't be correlated.
service timestamps log datetime msec localtime show-timezone service timestamps debug datetime msec localtime show-timezone ntp server 10.0.0.1 ! router ospf 1 log-adjacency-changes detail
| Command | What it shows |
|---|---|
show ip ospf | include throttle|SPF|LSA | Throttle and arrival timers; compare across every router |
show ip ospf statistics | SPF log: when each SPF ran, how long, what triggered it |
show ip ospf database router <id> | LS age and sequence; when the change reached this router |
show ip route 10.3.3.0 | Current next-hop and "last update" |
show ip cef 10.3.3.0 detail | What the forwarding plane is actually using |
show ip traffic | ICMP time-exceeded counters; a jump after an event points to a loop |
debug ip ospf spf statistic | Per-SPF timing in the log (lab only) |
Data-plane evidence
- A continuous fast ping or IP SLA UDP jitter probe across the failure. Lost packets × interval = total outage; subtract detection and SPF time and the rest is mostly micro-loop.
- A traceroute started during convergence shows the same two hops repeating: R1, R2, R1, R2…
- A capture on the cross-point link shows identical packets with TTL dropping by 2 on each pass.
Incident report template
| Field | What to record |
|---|---|
| Trigger | Link or router, time in ms, cause (failure, restore, metric change) |
| Detection | Method and time on each attached router |
| LSA origination / arrival | Originator log, LS age on each router |
| SPF | Start and duration per router |
| FIB update | Time per router from CEF / route "last update" |
| Predicted cross-points | Links whose direction flipped |
| Observed loop | Routers, start, end, duration |
| Impact | Packets lost, TTL-expired counts, prefixes and services hit |
| Root cause of skew | Timers, prefix count, platform, flooding distance |
| Remediation | Timers, BFD, prefix priority, FRR, SR micro-loop avoidance |
Mitigation
Faster, more uniform convergence shrinks micro-loops everywhere. Only ordered or explicitly steered convergence removes them.
| Technique | Local | Remote | Notes |
|---|---|---|---|
| Identical SPF/LSA throttle (RFC 8405) | Shrinks | Shrinks | Cheapest win; mismatched timers cause the longest loops |
| BFD on core links | Shrinks | Shrinks | Both ends of a link detect near-simultaneously |
| Prefix prioritisation | Shrinks | Shrinks | Loopbacks and BGP next-hops fixed first |
| LFA / remote LFA | Masks | No | Protects the failure point only |
| Local delay (RFC 8333) | Removes | No | Repairing router holds its FRR path, delays its own FIB update |
| Ordered FIB (RFC 6976) | Removes | Removes | Standardised, rarely deployed |
| SR micro-loop avoidance + TI-LFA | Removes | Removes | Loop-free SR path for a set delay, then the normal path |
| max-metric / gradual cost | Avoids | Avoids | Planned changes only |
router ospf 1 timers throttle spf 50 200 5000 timers throttle lsa 0 20 5000 timers lsa arrival 15 timers pacing flood 15 bfd all-interfaces fast-reroute per-prefix enable area 0 prefix-priority low fast-reroute per-prefix remote-lfa area 0 tunnel mpls-ldp ! interface GigabitEthernet0/1 bfd interval 50 min_rx 50 multiplier 3 carrier-delay msec 0
timers lsa arrival must be lower than the neighbours' LSA throttle hold, or repeated LSAs are dropped. Remote LFA needs LDP on the core links.
router ospf 1 segment-routing mpls microloop avoidance segment-routing microloop avoidance rib-update-delay 3000 area 0 interface GigabitEthernet0/0/0/0 fast-reroute per-prefix fast-reroute per-prefix ti-lfa enable
The RIB update delay is how long the router uses the temporary SR path before installing the normal path. It must exceed the worst-case convergence time in the area.
max-metric router-lsa, let traffic drain, do the work, then remove it. Traffic moves away and back in one controlled step each way. Check exact syntax against your software release; options differ between IOS, IOS-XE and IOS-XR.
Lab Exercise
- Pick four core routers that form a ring, set costs 10 / 10 / 40 / 10 as above, and advertise a loopback (10.3.3.1/32) on "R3".
- Mismatch timers on purpose: leave "R4" at
timers throttle spf 5000 10000 10000, the rest at50 200 5000. - Start a fast ping from behind "R1" to 10.3.3.1 and a capture on the R1–R4 link.
- Shut R2–R3. Record lost packets, TTL-exceeded counters and
show ip ospf statisticson all four. - Fill in the report template. The R1–R4 loop should last roughly R4's SPF initial wait.
- Align timers, add BFD, repeat. Then bring the link back up and measure the restoration loop separately.
- If the image supports it, enable SR with TI-LFA and micro-loop avoidance, and repeat.
CCIE Exam Takeaway
Micro-loop = X already points to Y, Y still points to X
Duration = gap between their two FIB updates
- "Same LSDB, same SPF result, different moment."
- "A cross-point is any link whose direction of use flips between the old and new tree."
- "LFA fixes the local loop; only ordered or SR-steered convergence fixes the remote one."
- "Link-state only: RIP loops differently, and EIGRP's DUAL never loops."
References
- RFC 5715: A Framework for Loop-Free Convergence
- RFC 6976: Framework for Loop-Free Convergence Using the Ordered FIB Approach
- RFC 8333: Micro-loop Prevention by Introducing a Local Convergence Delay
- RFC 8405: SPF Back-Off Delay Algorithm for Link-State IGPs