3. OSPF报文与状态机深入
OSPF 的可靠性并不来自 TCP,而是来自五种报文在 IP 之上的分工协作。理解这五种报文,是理解邻居为什么停在某个状态、为什么路由学不到、为什么 LSA 反复重传的前提。本节先拆解报文职责,再把它们映射到邻居状态机上,最后给出可落地的排障路径。
五种报文的职责边界
OSPF 直接封装在 IP 协议号 89 之上,五种报文共同构成一个“确认式泛洪”机制:
- Hello(Type 1):周期性发送,默认广播网络 10s、NBMA/点到多点 30s,Dead 时间为 Hello 的 4 倍。它负责发现邻居、协商参数、选举 DR/BDR,并作为保活。Hello 里携带 Router ID、Area ID、Hello/Dead 间隔、优先级、邻居列表、认证字段、Stub 区域标志和 MTU 检查位。
- DD(Database Description,Type 2):描述本地 LSDB 的“目录”,只含 LSA 头部(类型、Link State ID、Advertising Router、序列号),不含完整内容。通过 I/M/MS 三个标志位完成主从协商与分片传输。
- LSR(Link State Request,Type 3):当 DD 中发现对方有而本地没有、或本地版本更旧的 LSA 时,按 LSA 头部三元组精确请求完整内容。
- LSU(Link State Update,Type 4):承载一个或多个完整 LSA,是真正传递拓扑信息的报文。它既用于响应 LSR,也用于本地拓扑变化后的主动泛洪。
- LSAck(Link State Acknowledgment,Type 5):对收到的 LSU 做显式确认,可一次确认多个 LSA 头部。没有它,LSU 会按 Retransmit 间隔(默认 5s)重传。
关键点在于:DD 只交换目录,LSR/LSU 才交换内容,LSAck 保证内容不丢。这条链路一旦某一环断裂,邻居状态就会卡住。
邻居状态迁移:每个状态在等什么
状态机的本质是“等待某个报文或某个条件”。把状态与报文对应起来,排障时就能直接定位卡点:
| 状态 | 进入条件 | 卡在此状态的典型原因 |
|---|---|---|
| Down | 未收到任何 Hello | 接口未启用 OSPF、链路/二层不通、Hello 被 ACL 过滤 |
| Init | 收到 Hello,但邻居列表中没有本机 Router ID | 单向通信、组播被阻断、认证失败 |
| 2-Way | 双方 Hello 中都看到对方 Router ID | 广播网络中非 DR/BDR 之间正常停留于此;若 DR 选举异常则卡住 |
| ExStart | 开始 DD 主从协商 | MTU 不一致、Router ID 冲突、DD 序列号异常 |
| Exchange | 交换 DD 目录 | MTU 不匹配导致 DD 被丢弃、链路丢包严重 |
| Loading | 发送 LSR 请求缺失 LSA | LSU 未响应、LSA 被过滤、链路拥塞 |
| Full | LSDB 完全同步 | 正常状态;若频繁回退说明链路或资源不稳定 |
需要特别强调:2-Way 在广播网络中不是故障。DR/BDR 与所有 DROther 建立 Full,而 DROther 之间保持 2-Way,这是设计行为。只有 DR/BDR 选举异常或需要 Full 的邻居卡在 2-Way 才需要处理。
故障排查要点:从状态反推报文
排障的核心思路是“看状态、抓报文、对参数”。以下命令在 Cisco IOS 上可直接使用:
R1# show ip ospf neighbor
R1# show ip ospf interface GigabitEthernet0/0
R1# debug ip ospf adj
R1# debug ip ospf packet
R1# show ip ospf database
R1# show ip ospf statistics
典型场景与判断依据:
- 一直 Down:先确认接口是否在 OSPF 进程中(
show ip ospf interface brief),再确认 Hello/Dead 是否一致,最后检查是否被 ACL 或认证拦截。 - 卡在 Init:说明本机收到了 Hello,但对方没收到本机的 Hello。重点查单向链路、组播 224.0.0.5 是否被过滤、接口是否被配置为 passive。
- 卡在 ExStart:最常见原因是 MTU 不一致。DD 报文携带 MTU 字段,若两端不匹配,DD 会被丢弃。可用
show ip ospf interface对比 MTU,或在接口下配置ip ospf mtu-ignore临时绕过(不推荐长期使用)。 - 卡在 Exchange:DD 分片传输中断,通常是链路丢包或 MTU 问题。检查接口错误计数和链路质量。
- 卡在 Loading:LSR 发出但收不到 LSU。检查对方是否过滤了 LSA、链路是否拥塞、LSA 是否因序列号问题被丢弃。
- 频繁 Full→Down→Full:说明 Hello 保活不稳定,可能是链路抖动、CPU 过高导致 Hello 超时,或 Dead 时间设置过短。
排障时优先使用
show ip ospf neighbor 查看状态和 Dead Time 倒计时。如果 Dead Time 在减少但状态不变,说明 Hello 仍在收但参数协商有问题;如果 Dead Time 归零后邻居消失,说明 Hello 已中断。
一个可复用的排障检查清单
把上述内容整理成可执行的检查顺序,便于现场快速定位:
- 确认接口已加入 OSPF 进程且未被 passive。
- 确认两端 Area ID 一致。
- 确认 Hello/Dead 间隔一致。
- 确认认证类型和密钥一致。
- 确认 MTU 一致(ExStart 卡点)。
- 确认网络类型一致(广播/点对点/NBMA)。
- 确认 Router ID 无冲突。
- 确认组播和 ACL 未阻断 OSPF 报文。
- 查看
show ip ospf statistics是否有重传或校验错误。 - 必要时用
debug ip ospf adj观察状态迁移细节。
在生产网络中慎用
debug ip ospf adj,它会产生大量日志并消耗 CPU。建议在维护窗口或实验室环境使用,并配合 logging buffered 限制输出。