首页 / 资讯中心 / 文章详情

OSPF路由排障:从邻居状态、LSA到SPF计算与路由优选

OSPF路由排障:从邻居状态、LSA到SPF计算与路由优选 ★ FEATURED ARTICLE
凌晨两点被叫起来处理“某个网段不通”ping 是通的但路径追踪显示流量绕了一个大圈从核心到汇聚、再到另一个汇聚又折回来。登上设备一看同一个目的网段有两条等价路径一条进了路由表另一条躺在链路状态数据库里却没参与转发。这是我这几年处理 OSPF 问题最常见的一幕——OSPF 路由表面上只是打几个 network 命令、划几个区域号的事真正难的是出问题时你能不能顺着链路状态库、SPF 计算、路由优选这条链路把原因定位出来。作为网络基础里绕不开的一课OSPF 恰恰是最容易被“背命令”糊弄过去的一课考完证的人能默写邻居状态机却未必说得清为什么千兆链路和万兆链路在这里被算成了同一个代价。下面这些内容不讲教科书定义讲的是我在实际网络中做规划、调优和排障时攒下来的东西——邻居为什么起不来、LSA 到底描述了什么、为什么算出的 cost 和预期对不上、区域类型改了之后路由为什么“消失”。刚接触真设备的新手能拿来对照维护过几年网络的人也能找到共鸣。1. OSPF 在现网长期存在的原因路径由计算得出1.1 链路状态与距离矢量的本质分野聊 OSPF 绕不开一个对比。RIP 这类距离矢量协议路由器之间传的是“我到某个网段有多远”邻居说什么就信什么本质上是在传结论。OSPF 传的是“我连着谁、这段链路的代价是多少”每台路由器拿到的是原始素材自己用 Dijkstra 算最短路。这个差别听起来像学术问题实际影响两件事收敛速度和环路风险。传结论的协议有个先天毛病坏消息传得慢。一条链路断了旁边那台设备可能还在告诉邻居“我这儿有条路能过去”因为它的信息是从别人那儿抄来的抄的时候路还是好的。链路状态协议不存在这个问题因为每台设备的数据库里存的都是自己亲眼看得到的链路状态谁断了谁自己知道立刻发一条新的通告出去其他人收到后重算。所以 OSPF 在链路抖动频繁的环境里表现更干净不会出现长时间的计数到无穷。代价是资源。每台设备都要维护一份完整的区域拓扑数据库都要跑一遍 SPF 算法链路一抖全网重算。这就引出了 OSPF 设计里最重要的一层抽象——区域。1.2 区域划分是在给链路状态数据库减负很多人学 OSPF 时把区域理解成“分组管理”好像只是为了逻辑上整齐。不是。区域的第一目的是控制 LSA 泛洪范围。如果不划区域一个几百台设备的大网就是单个区域任何一条链路抖动都会触发所有设备重算 SPF数据库膨胀、CPU 飙升、收敛变慢最后大家都难受。划了区域之后区域内部的拓扑细节只在本区域内泛洪。跑到区域边界的那台路由器ABR负责把区域内的信息“压缩”成汇总通告发给其他区域。其他区域的路由器看到的不是“区域 1 里第 7 台交换机后面的那条百兆链路断了”而是“去往 10.1.0.0/16 的路径可以走 ABR”细节被隐藏了。这就是为什么在大型网络里边缘设备的路由表能控制在几百条而不是几万条。有个前提必须记住所有非骨干区域都必须挂在骨干区域上骨干区域本身必须连续。这条规则不是形式主义因为区域间的路由信息是通过骨干区域中转的骨干断开或者不连续跨区域的路径就断了。我见过有人在扩容时把两台 ABR 之间的骨干链路改成了普通区域结果两个片区之间立刻失联查了半天才发现是区域 0 被打断了。1.3 一个容易被忽视的前提路由由计算产生OSPF 的路由不是“学”来的是“算”出来的。这三个字决定了排查思路。路由没出来不一定是没收到通告也可能是收到了但 SPF 算不出结果或者算出来了但被路由策略拦掉了或者算出来了但被别的协议以更优的管理距离压住了。这三层是完全不同的原因对应完全不同的处理方法。太多人一看到路由缺失就去改 network 命令、改区域号其实问题可能压根不在这。我在后面会专门用一节讲这个三段式定位法因为这是我认为 OSPF 排障里性价比最高的一套思路。2. 邻居无法建立时先检查 Hello 包中的几个字段2.1 邻居状态机是一条天然的排查主线OSPF 的邻居状态机有七个状态Down、Init、2-Way、ExStart、Exchange、Loading、Full。新手背这个顺序很容易但真正有用的是把它当成一条排查主线——你看到的当前状态直接告诉你卡在了哪一步前一步做对了什么这一步缺什么。Down 表示没收到任何 Hello。Init 表示收到了对方的 Hello但对方的 Hello 里没有我的 Router ID说明是单向通信。2-Way 表示双方都看到了对方正常情况在广播网络里非 DR/BDR 之间停在这里是健康的。ExStart 开始协商主从关系准备交换数据库描述包。Exchange 交换摘要。Loading 请求具体的 LSA 明细。Full 表示数据库同步完成邻接关系建立。这条主线最大的价值是排除法。你先确认物理层通不通再看 Hello 能不能双向到再看参数是否匹配再看数据库能不能同步。每一步都有明确的验证手段不用瞎猜。2.2 Init 和 2-Way 两个状态对应完全不同的故障停在这两个状态的问题性质完全不同但很多人混为一谈。卡在 Init典型是单向收到 Hello。可能的原因包括链路一端的光模块收发出问题只通一个方向中间有设备过滤了组播OSPF 的 Hello 是发往 224.0.0.5 的普通的三层设备通常不转发这类组播认证配置一边开一边没开导致对端丢弃或者两边区域号不一致虽然收到了但直接丢弃。我遇到过一次是中间串了一台二层设备开了某种组播抑制功能Hello 单向丢失两端一个在 Init 一个在 Down看着像链路问题实际是中间设备在捣乱。卡在 2-Way 就要分情况看了。广播型网络里DR 和 BDR 跟所有其他路由器建立 Full其余的路由器之间互相停在 2-Way这是设计如此不是故障。新手第一次看到一堆 2-Way 就慌了其实完全不用管。真正需要警惕的是所有邻居都停在 2-Way那说明 DR 选举出了问题常见原因是接口优先级被配成了 0不参与选举或者网络类型配错了比如本来应该是点到点被配成了广播。提示判断 2-Way 是否正常看有没有至少一对邻居是 Full。如果全网一台 Full 都没有再去查网络类型和优先级。2.3 ExStart 卡死MTU 与 Router ID 两个隐形因素ExStart 是我认为最容易被忽略的一个卡点因为这时邻居已经能看到对方了双方都觉得自己没问题但就是建立不起来。第一个元凶是 MTU 不一致。数据库描述包里携带接口 MTU两端不一致时MTU 大的那边发出的包对端接不住协商就僵住了。这种场景在现网很常见一边是万兆口 MTU 配了 9000另一边是千兆口默认 1500两个区域又刚好接在一起。解决方式要么统一 MTU要么在接口上关闭 MTU 检查多数设备支持这个开关但关闭检查只是绕过问题真正的 MTU 不一致在转发大包时还是会出问题建议统一配置。第二个元凶是 Router ID 冲突。两台设备的 Router ID 相同时LSA 里的标识会混乱邻居关系可能反复震荡或者卡在 ExStart。Router ID 的选举规则是手工指定的优先其次是最大的环回口地址最后是最大的物理接口地址。这里有个坑——Router ID 是进程启动时确定的改了接口地址不会自动更新必须重启 OSPF 进程或者手动触发一次重新选举。我见过有人改完环回口地址发现 Router ID 没变以为是设备 bug其实是设计如此。3. LSDB 中的内容LSA 类型与现网拓扑的对应3.1 一类和二类 LSA区域内的原始地图一类 LSARouter LSA是每台路由器自己产生的描述“我有哪些接口、每个接口连着什么、代价多少”。这是 SPF 计算的原始输入区域内每台路由器都会产生一条。二类 LSANetwork LSA是 DR 产生的描述一个广播网段上有哪些路由器。为什么需要它因为在广播网络里多台路由器挂在同一个网段上如果每台都把自己到其他所有路由器的链路都算一遍拓扑就变成了全互联的网状规模一大就爆炸。DR 站出来代表整个网段发一条通告把网状结构简化成星型SPF 计算的复杂度就降下来了。这也解释了为什么广播网络里非 DR 之间不需要建立 Full 邻接——它们之间的连通性通过 DR 的二类 LSA 间接表达就够了。查这两个类型时我习惯用show ip ospf database router和show ip ospf database network重点看链路数量、接口地址和 cost 是否符合预期。如果某台设备的接口地址没出现在一类 LSA 里八成是那个接口没有被 network 命令覆盖到或者被设成了被动接口。3.2 三类 LSAABR 做的信息压缩三类 LSASummary LSA由 ABR 产生把区域内的网段汇总后发给其他区域。注意它描述的是“网段 代价”不是拓扑所以接收方只能老老实实相信 ABR 给的代价没法自己算。这个特性决定了一件事跨区域的路由路径是由 ABR 决定的不是由 SPF 决定的。这意味着如果你在两个 ABR 上配了不同的汇总策略同一个目的网段可能出现不对称路径。我见过一次跨区域访问延迟异常最后发现是两个 ABR 的汇总掩码不一致导致部分明细路由从一个 ABR 出去、从另一个 ABR 回来去回路径不对称。汇总这件事在 ABR 上必须两边对齐掩码、cost、区域号都要一致。还有一个常被忽略的点三类 LSA 的过滤。想阻止某些网段进入某个区域可以用区域汇总的 not-advertise 参数或者用前缀过滤列表。前缀过滤列表有个副作用——它只影响本设备的 SPF 计算不阻止 LSA 继续泛洪。也就是说你的设备上没有这条路由但下游设备可能还有。真要阻断泛洪得在 ABR 上用汇总的方式拦。3.3 五类和七类 LSA外部路由的两条通道五类 LSAAS External LSA由 ASBR 产生描述引入到 OSPF 里的外部路由。它的泛洪范围是全网除了特殊区域所以一条外部路由抖动会影响所有区域这是它最大的问题。七类 LSANSSA External LSA就是为了解决这个问题引入的。NSSA 区域内的 ASBR 用七类 LSA 在区域内传递外部路由到了 ABR 再转换成五类发给其他区域。这样做的好处是外部路由的抖动被限制在 NSSA 内部不影响整个网络。五类和七类有个关键区别是转发地址。七类 LSA 里有个 P 比特置位表示允许 ABR 做转换。如果没有置位ABR 不会转成五类外部路由就到不了其他区域。这个 P 比特通常在引入路由时自动置位但如果做了某些特殊配置可能会被清掉排查外部路由不通时可以看一眼。3.4 LSA 类型速查表类型名称产生者泛洪范围典型用途Type 1Router LSA每台路由器本区域描述区域内接口与链路代价Type 2Network LSADR本区域描述广播网段成员Type 3Summary LSAABR相关区域区域间网段汇总Type 4ASBR Summary LSAABR相关区域指出 ASBR 的位置Type 5AS External LSAASBR除特殊区域外全网外部引入路由Type 7NSSA External LSANSSA 内 ASBR仅 NSSA 内受限范围的外部路由这张表我建议贴在工位上。排障时先判断“我需要的这条信息应该由谁产生、应该出现在哪”比一条条命令翻要快得多。比如跨区域访问不到但区域内正常那基本就是三类 LSA 的问题外部网段不通先看五类有没有、再看到达 ASBR 的四类有没有。4. SPF 计算与路由结果偏离预期的原因4.1 cost 计算规则与“千兆不如百兆”的反常现象接口 cost 的算法是参考带宽除以接口带宽。多数设备的默认参考带宽是 100Mbps于是百兆接口 cost 是 1千兆接口 cost 是 1万兆接口 cost 还是 1。取整之后全一样。这个默认值在十几年前是合理的那时候百兆还是主流。现在核心链路动辄万兆接入还是千兆全被算成 1SPF 就完全区分不出快慢。结果就是前面提到的场景一台路由器到某个目的网段有两条路一条经过万兆链路一条经过千兆按 cost 算都是 2设备就做等价负载均衡一半流量走了慢的那条。用户投诉忙时卡顿你查链路利用率发现万兆口只用了一半千兆口跑满了。解决办法是调参考带宽# 全设备统一调整为 100G 基准 router ospf 1 auto-cost reference-bandwidth 100000调完之后百兆接口 cost 变成 1000千兆是 100万兆是 10差距就出来了。注意参考带宽必须全网统一。如果一部分设备按 100M 算、一部分按 100G 算同一段链路在两端算出的 cost 不同会导致路径计算错误而且这种错误很难发现因为接口和邻居都正常。还有一个细节手工指定 cost 的接口优先级高于自动计算。如果有人为了临时调整路径在某条链路上写死了 cost后面改了参考带宽也不会生效。做全网调整前先扫一遍有没有手工 cost 配置这是踩过的坑。4.2 区域类型对选路结果的改变区域类型一改路由行为就跟着变这是新手最容易迷惑的地方。普通区域什么 LSA 都收。Stub 区域挡住四类和五类只剩一条 ABR 下发的默认路由三类 LSA 形式的默认路由用来访问外部。这样做的效果是区域内路由器的数据库大幅缩小代价是外部路径必须绕 ABR哪怕区域内存在一条更短的出口也走不了。Totally Stub 更极端连三类 LSA 也挡只保留一条默认路由区域内路由器除了本区域明细路由其余全靠默认。NSSA 和 Totally NSSA 是在 Stub 的基础上允许引入外部路由用七类 LSA 承载。踩坑点在于区域类型必须区域内所有设备一致。如果一台设备配了 Stub另一台没配两边的 Hello 包里的区域标志位对不上邻居直接起不来状态停在 Down 或者 Init而且日志里只会说参数不匹配不会直接告诉你哪一项。改区域类型时一定要先把区域内所有设备列出来逐个确认别漏掉。另一个坑是 Stub 区域不能跨越 ASBR。如果区域里有路由器要引入外部路由那它不能是 Stub只能上 NSSA。这个在改造老网络时经常遇到——本来是个普通区域为了瘦身改成 Stub结果发现区域里有一台设备在做引入一改外部路由全断。4.3 虚连接解决骨干不连续问题的适用边界虚连接是 OSPF 里一个看起来很方便、用起来容易出问题的功能。它的作用是在两个 ABR 之间通过一个传输区域建立一条逻辑链路让被隔断的骨干区域看起来连上了。它的边界条件很严格虚连接必须配置在穿越传输区域的两端 ABR 上两端都要配一端配了没用传输区域本身必须是普通区域不能是 Stub虚连接建立的前提是两端 ABR 在传输区域内的路由可达如果连路由都没有虚连接起不来虚连接的 cost 通常取穿越路径的 cost。问题在于虚连接会带来一批隐蔽的故障。比如传输区域里某条链路抖动虚连接跟着断骨干区域的连通性就受影响但故障表现却出现在别的区域。再比如虚连接建立后两边 LSA 的传播路径变了原本的汇总策略可能失效。我的建议是虚连接当临时手段用能重新规划区域划分就重新规划。真要靠虚连接长期维持骨干连通的网络说明区域设计本身就有问题早晚要还这笔账。5. 从邻居表到路由表的收敛调优与故障定位5.1 三段式定位法从物理层到转发表的逐级排查我把 OSPF 排障分成三段按顺序走基本不会漏。第一段是链路层。接口状态、光模块收发功率、误码计数、双工模式、MTU。这段看起来最基础但实际故障占比最高。光模块单收、双工不匹配、MTU 不一致这些都是控制平面查半天查不出来的。我的习惯是先看接口计数有没有错误包再看 MTU 是否两端一致这两个确认了再往上走。第二段是邻居与数据库。看邻居状态是否 Full看各类 LSA 是否齐全。这里的关键是先确认邻居 Full再确认 LSDB 有料最后才看路由表。顺序反了容易误判——比如邻居还没建起来就去看路由表发现没有路由然后去改路由策略完全跑偏。第三段是路由与转发。LSDB 里有这条 LSA不代表路由表里有这条路由。中间还隔着 SPF 计算、管理距离比较、路由过滤、汇总策略。这一段要查的是SPF 算出来了吗看路由表的候选路径、被别的协议压住了吗看管理距离、被过滤了吗看分发列表和前綴列表、被汇总覆盖了吗。5.2 现象与原因对照表现象优先怀疑验证手段邻居停在 Init单向 Hello、认证不一致、区域号不符双向抓包确认 Hello 是否都收到全网红邻居停在 2-Way优先级为 0、网络类型配错查接口优先级与网络类型邻居停在 ExStartMTU 不一致、Router ID 冲突对比两端接口 MTU确认 Router ID 唯一邻居 Full 但无路由区域类型不一致、LSA 被过滤查 LSDB 对应类型 LSA 是否存在路由存在但业务不通转发面问题、非对称路径、ACL双向路径追踪核对去回路径路由频繁震荡链路抖动、Hello 定时器不匹配查接口错误计数与日志这张表我在很多次现场都用过基本能覆盖八成问题。剩下两成通常是组合故障比如 MTU 不一致叠加认证配置错误。5.3 定时器、被动接口与认证的保守做法Hello 定时器和 Dead 定时器在不同网络类型下默认值不同。广播和点到点网络是 10 秒和 40 秒非广播多路访问和点到多点网络是 30 秒和 120 秒。这两个值两端必须完全一致不一致邻居就起不来。我一般不建议随便改小虽然能加快故障检测但代价是 Hello 包频率上升在低带宽链路上会明显增加开销。真要加快检测用双向转发检测这类机制比缩短 Hello 更合适。被动接口是个性价比很高的配置。接终端的接口、环回口这些不需要跑 OSPF 的地方配成被动接口之后不发 Hello既省资源又避免把终端网段意外暴露出去。但要注意被动接口仍然会把该网段通告出去如果被 network 命令覆盖只是不建邻居。有人以为被动接口等于不通告这是个常见误解。认证的迁移要特别注意平滑。明文认证切到密文认证如果两端同时改中间会有一小段邻居断开可能引发短暂的路由抖动。稳妥的做法是先让两端都启用认证但配置成“允许空认证”的过渡状态确认邻居正常后再把空认证关掉。这个窗口期虽然短但在承载实时业务的核心网里几秒钟的抖动也可能造成业务告警。最后说一个我自己的体会OSPF 的配置命令其实很少network、area、cost、汇总、认证翻来覆去就这些。真正的门槛不在配而在你能不能在脑子里把 LSDB、SPF、路由表这三层分开看。碰到问题先问自己问题出在哪一层然后只在这一层里找。我见过太多人一上来就改配置改到最后连原本哪里是对的都忘了只能整段重配。分层定位这件事比记住任何一条命令都值钱。
阅读完成 · 觉得有帮助?
咨询建站