网络与 IP

OSPF 状态机详解:七种邻居状态与卡在 ExStart 的排查

OSPF 状态机描述两台路由器从互不认识到数据库完全同步的过程,一共七种状态:Down、Init、2-Way、ExStart、Exchange、Loading、Full(NBMA 网络另有一个 Attempt)。前三种是发现邻居,后四种是同步链路状态数据库;邻居停在哪个状态,就说明卡在了哪一步。

作者 顶联产品团队发布于 8 分钟阅读

OSPF 状态机,指的是 OSPF 路由器为每一个邻居维护的一组状态,以及状态之间的迁移规则,定义在 RFC 2328 第 10 章。常说的“OSPF 七种状态”是 Down、Init、2-Way、ExStart、Exchange、Loading、Full,只用于 NBMA 网络的 Attempt 通常不计在内。前三种状态完成“发现邻居、确认双向通信”,后四种完成“同步链路状态数据库”;两台路由器走到 Full,才算建立了完全邻接,之后才能据此计算路由。排障时最有用的一点是:邻居停在哪个状态,就说明卡在了哪一步,每个状态对应的故障范围都很小。

OSPF 七种邻居状态一览

状态 进入条件 这一阶段收发的报文 正常情况下
Down 初始状态;或在 Dead 时间内没收到对方的 Hello 本端照常发送 Hello 邻居表里看不到对方,或对方刚断开
Init 收到对方的 Hello,但其中的邻居列表里还没有自己的 Router ID Hello 一闪而过,通常不超过一个 Hello 间隔
2-Way 在对方的 Hello 里看到了自己的 Router ID,确认双向通信 Hello;广播网络在这一阶段选举 DR、BDR 点到点链路上一闪而过;广播网络里 DROther 之间长期停在这里是正常的
ExStart 决定建立邻接,协商主从关系和 DD 序列号 不带 LSA 摘要的空 DD 报文,I、M、MS 三个标志位置 1 一两秒
Exchange 主从确定,交换数据库摘要 携带 LSA 头部的 DD 报文;发现缺少的条目时可以开始发 LSR 数据库越大越久,通常几秒
Loading 摘要交换完毕,请求自己缺少或较旧的 LSA LSR、LSU、LSAck 几秒
Full 请求列表清空,双方数据库一致 周期性的 Hello;拓扑变化时的 LSU、LSAck 长期稳定在这里

Attempt 只出现在 NBMA 网络:手工指定了邻居地址,本端正在向它单播 Hello,但还没收到回应。

邻居(neighbor)和邻接(adjacency)是两个概念:到 2-Way 就算邻居,从 ExStart 开始建立邻接,到 Full 才是完全邻接。只有建立邻接的路由器之间才同步数据库。

从 Down 到 Full:OSPF 邻居建立过程

以两台核心交换机为例:Core-A 的 Router ID 是 1.1.1.1,Core-B 是 2.2.2.2,用一条点到点链路互联,都在区域 0。

发现邻居:Down、Init、2-Way

  1. Core-A 的接口启用 OSPF 后,每 10 秒向组播地址 224.0.0.5 发送 Hello。Hello 里带着区域号、Hello 与 Dead 间隔、网络掩码、认证信息、优先级,以及“我已经见过的邻居”列表,这时列表是空的。
  2. Core-B 收到这个 Hello,先核对参数(见下文),一致就把 Core-A 加入邻居表,状态记为 Init,并在自己的下一个 Hello 里把 1.1.1.1 写进邻居列表。
  3. Core-A 收到 Core-B 的 Hello,在列表里看到了自己,确认双向可达,Core-B 在它这里直接进入 2-Way;Core-A 随后发出的 Hello 里也带上了 2.2.2.2,Core-B 收到后同样进入 2-Way。
  4. 点到点网络上双方总要建立邻接,2-Way 立即转入 ExStart。广播网络上,这一步要先等 DR、BDR 选举出结果,只有和 DR、BDR 之间才继续往下走。接口刚启用时,路由器会先等待一个 Dead 间隔(默认 40 秒)收集 Hello,再进行选举,所以广播网络上刚上线的邻居在 2-Way 停留几十秒是正常的。

同步数据库:ExStart、Exchange、Loading、Full

  1. ExStart:双方各发一个空的 DD 报文,I(Init)、M(More)、MS(Master)三个标志位都置 1,都宣称自己是主。比较 Router ID,较大的一方为主(Master)。这里 2.2.2.2 较大,Core-A 承认 Core-B 为主,并在回应中采用 Core-B 的序列号,双方进入 Exchange。主从关系与 DR 选举无关,只决定由谁控制 DD 报文的序列号。
  2. Exchange:双方用 DD 报文发送自己数据库里每一条 LSA 的头部,包括类型、链路状态 ID、通告路由器、序列号、校验和、老化时间。主方每发一个 DD,从方用相同的序列号回一个作为确认,一问一答。收到对方的摘要后,各自把“我没有的”和“我这份比较旧的”LSA 记入请求列表。
  3. Loading:用 LSR 请求列表中的 LSA,对方用 LSU 发出完整内容,收到后回 LSAck 确认。请求列表清空,进入 Full。如果 Exchange 结束时请求列表本来就是空的,就跳过 Loading,直接进入 Full。
  4. Full:双方数据库一致,各自更新 Router LSA,把这条邻接写进去并泛洪出去,然后运行 SPF 计算路由。

在点到点链路、数据库不大的情况下,从 Init 到 Full 一般只需要几秒钟。

OSPF 状态机怎么迁移:事件与状态对照

状态之间的跳转由事件触发。除了上面一路向前的过程,下表里的几种“回退”事件是排障时最常遇到的:

当前状态 事件 迁移到 说明
Down HelloReceived Init 收到对方的 Hello
Down(仅 NBMA) Start Attempt 开始向手工指定的邻居单播 Hello
Init 2-WayReceived 2-Way 或 ExStart 看到了自己的 Router ID;需要建立邻接的直接进入 ExStart
2-Way AdjOK? ExStart DR、BDR 选出后,发现需要和对方建立邻接
ExStart NegotiationDone Exchange 主从关系与初始序列号协商完成
Exchange ExchangeDone Loading 或 Full 请求列表非空进入 Loading,为空直接 Full
Loading LoadingDone Full 请求的 LSA 全部收到
Exchange 及以上 SeqNumberMismatch、BadLSReq ExStart DD 序列号或标志位异常,或请求了对方没有的 LSA,从头协商
ExStart 及以上 AdjOK?(不再需要邻接) 2-Way 例如 DR 变化后,双方都成了 DROther
2-Way 及以上 1-WayReceived Init 对方的 Hello 里不再有自己
任意状态 InactivityTimer Down Dead 时间内没收到 Hello
任意状态 KillNbr、LLDown Down 接口关闭、链路断开、OSPF 进程重启

“回到 ExStart”的两个事件,是邻居在 ExStart、Exchange、Loading 之间来回跳的原因;InactivityTimer 则是 Full 掉回 Down 最常见的原因。

用 display ospf peer 看邻居状态

华为、H3C 用 display ospf peer,加 brief 只看概要:

<Core-A> display ospf peer brief

         OSPF Process 1 with Router ID 1.1.1.1
                  Peer Statistic Information
 ----------------------------------------------------------------------------
 Area Id          Interface                        Neighbor id      State
 0.0.0.0          Vlanif10                         2.2.2.2          Full
 0.0.0.0          Vlanif20                         3.3.3.3          ExStart
 ----------------------------------------------------------------------------

不加 brief 时,每个邻居会显示 State、主从角色(Mode)、优先级、DR 和 BDR 地址、MTU、距离 Dead 超时还剩几秒、邻居已建立多久,排障时这些字段都用得上。输出格式随设备版本略有差异。

思科用 show ip ospf neighbor:

Router# show ip ospf neighbor

Neighbor ID     Pri   State           Dead Time   Address         Interface
2.2.2.2           1   FULL/DR         00:00:35    10.0.10.2       GigabitEthernet0/0
4.4.4.4           1   2WAY/DROTHER    00:00:33    10.0.10.4       GigabitEthernet0/0
5.5.5.5           0   FULL/  -        00:00:38    10.0.12.2       GigabitEthernet0/1

State 列斜杠前是邻居状态,斜杠后是对方在这个网段上的角色:FULL/DR 表示与 DR 已完全邻接;2WAY/DROTHER 表示双方都是 DROther,正常;FULL/ - 出现在点到点网络上,没有 DR 的概念。Dead Time 是距离判定邻居失效还剩的时间,默认从 40 秒开始倒数,每收到一个 Hello 就重置一次,所以正常情况下在 30 到 40 秒之间循环;如果经常看到它明显低于 30 秒才被重置,说明有 Hello 丢失或晚到。

卡在哪个状态,对应什么故障

现象 最可能的原因 先查什么
邻居表里根本没有对方 Hello 收不到,或收到后因参数不一致被丢弃 接口是否启用 OSPF、是否被设为静默接口;Hello 参数与认证;ACL 是否拦截了协议号 89
停在 Init 单向通信:我收到了对方的 Hello,对方没收到或没接受我的 链路单向丢包、中间设备单向过滤组播、ACL 方向、对端的错误计数
停在 2-Way 广播网络上双方都是 DROther(正常);或网段里所有路由器优先级都为 0 DR、BDR 字段与各台的优先级
停在 ExStart,或在 ExStart 与 Exchange 间反复 两端 MTU 不一致;单播的 DD 报文不通 两端接口 MTU;ACL 是否只放行了组播
停在 Loading 发出 LSR 后收不到 LSU,常见是大报文在中途被丢弃 两端之间大包能否通过;设备日志
已经 Full,却没有路由 两端网络类型不一致、路由被过滤、被其他路由覆盖 接口的网络类型、路由表

邻居不出现或停在 Init:Hello 参数与认证

收到 Hello 后,下面这些字段必须与本端接口一致,否则这个 Hello 直接丢弃:

  • 区域 ID;
  • 认证类型与密钥:不认证、明文、MD5 等,两端必须完全一致;
  • Hello 间隔与 Dead 间隔:广播和点到点网络默认 10 秒、40 秒,NBMA 和点到多点默认 30 秒、120 秒,两端网络类型默认值不同时最容易出错;
  • 网络掩码:只在广播和 NBMA 网络上检查;
  • 区域类型标志:一端把区域配成了 Stub 或 NSSA,另一端没有;
  • 另外,Router ID 不能重复。

注意,参数不一致或认证失败时,对方的 Hello 被丢弃,邻居表里根本不会出现对方,并不会停在 Init。真正停在 Init,意味着“我收到了你的 Hello,你却没收到我的”:链路一个方向丢包(比如一芯光纤衰减过大)、中间的二层设备或虚拟交换机过滤了一个方向的组播、ACL 只在一侧放行。少数检查不对称的情况也会造成单边 Init,例如一端是广播类型、另一端是点到点且掩码不同,只有广播一端会检查并丢弃对方的 Hello。

华为上先看本端接口参数,再看错误计数:

display ospf interface Vlanif10
display ospf error

display ospf error 隔几秒执行两次,看哪个计数在增长:Bad area id(区域号)、Bad authentication type 和 Bad authentication key(认证)、Netmask mismatch(掩码)、Hello timer mismatch 和 Dead timer mismatch(计时器)、Extern option mismatch(区域类型)、Router id confusion(Router ID 重复)。字段名以设备版本为准。

思科可以临时打开调试,R 是收到的值,C 是本端配置的值:

show ip ospf interface GigabitEthernet0/0
debug ip ospf hello
OSPF: Mismatched hello parameters from 10.0.10.2
OSPF: Dead R 120 C 40, Hello R 30 C 10  Mask R 255.255.255.0 C 255.255.255.0
debug ip ospf adj
OSPF: Rcv pkt from 10.0.10.2, GigabitEthernet0/0 : Mismatch Authentication type. Input packet specified type 0, we use type 2

认证类型 0 是不认证,1 是明文,2 是 MD5。生产设备上调试完要立即执行 undebug all。修改时两端一起改,华为在接口下用 ospf timer hello 10、ospf timer dead 40、ospf authentication-mode md5 1 cipher 密钥,思科用 ip ospf hello-interval 10、ip ospf dead-interval 40、ip ospf authentication message-digest 加 ip ospf message-digest-key 1 md5 密钥。

停在 2-Way:先确认是不是正常现象

广播网络上,一个网段有 N 台路由器,两两建立邻接需要 N(N−1)/2 条;选出 DR、BDR 后,其他路由器只和这两台建立邻接。6 台路由器两两相连要 15 条邻接,有了 DR、BDR 只要 9 条。所以 DROther 之间停在 2-Way 是设计如此。

不正常的情况有两种:一是网段里所有路由器的优先级都被设成了 0,没有 DR 可选,所有邻居都停在 2-Way,这个网段上建立不了任何邻接,经过它的路由也就学不到,至少要让一台的优先级大于 0;二是应当与 DR 建立邻接的路由器也停在 2-Way,要按 ExStart 的思路继续查。

机房里两台设备之间的以太网互联,建议两端都改为点到点类型(华为 ospf network-type p2p,思科 ip ospf network point-to-point),省去选举和等待,收敛更快。两端必须同时改,否则就成了后文的网络类型不一致。

卡在 ExStart 或 Exchange:多半是 MTU 不一致

DD 报文里带有发送接口的 MTU。按 RFC 2328,收到的 DD 里的 MTU 大于本端接口 MTU 时,本端认为自己收不下对方的大报文,拒绝这个 DD。结果是 MTU 小的一端停在 ExStart,MTU 大的一端常显示为 Exchange,双方不断重传。机房里最常见的场景,是一端为存储或虚拟化网络开了 9000 字节的巨型帧,另一端仍是 1500。

两家厂商的默认行为不同:

  • 思科默认检查 MTU,debug ip ospf adj 会提示 Nbr 10.0.10.2 has larger interface MTU。正确的做法是把两端 MTU 改成一致;ip ospf mtu-ignore 只是跳过检查,大于对端 MTU 的报文照样可能在对端被丢弃,不建议长期使用。
  • 华为默认在 DD 报文里把 MTU 填为 0、也不检查,所以两台华为设备 MTU 不同照样能走到 Full,display ospf peer 里看到的 MTU 为 0 就是这个原因。接口下配置 ospf mtu-enable 后才填写并检查。不检查不等于没有问题:数据库变大、LSU 报文超过对端 MTU 时,可能表现为停在 Loading。

查看接口 MTU,华为用 display interface Vlanif10,思科用 show ip interface GigabitEthernet0/0 | include MTU。

ExStart 的另一个原因是 DD 报文不通。在广播网络上,Hello 走组播,DD 和 LSR 却是发往对方接口地址的单播。中间的 ACL 或防火墙如果只放行了 224.0.0.5、224.0.0.6,Hello 正常、2-Way 正常,到 ExStart 就过不去了。

停在 Loading,或已经 Full 却没有路由

停在 Loading,说明 LSR 发出去了,对应的 LSU 迟迟收不到;如果对方收到的 LSR 请求的是它数据库里没有的 LSA,会触发 BadLSReq 事件,邻居退回 ExStart 重新协商,周而复始。先用不分片的大包测两端之间能否通过:华为 ping -f -s 1472 10.0.10.2,思科 ping 10.0.10.2 size 1500 df-bit。大包不通,回到 MTU 的思路;大包正常,看设备日志里有没有 LSA 校验相关的报错。

已经 Full 却缺路由,最典型的是两端网络类型不一致:一端广播、一端点到点,计时器默认值相同,邻居可以走到 Full,但两端对这条链路的描述方式不同,SPF 无法确认链路双向可用,路由算不出来。用 display ospf interface 或 show ip ospf interface 核对两端的网络类型。其次是路由被过滤,或同一前缀存在优先级更高的路由:华为上静态路由(优先级 60)会压过 OSPF 外部路由(150),思科上静态路由(管理距离 1)会压过 OSPF(110)。用 display ip routing-table protocol ospf 或 show ip route ospf 看 OSPF 实际装进路由表的条目,再用 display ospf lsdb 确认 LSA 是否已经收到。

在管理系统里怎么落地

OSPF 排障的大部分时间花在登录两端设备、执行 display 命令、对比配置上;而修改 MTU、计时器、网络类型这类操作,只改了一端就会把原本正常的邻居打断。Toplink DCIM 的 交换机管理 可以在浏览器里直接打开交换机的 SSH 或 Telnet 终端,每次会话全程录像并记录命令日志,事后可以回看每次会话执行过哪些命令;邻居异常时,对照会话时间就能找到是哪一次操作改动了 OSPF 参数。交换机的端口占用与上联关系也在系统里统一登记,查一条互联链路时,先在系统里确认两端的设备和端口,再分别登录核对两端的配置。

常见问题

OSPF 的 Router ID 是怎么确定的?改了为什么不生效?

手工配置的优先;没有配置时,思科从处于 up 状态的 Loopback 接口中选最大的 IP,没有 Loopback 再从物理接口里选,华为的自动选取规则以版本手册为准。Router ID 在进程启动时就确定了,修改后要重启 OSPF 进程才生效(华为 reset ospf 进程号 process,思科 clear ip ospf process),重启会断开这个进程的所有邻居。

邻居失效后要多久才能发现?能缩短吗?

接口物理断开会立即感知;对端设备故障、或中间隔着二层设备时,要等 Dead 间隔到期,广播和点到点网络默认 40 秒,这段时间里流量仍会发往已失效的邻居。可以两端一起缩短 Hello 与 Dead 间隔,或为 OSPF 启用 BFD,把检测时间缩短到秒级以内,BFD 同样需要两端都配置。

邻居在 Full 和 Down 之间反复切换是什么原因?

多数是 Hello 报文在 Dead 时间内连续丢失:链路丢包或拥塞、设备 CPU 过高来不及处理协议报文、二层环路。思科日志里的 Neighbor Down: Dead timer expired 就是这种情况,先查接口错误计数、CPU 和链路利用率。

想看看在你的机房里怎么用?

从一次产品演示开始,梳理你的业务链路。

查看价格
服务热线 400-112-2951

让我们聊聊你的 IDC 业务

扫码添加企业微信,预约产品演示或申请试用。

Toplink 企业微信二维码

长按保存或使用企业微信 / 微信扫描

也可致电
400-112-2951
Telegram
@TopLink88