ospf-troubleshooting
OSPF adjacency, LSDB, area types, authentication, route filtering, and redistribution — symptom-first decision trees with lookup tables
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
OSPF adjacency, LSDB, area types, authentication, route filtering, and redistribution — symptom-first decision trees with lookup tables
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
BGP session state, missing routes, prefix policy, default-originate, next-hop-self, route reflector — decision trees and checklists
SLA path failure workflow — read sla_paths.json, traceroute-first localization, ECMP handling, protocol triage
Cross-protocol redistribution (OSPF↔EIGRP) — seed metrics, subnets keyword, loop risk, route-map filtering
Path selection investigation — PBR, route-map and prefix-list policy influence, ECMP behavior, routing table verification
| name | OSPF Troubleshooting |
| description | OSPF adjacency, LSDB, area types, authentication, route filtering, and redistribution — symptom-first decision trees with lookup tables |
PREREQUISITE: Before using this skill, you MUST have already run
get_interfaces(device)andget_ospf(device, "neighbors")on the target device. If neighbors are missing or fewer than expected, go directly to the Adjacency Checklist below — do not read the full skill from the top. If all neighbors are FULL and all interfaces Up/Up, proceed with the relevant symptom section.
OSPF adjacency, LSDB, area types, authentication, route filtering, redistribution receipt. Covers C1C, C2C, E1C, E2C (Area 0), A1C, A2C (Area 1 stub).
Defaults: Hello 10s · Dead 40s (broadcast/P2P) | Hello 30s · Dead 120s (NBMA/P2MP) · AD 110 · Reference BW 100 Mbps
When an OSPF neighbor is not FULL or missing entirely:
get_ospf(device, "neighbors")
| State | Root Cause |
|---|---|
| FULL | Healthy |
| EXSTART / EXCHANGE | MTU mismatch (most common) or duplicate Router ID. MTU: get_interfaces(device) on both sides — compare MTU. Router ID: if MTU matches, run get_ospf(device, "details") on both sides and compare Router IDs — a duplicate RID causes the DD master/slave election to deadlock permanently. |
| LOADING | LSA requests pending — retransmission failing (lossy link, CRC errors, congestion) or the requested LSA was prematurely aged out (MaxAge) before delivery. RFC 2328 defines no Loading-state timeout — a stuck Loading neighbor persists indefinitely. Check interface errors; if none, advise operator to clear ip ospf process on the stuck side. |
| INIT | Hello one-way (my RID not in their Hello): asymmetric link, ingress ACL blocking 224.0.0.5/224.0.0.6, or auth mismatch on one side |
| 2WAY | DR/BDR election only (non-DR/BDR on broadcast) — normal for non-DR routers |
| DOWN | No hellos received: interface down, passive interface, or wrong area |
| Query | What it returns | Use when |
|---|---|---|
neighbors | Neighbor state, router-id, interface | Checking adjacency health |
interfaces | Timer values, auth type, passive flag, area, network type, cost | Verifying adjacency parameters (timers, auth, passive, area) |
config | Process-level config (area definitions, redistribution, network statements) | Checking OSPF process config (area types, redistribution, network statements). |
database | LSDB contents (LSA types, ages, router-ids) | Investigating missing routes |
details | Process-level details (SPF stats, router-id, ABR/ASBR role) | Checking NSSA translation, SPF timers |
Verify these items on each side in order. Most use get_ospf(device, "interfaces") — items that require a different query note this explicitly. Stop at the first mismatch — fix it first, then re-verify.
get_ospf(device, "interfaces") on each side and compare them.
Mismatch → root cause found, stop here.
Standard defaults (broadcast/point-to-point): hello=10, dead=40. NBMA/point-to-multipoint: hello=30, dead=120. Any other dead interval (e.g. 7) is non-standard.
Fix direction: restore the device with non-standard values to defaults — never change
correctly-configured devices to match a misconfigured outlier.get_ospf(device, "config") — look for area X nssa, area X stub. Mismatched type → adjacency rejected (NSSA sets N-bit in Hello options; normal sets E-bit — mismatch = hellos silently dropped) (RFC 3101 §2.3).passive-interface disables hellos)get_interfaces(device) on both sides — compare MTU values. OSPF includes interface MTU in DBD packets (RFC 2328 §10.6); if the received MTU exceeds the local interface MTU, the DBD is rejected and the adjacency stalls in EXSTART/EXCHANGE. The lower-MTU side logs "Nbr X has larger interface MTU".ip ospf mtu-ignore — it masks the symptom and can cause oversized OSPF packets to be dropped in transit.get_ospf(device, "details") on both sides and compare Router IDs. A duplicate RID (two routers with the same Router ID) causes DD master/slave election in ExStart to deadlock permanently — the adjacency never leaves ExStart. Fix the misconfigured device; the correct RID is typically the Loopback0 address. Note: this check uses details, not interfaces.When a route should be in the RIB but isn't:
get_ospf(device, "database")
get_routing(device, prefix="<expected-prefix>")
After running the two queries above, branch on the result:
Is the expected LSA present in the LSDB? (get_ospf(device, "database"))
| LSDB Result | RIB Result | Diagnosis Path |
|---|---|---|
| LSA present | Route absent from RIB | Filtering or forwarding problem on this device — check Distribute-List Filtering below. For Type 5/7 LSAs, also check forwarding address reachability and E1/E2 metric type (see External Route Issues section). |
| LSA present | Route present, wrong metric/path | For Type 5/7: check E1/E2 metric type preference (see External Route Issues section). For intra/inter-area: check cost in LSDB. |
| LSA absent | Route absent | Flooding scope or origination problem — check Area-Type Route Presence Rules below. |
LSA absent — after checking area-type rules:
If the area type should allow this LSA type (e.g., Type 5 in Area 0, Type 3 in a non-totally-stubby area) and all neighbors on this device are FULL:
redistribute statement on the ASBR).area range not-advertise or outbound filtering).If the area type does not allow this LSA type (e.g., Type 5 in a stub area), the absence is expected — the ABR should inject a default route (Type 3) instead.
Understand what should be in the LSDB before diagnosing what's missing:
| Type | Name | Who generates | Flooded |
|---|---|---|---|
| 1 | Router LSA | Every router | Within area |
| 2 | Network LSA | DR on broadcast | Within area |
| 3 | Summary LSA | ABR | Between areas |
| 4 | ASBR Summary | ABR | Other areas |
| 5 | External LSA | ASBR | All areas (except stub) |
| 7 | NSSA External | ASBR in NSSA | NSSA only → converted to Type 5 at ABR |
Critical for interpreting the LSDB:
no-summary): No Type 3/5/7. Only a single default (Type 3) from ABR. Know the difference — look for presence/absence of Type 3 LSAs.nssa no-summary): No Type 3/5. Type 7 within area + single default (Type 3) from ABR. Combines NSSA external redistribution with totally stubby inter-area filtering.area range)ABRs (C1C, C2C in this topology) can summarize inter-area routes using area X range <network> <mask>. When active, individual subnets within the range are suppressed and replaced with a single aggregate Type 3 LSA. Adding not-advertise suppresses even the aggregate.
Symptom: specific subnets from another area are missing, but an aggregate prefix is present.
get_ospf(device, "config") → look for `area X range` on the ABR (C1C or C2C)
get_ospf(device, "database") → verify the aggregate Type 3 LSA exists
This is intentional design, not a fault — verify against INTENT.json whether summarization is expected.
distribute-list under router ospf filters routes from the RIB without removing LSAs from the LSDB. This causes a confusing symptom: get_ospf(device, "database") shows the LSA but get_routing(device, prefix=<X>) returns no OSPF route.
get_ospf(device, "config") → look for `distribute-list` under router ospf
If found, identify the referenced ACL or prefix-list, then inspect the filter logic:
get_routing_policies(device, "access_lists") → if distribute-list references an ACL
get_routing_policies(device, "prefix_lists") → if distribute-list references a prefix-list
This is a deliberate policy decision — not a flooding failure.
When redistributed routes are missing in an NSSA area:
Type 7 LSA not generated → check redistribute config on the ASBR
get_ospf(device, "config")
Look for the redistribute statement; if missing, that's the issue.
Type 7 present in area but Type 5 missing in backbone → NSSA ABR translation issue
area X nssa (not area X nssa no-redistribution)get_ospf(device, "details")Default not propagating into NSSA → ABR must have area X nssa default-information-originate
When neighbors are stuck in INIT with auth mismatch:
Before investigating auth keys: confirm hello/dead timers match on both sides. Timer mismatch and auth key mismatch produce identical symptoms (interface Up/Up, L3 reachable, neighbor count = 0). Timer values and auth type are both visible in
get_ospf(device, "interfaces")output. Check timers first.
get_ospf(device, "interfaces") → shows auth type, timer values, and all OSPF interface details
Check: key-id match, key-string match (case-sensitive), MD5 vs plain text type consistent on both ends.
DR/BDR election occurs on broadcast/NBMA network types only. Highest priority wins (default 1); ties broken by highest Router ID. Priority 0 = ineligible for DR/BDR.
| Symptom | Cause | Check |
|---|---|---|
| Wrong device is DR | Priority misconfiguration | get_ospf(device, "interfaces") — check OSPF priority per interface |
| No DR elected | All priorities set to 0 | Same — at least one device must have priority > 0 |
| DR does not change after reboot of old DR | Non-preemptive election | Expected behavior — current DR keeps role until it fails (RFC 2328 §9.4) |
Note: DR election is non-preemptive. A higher-priority router joining the segment later does NOT take over the DR role — it waits until the current DR goes down.
When redistributed external routes appear in the LSDB but are not installed in the RIB:
OSPF supports two external metric types for Type 5 / Type 7 LSAs:
| Type | Cost Calculation | Preference |
|---|---|---|
| E1 | External metric + internal OSPF cost to ASBR (cumulative) | Always preferred over E2 |
| E2 | External metric only — ignores internal distance | Default on Cisco IOS |
Critical rule: Type 1 always beats Type 2 for the same destination, regardless of numeric values. If both types exist for the same prefix, E1 wins even if its total cost is higher.
Symptom: Unexpected path taken to an external prefix → check metric type in get_ospf(device, "database"). If E1 and E2 both appear for the same destination, E1 wins unconditionally.
Fix direction: Redistribute with consistent metric type across all ASBRs. Mixing E1 and E2 for the same prefix causes unpredictable path selection.
A non-zero forwarding address in a Type 5 or Type 7 LSA instructs routers to send traffic directly to that IP rather than through the advertising ASBR.
get_ospf(device, "database") → look for non-zero forwarding address in Type 5/7 LSAs
get_routing(device, prefix=<fwd_addr>) → verify forwarding address is reachable
Symptom: LSA present in LSDB but route not installed in RIB. If the forwarding address is not reachable via OSPF intra- or inter-area routes, the external route is silently discarded — it exists in the LSDB but cannot be used for forwarding.
Fix: Ensure the forwarding address is reachable via OSPF, or configure the ASBR to use forwarding address 0.0.0.0 (routes traffic through the ASBR itself).
get_ospf(device, "database") shows expected LSA types for the area typeget_routing(device) shows all expected prefixes with correct next-hopsReferences: RFC 2328 (OSPFv2: neighbor FSM §10, MTU §10.6, external metrics §16.4, forwarding address §12.4.3) · RFC 3101 (NSSA: P-bit §3, translator election §2.2) · RFC 5709 (OSPF HMAC-SHA auth)