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 保证内容不丢。这条链路一旦某一环断裂,邻居状态就会卡住。

OSPF 五种报文与邻居状态迁移映射 R1 Router ID 1.1.1.1 R2 Router ID 2.2.2.2 Hello (Type 1) 发现邻居 / 参数协商 / DR 选举 / 保活 DD (Type 2) 交换 LSDB 目录(仅 LSA 头部),I/M/MS 协商主从 LSR (Type 3) 按三元组请求缺失或过期的 LSA LSU (Type 4) 携带完整 LSA,响应请求或主动泛洪 LSAck (Type 5) 显式确认,未确认则 5s 后重传 状态: Down → Init → 2-Way → ExStart → Exchange → Loading → Full

邻居状态迁移:每个状态在等什么

状态机的本质是“等待某个报文或某个条件”。把状态与报文对应起来,排障时就能直接定位卡点:

状态进入条件卡在此状态的典型原因
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 请求缺失 LSALSU 未响应、LSA 被过滤、链路拥塞
FullLSDB 完全同步正常状态;若频繁回退说明链路或资源不稳定

需要特别强调: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 已中断。

一个可复用的排障检查清单

把上述内容整理成可执行的检查顺序,便于现场快速定位:

  1. 确认接口已加入 OSPF 进程且未被 passive。
  2. 确认两端 Area ID 一致。
  3. 确认 Hello/Dead 间隔一致。
  4. 确认认证类型和密钥一致。
  5. 确认 MTU 一致(ExStart 卡点)。
  6. 确认网络类型一致(广播/点对点/NBMA)。
  7. 确认 Router ID 无冲突。
  8. 确认组播和 ACL 未阻断 OSPF 报文。
  9. 查看 show ip ospf statistics 是否有重传或校验错误。
  10. 必要时用 debug ip ospf adj 观察状态迁移细节。
在生产网络中慎用 debug ip ospf adj,它会产生大量日志并消耗 CPU。建议在维护窗口或实验室环境使用,并配合 logging buffered 限制输出。