OSPF这三个字母,很多人在备考的时候背得滚瓜烂熟,真到机房面对两台起不来邻居的路由器,往往还是两眼一抹黑。我自己第一次独立配OSPF是在一个不大的办公网里,三台路由器做核心,心想这么简单的拓扑十分钟搞定,结果邻居卡在ExStart整整一个下午,最后发现是两端接口MTU差了2字节。那次之后我才真正明白,OSPF协议基础的"基础"两个字不是让你背七种状态机,而是让你在邻居起不来的时候,知道下一步该敲哪条命令、该看哪个字段。这篇内容就是围绕这件事展开的:把OSPF的核心机制、报文交互、LSA分工、区域设计、开销计算讲清楚,再配上一套能直接抄的配置流程和一条完整的排障链路,适合刚接触动态路由的初级网络运维,也适合已经会敲命令但说不清"为什么这么配"的朋友拿来对照复盘。
1. 从静态路由撑不住的那一刻说起
静态路由好用,配置直观、不占CPU、不产生任何协议报文,两三条路由的场景下它就是最优解。问题在于它的维护成本是随网络规模呈非线性增长的:N个网段互联,理论上需要配置的路由条目量级接近N的平方,而且任何一条链路发生变化,都得人工去改。我见过一个临时办公点,二十多个网段全靠静态路由串起来,某次运营商线路切换,负责的同事改了四台设备的配置表,第二天发现漏了一条回程路由,导致某个业务单向不通,查了大半天。这就是静态路由的真实天花板——它不关心网络拓扑变化,它只忠实执行你写死的那条规则。
1.1 距离矢量协议的局限与链路状态的思路差异
在OSPF普及之前,小型网络里用得最多的是RIP这类距离矢量协议。距离矢量的核心逻辑是"我听邻居说",每台路由器把自己的整张路由表周期性发给邻居,邻居收到后加上自己的跳数再往外传。这种模式有两个绕不开的毛病:一是收敛慢,靠30秒一次的周期更新加水平分割、毒性逆转这些补丁来防环;二是"传闻路由"问题,路由器对远方网络的认知全部来自邻居转述,它并不知道网络长什么样,只知道"从哪个方向出去跳数少"。
OSPF走的是完全相反的路子,叫链路状态。每台路由器负责描述"我自己身上有哪些接口、分别连着谁、接口开销是多少",把这段信息打包泛洪给同一区域内的所有路由器。所有路由器收齐之后,各自在本地拼出一张完整的区域拓扑图,也就是链路状态数据库LSDB,然后用SPF算法以自己为根算出一棵最短路径树。这个差别很关键:距离矢量是"别人告诉我怎么走",链路状态是"我自己算怎么走"。前者容易被错误信息带偏,后者每台设备都基于同一份原始地图独立计算,一致性强得多。
用生活化的比喻:距离矢量像是你问路人怎么去火车站,路人说"往前走三个路口右转",他可能也是听别人说的;链路状态像是每个人手里都有一张完整城市地图,自己去规划路线。地图更新的代价当然更高,但它换来的是收敛快、易排错、支持区域分层。
1.2 一份链路状态数据库到底长什么样
理解LSDB是理解OSPF的钥匙。你可以把LSDB想象成一张表,表里每一行是一条LSA(链路状态通告),每条LSA由三部分构成:谁发的(Advertising Router)、描述的是什么(LSA类型和Link State ID)、内容是什么(具体的链路和开销)。同一区域内所有路由器的LSDB在稳态下应该完全一致,这个"完全一致"是判断OSPF是否健康的重要依据——如果两台路由器的LSDB对不上,说明泛洪过程出了问题,路由计算必然出错。
这里有个很容易被忽略的点:LSDB同步和路由表同步是两件事。LSDB一致只说明大家看到的地图一样,最终装进路由表还要经过SPF计算、路由优选、以及和静态路由、其他协议路由的比较。很多新手看到display ospf lsdb输出正常就以为万事大吉,结果路由表里没有预期条目,实际上是SPF算出来的路径被别的路由源抢了优先级。这个思路要尽早建立起来:排查OSPF问题,先从邻居和LSDB入手,再看SPF结果,最后看路由表,顺序不能乱。
1.3 OSPF在几种主流IGP里的位置
选协议这件事没有绝对优劣,只有场景匹配。把常被拿来比较的几种放在一起看,差异会清晰很多:
| 对比维度 | OSPF | 中间系统到中间系统 | 增强型内部网关路由协议 |
|---|---|---|---|
| 算法基础 | Dijkstra SPF | Dijkstra SPF | DUAL(扩散更新算法) |
| 分层方式 | 区域,必须有一个骨干区域 | 区域,骨干区域可灵活布置 | 无强制分层,靠可行性条件防环 |
| 厂商支持 | 开放标准,几乎所有设备支持 | 开放标准,但配置风格差异大 | 早期为单一厂商私有 |
| 收敛速度 | 快,可做到秒级 | 很快,大规模场景表现稳定 | 很快 |
| 规模适配 | 中小到大型网络都合适 | 超大型网络更有优势 | 中型网络较常见 |
| 学习曲线 | 中等,概念多但资料全 | 偏陡,TLV结构不直观 | 中等 |
对绝大多数企业内部网络来说,OSPF是性价比最高的选择:标准开放、资料齐全、故障案例多、跨厂商互通基本没有坑。我个人的判断原则很朴素——如果网络规模在几十台路由器以内、没有跨厂商极端性能要求,直接上OSPF,把精力花在区域规划和地址设计上,收益比纠结算法细节大得多。
2. 五种报文撑起的邻居握手过程
OSPF的所有行为都建立在五种报文之上,把它们的用途和顺序理清楚,邻居建立过程就不需要死记硬背了。这五种分别是:Hello报文负责发现和维持邻居;DD报文(数据库描述)负责交换LSDB的目录摘要;LSR报文(链路状态请求)负责点名要具体某条LSA;LSU报文(链路状态更新)负责把LSA内容送过去;LSAck报文负责确认收到。整个交互像极了一次图书馆借书:先看目录卡片(DD),记下想要的书号(LSR),管理员把书递给你(LSU),你签收(LSAck)。
2.1 Hello报文里那几个决定成败的字段
Hello报文是每台启用OSPF的接口周期性发出的"自我介绍",广播网络默认10秒一次,Dead时间40秒。这两个数值双方必须一致,否则邻居关系根本建立不起来——这是新手最容易踩的坑之一,因为有些设备默认值不同,或者有人为了"加快收敛"单边改了Hello时间。我建议在没有明确需求的情况下,全部保持默认,要改就全网统一规划。
Hello报文里有几个字段直接决定邻居能不能建立:
- Area ID:两端接口必须属于同一个区域,否则连Init状态都过不去。
- Hello/Dead Interval:必须一致,不一致时邻居会反复震荡。
- 认证类型和认证密钥:一端开了认证另一端没开,或者密钥不一致,邻居建立必然失败。
- Stub区域标志(E-bit):这个位用来标识区域是否允许外部路由进入,两端不一致同样无法建立邻居。这个细节冷门,但在混配Stub区域时经常出问题。
- 网络掩码:在广播型网络上,两端接口掩码必须一致,否则邻居卡在2-Way或无法进入ExStart。
- Router ID:虽然不直接在Hello里比较,但区域内Router ID重复是隐性杀手,后面单独说。
注意:Hello时间里还携带了邻居列表,只有双方在彼此的Hello邻居列表里都出现,才会进入下一状态。单向链路或者ACL过滤了组播报文时,会出现一端是Full、另一端是Down的诡异现象,别急着怀疑配置。
2.2 从Down走到Full,每一步卡住说明什么
OSPF邻居状态机一共有八种状态(含NBMA网络下的Attempt),实际排障时最有诊断价值的是这几种:
| 状态 | 含义 | 卡在这里的典型原因 |
|---|---|---|
| Down | 还没收到对方的Hello | 接口未启用OSPF、链路不通、组播被过滤、区域ID不匹配 |
| Init | 收到了对方Hello,但对方没收到我的 | 单向链路、一端ACL拦截、一端接口被shutdown |
| 2-Way | 双方互相看到了,但不建立完全邻接 | 广播网络中非DR/BDR之间正常停在这里;掩码不一致也会卡这里 |
| ExStart | 开始协商主从关系和DD序列号 | 两端MTU不一致、Router ID重复 |
| Exchange | 正在交换DD摘要 | 大网中LSDB差异过大导致交换缓慢,或MTU问题 |
| Loading | 正在用LSR请求缺失的LSA | 链路质量差导致LSA丢失,或对端LSDB异常 |
| Full | 邻接关系完全建立,LSDB已同步 | 正常状态 |
这张表我建议直接抄下来贴在工位上。排障最怕的是漫无目的地敲命令,有了这张对照表,看到邻居停在哪个状态,排查范围立刻缩小到一个很小的集合。比如卡在ExStart,那就不要再去检查区域ID和认证了,99%是MTU或者Router ID的问题。
2.3 ExStart卡死的两种高发原因
ExStart是我见过最多的"绊脚石"。这个阶段双方要通过DD报文协商主从关系(Router ID大的一方成为Master),同时确定DD报文的序列号。协商能否成功,取决于DD报文能否被对方正常接收。
第一种原因是MTU不匹配。DD报文的接口MTU字段会被对端校验,一旦发现不一致,对端会直接丢弃这个DD报文,导致双方在ExStart反复重传、谁也无法推进。这个问题的隐蔽之处在于:ping大包可能通(因为MTU只是略小),普通业务也不受影响,唯独OSPF邻居起不来。排查方法很简单,在两台设备上分别查看接口MTU,对比一下就知道。修复方式是两端统一MTU,或者在对端接口上配置忽略MTU检查——后者能快速恢复业务,但属于掩盖问题,长期还是应该统一规划。
第二种原因是Router ID重复。Router ID在OSPF区域内必须唯一,通常取设备上最大的Loopback地址,没有Loopback就取最大的物理接口地址。如果规划不慎导致两台设备取了同一个Router ID,邻居关系会反复建立又断开,日志里能看到明确的冲突提示。我在一个迁移场景里遇到过:两台设备都从旧配置继承了同一个Loopback地址,改造时没人注意到,结果整个区域的路由时有时无,查了很久才定位到。所以Router ID这条,我现在的习惯是手工指定、全网规划、写进配置规范。
3. LSA不是一种东西:六类常见类型的职责划分
很多人学OSPF卡在LSA这一关,原因是一上来就背"六种LSA类型",却没搞明白它们解决的是不同层面的问题。换个角度理解会轻松很多:LSA的本质是"信息的载体",不同区域、不同角色需要传递的信息粒度不同,所以才演化出这么多类型。区域内的路由器需要知道区域内每条链路的细节,所以有Type1和Type2;区域之间只需要知道"哪个网段、多远、从哪个ABR出去",不需要细节,所以有Type3做摘要;外部路由要区分"是谁引入的"和"外部网段在哪",于是有了Type4和Type5。
3.1 区域内的两块基石:Type1与Type2
Type1是路由器LSA(Router LSA),每台路由器为它所属的每个区域各生成一条。内容描述这台路由器在该区域内的所有接口、接口连接的邻居、以及每条链路的开销。这是SPF算法计算的原始素材,没有Type1就什么都算不出来。
Type2是网络LSA(Network LSA),由广播网络(或NBMA)上的DR生成,描述这个广播网段上连接了哪些路由器。为什么要单独有一条?因为广播网络里多台路由器挂在同一个共享介质上,如果每台路由器都往Type1里写"我连着这个网段",SPF计算时会出现大量重复的伪节点。DR生成Type2代表这个共享网段作为一个"虚拟节点",各路由器的Type1指向它,计算就清晰了。这也是DR存在的核心意义之一——除了减少邻接数量,它还承担了生成Type2的职责。
点对点网络没有DR,也就没有Type2,这时候链路的描述完全靠Type1里的邻居信息。所以在纯点对点互联的拓扑里,display ospf lsdb只看得到Type1,这是正常的,不要以为配置漏了。
3.2 跨区域的信息摘要:Type3与Type5
Type3是汇总LSA(Summary LSA),由ABR(区域边界路由器)生成,作用是把一个区域内的路由"摘要"成一条或多条路由,发布到相邻区域。注意是"路由"而非"链路细节"——接收方只知道有这么个网段、开销是多少、要从哪个ABR出去,完全不知道那个区域内部长什么样。这种信息隔离正是OSPF能做大的原因:核心区域不需要维护每个接入区域的所有链路状态,只维护路由摘要即可。
Type5是外部LSA(AS External LSA),由ASBR(自治系统边界路由器)生成,用来描述通过重分发引入的外部路由。Type5有一个全区域泛洪的特性——它会在整个OSPF域内传播(Stub区域除外),所以外部路由条目多的时候要格外小心,容易把设备内存和CPU压上去。实际工程中,如果外部路由超过几百条,一般会考虑用区域类型做过滤,或者用更合适的方案重新设计。
Type3和Type5一个关键区别要记住:Type3是ABR"翻译"出来的,Type5是ASBR"引入"进来的。判断一条路由的来源,看它的LSA类型就能反推网络结构。
3.3 容易被忽略的Type4与Type7
Type4是ASBR汇总LSA,也是ABR生成的,作用是告诉其他区域"哪个路由器是ASBR"。为什么要这条?因为其他区域的路由器收到了Type5外部路由,需要知道去外部网段的下一跳应该指向哪个ASBR,但Type5里只写了ASBR的Router ID,跨区域之后无法直接算出到达ASBR的路径,所以需要一个"到ASBR的路由"做支撑,Type4就是这个角色。如果某个区域能学到Type5却ping不通外部网段,八成是Type4缺失。
Type7是NSSA外部LSA,只在NSSA区域内使用,由NSSA区域内部的ASBR生成,传播到NSSA的ABR时会被转换成Type5再发往其他区域。Type7和Type5的核心区别在于泛洪范围和P-bit(Propagate bit)的处理,这部分内容展开会很长,但你需要记住的结论是:NSSA区域解决的是"我想引入外部路由,但不想接收别人引入的外部路由"这个矛盾场景。
提示:很多资料会把LSA类型和区域类型混在一起讲,容易把人绕晕。建议分开记:LSA是"信息长什么样",区域类型是"哪些信息允许进出"。这两条线各自理清,再交叉理解就顺了。
4. 区域划分:OSPF能撑起大网的关键设计
单区域OSPF在几十台路由器以内完全够用,一旦超过这个数量,问题就开始显现:任何一条链路抖动都会触发全区域SPF重算,所有路由器的CPU都会被拉起来;LSDB体积膨胀,设备内存压力增大;泛洪流量本身也占带宽。区域划分就是用来解决这三个问题的。
原理上很直白:把网络切成若干个区域,每个区域只维护自己的完整拓扑(Type1和Type2),区域之间的路由通过ABR以Type3摘要的形式传递。这样一次区域内变化只影响本区域的SPF计算,其他区域不受波及。代价是失去了端到端的完整拓扑视图,跨区域排障会稍微麻烦一些。
4.1 骨干区域为什么必须是Area 0
OSPF有一条硬性规定:所有非骨干区域必须直接与骨干区域相连,区域间路由必须经过骨干区域中转。这个规定不是随便定的,它是防止区域间路由环路的核心机制。
道理在于,Type3摘要本身没有防环能力。如果允许两个非骨干区域直接交换Type3,就形成了"区域A的路由从区域B进来,区域B的路由从区域A进来,谁也不清楚对方的信息来源"的局面,环路风险极高。强制所有区域间流量经过Area 0,相当于在拓扑上设置了一个唯一的中转枢纽,任何跨区域路径都必须"先上骨干、再下分支",这个约束简单粗暴但极其有效。
实际工程中常见的问题是:新增一个分支区域,物理上只能连到就近的非骨干区域,没法直连骨干。这时候有三个选择——用虚链路(Virtual Link)打通逻辑上的骨干连接、把该区域改造成与骨干区域合并、或者重新规划物理链路。我个人强烈建议优先考虑物理链路重新规划,虚链路的配置和排障复杂度都不低,容易变成长期的技术债。
4.2 ABR、ASBR、内部路由器的判定标准
这三个角色不是靠配置命令指定的,而是由路由器在拓扑中的实际位置自动判定:
- 内部路由器:所有接口都属于同一个区域(或同为骨干区域的接口)。
- ABR:至少有一个接口在骨干区域,同时至少有一个接口在非骨干区域,并且该路由器在骨干区域里有至少一个Full状态的邻居。
- ASBR:执行了路由重分发(把其他协议或静态路由引入OSPF)的路由器,与接口区域无关。
这里有个容易误解的细节:ABR的判定要求"在骨干区域有Full邻居",只是把接口划进Area 0但邻居没起来,是拿不到ABR身份的,也就不会生成Type3。排查"区域间路由不通"时,先确认ABR身份是否生效,再去看Type3有没有生成,这个顺序能省很多时间。
4.3 Stub与NSSA:用区域类型换资源
除了普通区域和骨干区域,OSPF还定义了几种特殊区域类型,本质都是用"限制信息进入"来换取设备资源:
| 区域类型 | 允许Type3 | 允许Type4/Type5 | 允许Type7 | 典型用途 |
|---|---|---|---|---|
| 普通区域 | 是 | 是 | 否 | 绝大部分场景 |
| Stub | 是(含默认路由) | 否 | 否 | 末端区域,只有一条出口 |
| 完全Stub | 仅默认路由 | 否 | 否 | 末端区域,进一步瘦身LSDB |
| NSSA | 是 | 否 | 是 | 末端区域但需要引入少量外部路由 |
使用特殊区域的前提是这个区域确实是"末端"——只有一条路径通往外部。如果区域有两条出口,配了Stub之后其中一条出口的流量会因为缺少明细路由而绕行,甚至黑洞。我在一个双出口的分支网络上见过这个错误:为了省资源把区域配成了Stub,结果主备两条链路的主备切换逻辑完全失效,备用链路永远收不到流量。区域类型的选择必须结合拓扑冗余设计一起考虑,不能只看单点。
5. 开销计算与SPF:选路背后的真实逻辑
OSPF选路不看跳数,看开销(Cost)。这个设计比RIP先进,但也带来了新的复杂度:开销怎么算、参考带宽设多少、多条等价路径怎么处理,这些都是实际工程里会反复遇到的问题。
5.1 Cost的计算公式与参考带宽的陷阱
基本公式是:
接口Cost = 参考带宽 ÷ 接口带宽参考带宽默认是100Mbps。由此推出:10M接口Cost=10,100M接口Cost=1,1000M接口Cost=1(0.1向上取整为1),10000M接口Cost=1。看出问题了吗?百兆以上的接口在默认参考带宽下Cost全部是1,这意味着一条千兆链路和一条万兆链路在OSPF眼里完全等价,选路时只能靠等价负载均衡把流量分摊,无法实现真正的按带宽优选。
这是OSPF最经典的坑之一。解决方法是全局修改参考带宽,比如设为10000Mbps:
参考带宽 = 10000 千兆接口 Cost = 10000 / 1000 = 10 万兆接口 Cost = 10000 / 10000 = 1修改参考带宽有一个硬性要求:同一区域内所有路由器的参考带宽必须一致,否则各设备算出来的Cost不同,SPF计算会出现环路或者次优路径。这个一致性要求经常被忽略,尤其是在分批升级设备的时候,新旧设备的默认值不同,混跑就是一个隐患。我的做法是把参考带宽写进网络基线配置模板,所有设备上线统一执行。
还有一个实操细节:接口Cost可以手工指定,用于强制选路。比如两条并行链路,一条是主用但物理带宽较低,你想让它优先,就可以手工把它的Cost调低。手工指定Cost是排障和流量调度的常用手段,但要记录在案,否则半年后接手的人看到Cost和带宽对不上会一头雾水。
5.2 从LSDB到SPF树的三步走
SPF算法的输入是本区域的LSDB,输出是一棵以自己为根的最短路径树。过程可以概括为三步:
第一步,把自己作为根节点,Cost为0。第二步,把LSDB里所有直接相连的邻居挂到树上,Cost等于对应接口的Cost。第三步,反复从"未加入树的节点"里挑出距离根最近的一个,加入树,并把它所有的邻居挂上来,同时更新到达这些邻居的累计Cost,如果发现更短的路径就替换。这个过程一直持续到所有可达节点都进入树为止。
最终每个节点在树上的位置就代表了它在OSPF域内的最优路径,SPF把树上的路径转换成路由表条目:目的网络、下一跳、出接口、累计Cost。这个"累计Cost"是路径上所有出接口Cost的总和,不是单条链路的Cost,这一点在做流量规划时要特别注意。
区域内路由(Type1/Type2算出来的)和区域间路由(Type3)在SPF计算中的处理方式不同:区域内路由走完整的SPF,区域间路由是"先算出到ABR的最短路径,再叠加Type3里声明的Cost",属于距离矢量的思路。所以严格说,OSPF是"区域内链路状态、区域间距离矢量"的混合体。理解这一点,才能解释为什么跨区域排障时经常需要分段看——每一段的Cost来源不一样。
5.3 等价路由与选路优先级
当SPF算出多条到达同一目的网络的路径,且累计Cost完全相同时,OSPF会把这些路径都装进路由表做负载均衡,这就是等价路由(ECMP)。默认情况下最多支持几条等价路径取决于设备实现,常见是4条或8条,可以调整。
这里有一个容易误判的地方:Cost相同才会做ECMP,Cost不同时只选最小Cost的那条,哪怕差距只有1。所以如果发现流量没有按预期分摊,先去看各条路径的累计Cost是否真的相同,往往是一条链路上多了个百兆接口,导致整条路径Cost高了1。
选路优先级方面,OSPF内部有一个顺序:区域内路由优先于区域间路由,区域间路由优先于Type5外部路由,Type5外部路由中Type1(外部Cost加上内部Cost)优先于Type2(只比较外部Cost,默认)。这个优先级链路在排查"路由表里为什么是这条"时非常有用,很多"明明应该走A却走了B"的疑问,答案就在这条链上。
6. 从零跑通两台路由器的完整配置过程
理论讲完,落到实操。下面这套流程是我自己常用的顺序,从地址规划到验证,每一步都有明确目的。
6.1 环境规划与前置检查
假设两台路由器R1和R2通过千兆接口互联,各自挂一个业务网段,要求全网互通。地址规划如下:
| 设备 | 接口 | IP地址 | 说明 |
|---|---|---|---|
| R1 | Loopback0 | 10.0.0.1/32 | Router ID |
| R1 | GigabitEthernet0/0 | 10.1.1.1/24 | 互联链路 |
| R1 | GigabitEthernet0/1 | 192.168.10.1/24 | 业务网段A |
| R2 | Loopback0 | 10.0.0.2/32 | Router ID |
| R2 | GigabitEthernet0/0 | 10.1.1.2/24 | 互联链路 |
| R2 | GigabitEthernet0/1 | 192.168.20.1/24 | 业务网段B |
规划阶段有三件事必须先确认:互联接口的物理层是否up、两端MTU是否一致、两端接口掩码是否一致。这三件事听起来是废话,但我见过太多案例是物理层没通就开始怀疑OSPF配置,白白浪费一小时。
6.2 分步配置与命令意图说明
以下命令为通用语法示意,不同设备厂商的具体命令格式存在差异,请以实际设备手册为准。
第一步,配置接口地址并确认直连可达:
# 配置互联接口 interface GigabitEthernet0/0 ip address 10.1.1.1 255.255.255.0 no shutdown # 配置Loopback作为Router ID interface Loopback0 ip address 10.0.0.1 255.255.255.255 # 验证直连 ping 10.1.1.2配置Loopback的目的是提供一个稳定的Router ID。物理接口可能会down,Router ID一旦因为接口down而重新选举,会导致OSPF进程重建,邻居全部断开。用Loopback是最稳妥的做法。
第二步,启用OSPF并手工指定Router ID:
router ospf 1 router-id 10.0.0.1 network 10.1.1.0 0.0.0.255 area 0 network 192.168.10.0 0.0.0.255 area 0这里有两个要点。router-id手工指定优先于自动选举,避免设备重启后Router ID变化。network命令的反掩码是很多人第一次接触会犯错的地方——0.0.0.255对应/24,意思是"前24位匹配、后8位任意",和子网掩码的写法正好相反。我建议把常用反掩码对照表存下来,或者干脆全用精确的/32宣告到接口地址,虽然麻烦但不容易错。
第三步,R2做对称配置,仅在接口上额外确认MTU:
# R2配置 interface GigabitEthernet0/0 ip address 10.1.1.2 255.255.255.0 ip mtu 1500 router ospf 1 router-id 10.0.0.2 network 10.1.1.0 0.0.0.255 area 0 network 192.168.20.0 0.0.0.255 area 06.3 验证的四层递进顺序
配置完成后的验证必须按顺序来,跳步会漏问题:
第一层,邻居状态。查看OSPF邻居,确认状态是Full。如果停在2-Way,在只有两台路由器的广播网络上需要警惕——正常情况下非DR/BDR才会停在2-Way,两台设备应该一主一从,都进Full。
第二层,LSDB一致性。分别在两台设备上查看LSDB,对比Type1和Type2的条目数量。两台设备都应该有两条Type1(自己和对方各一条),如果互联链路是广播型,还应该有一条Type2。数量对不上说明泛洪没完成。
第三层,路由表。查看OSPF路由,R1应该能学到192.168.20.0/24,R2应该能学到192.168.10.0/24。注意看下一跳和出接口是否正确,Cost是否符合预期。
第四层,端到端连通性。从R1的业务网段地址ping R2的业务网段地址,注意要用带源地址的ping,否则可能因为源地址选择不当导致误判。
这四层全部通过,一次基础的OSPF配置就算跑通了。我建议把这四层验证写成一个检查清单,每次配置完都走一遍,形成肌肉记忆。
7. 邻居起不来时的分层排查链路
配置过程顺利的话十分钟搞定,但实际工作中,OSPF问题的复杂度往往来自"配置看起来完全正确"。下面这条排查链路是按我自己的经验整理的,从物理层往上逐层扒,基本能覆盖90%以上的邻居故障。
7.1 按层排查:从物理到协议
第一层,物理与二层。接口状态是否up、光模块是否正常、交换机侧的VLAN是否放通、有没有端口安全策略限制。这一层是最容易被"想当然"跳过的,尤其是跨交换机互联的场景,很多时候两边配置一模一样,问题就在中间那台设备的VLAN没放行。
第二层,三层可达性。两端接口能否互相ping通,注意要在设备上用正确的源地址ping。直连不通,OSPF必然起不来,先解决连通性。
第三层,基础参数一致性。依次核对:区域ID、Hello/Dead时间、认证配置、接口掩码、网络类型、MTU。这六项里任何一项不一致,邻居都可能建立失败或者反复震荡。我习惯用一条命令把两端的接口参数都打出来,逐行比对,比凭记忆核对可靠得多。
第四层,Router ID与DR选举。检查是否有Router ID重复。查看DR/BDR选举结果,确认优先级设置是否符合预期。如果某台设备接口优先级被误设为0,它会退出选举,主备关系可能和规划相反。
第五层,策略与过滤。检查接口上有没有ACL拦截了OSPF的组播报文(广播网络上使用224.0.0.5和224.0.0.6),检查有没有路由策略影响了LSA的生成或接收。这一层的问题是最后才查的,因为需要前面的层都排除干净才有意义。
7.2 两个真实场景的排查复盘
场景一:新上线的设备邻居一直停在Init。现象是A端看到邻居在Init,B端看到邻居在Down。Init的含义是"我收到了你的Hello,但你没收到我的",典型的单向通信。检查发现互联链路上有一台中间设备配置了ACL,只放行了单方向的组播。这个场景的启发是:Init状态几乎可以直接锁定单向问题,不用再纠结其他参数。
场景二:邻居能到Full,但路由学不全。这个问题更隐蔽。邻居Full说明握手正常,问题一定在LSA泛洪或者SPF计算环节。分步排查:先看两端LSDB是否一致,发现B端少了Type3;再看B端的ABR身份,发现虽然接口划进了Area 0,但Area 0里没有Full邻居,所以ABR身份没生效,自然不生成Type3。根因是Area 0的接口所在链路物理隔离。这个案例说明:邻居Full不等于路由正常,LSDB和路由表必须分别验证。
7.3 DR/BDR选举异常的处理
广播网络中DR/BDR选举是隐性的坑。规则是:先比接口优先级(默认1,范围0-255,0表示不参与),优先级高者当选;优先级相同则比较Router ID,大者当选。关键点是选举具有非抢占性——已经选出的DR不会因为新加入一台优先级更高的设备就被替换,除非DR失效或者OSPF进程重启。
这个非抢占特性经常导致"明明优先级配了100,为什么它不是DR"的困惑。解决办法要么重启OSPF进程强制重新选举,要么把原DR的优先级调低让它主动让位,要么接受现状——只要网络稳定,DR是谁其实不影响转发。我个人的建议是:如果拓扑规划明确要求某台设备做DR,就在部署阶段一次性把优先级配好,避免后期再调整。另外,互联链路如果是点对点类型(比如PPP或配置了p2p网络类型),根本不存在DR/BDR选举,这一点在判断问题时要先确认网络类型。
注意:接口类型为点对点时没有DR,也就没有Type2 LSA。如果你在排查中坚持找Type2而找不到,先确认一下接口的网络类型,能省下不少时间。
8. 几个我踩过之后才记住的细节
关于Hello时间的调整,我的建议是除非有明确需求,否则不要动。有些场景为了加快故障感知会把Hello调到3秒、Dead调到10秒,这在链路质量不稳定的环境里反而容易造成邻居震荡,因为丢一个Hello就可能触发重建。真的需要快速收敛,应该去看BFD联动这类机制,而不是粗暴地压Hello时间。
关于区域划分,我的体会是宁可少划也不要乱划。区域数量多了,ABR上的Type3数量会急剧膨胀,管理复杂度上升,而收益并不明显。一个中等规模的网络,三到五个区域通常就够了,关键是把变化频繁的接入区域和稳定的核心区域分开。
关于配置规范,我现在所有OSPF相关的项目都会做一份基线模板,明确Router ID规划规则、参考带宽统一值、Hello/Dead时间、认证方式、区域划分原则。模板的价值不在于约束别人,而在于半年后自己回来看的时候,能快速回忆起当时的决策依据。
还有一点关于验证的习惯:配置完成后不要只看邻居状态就宣布完工,一定要做端到端业务验证,并且记录配置前后的路由表快照。出现问题时,快照对比往往比任何排查思路都直接有效。这个习惯帮我省下的时间,远超记录本身的花费。
最后提一句关于学习的路径。OSPF的RFC文档很长,不建议从头啃。比较高效的方式是先把邻居状态机和五种报文吃透,这部分理解了,LSA和各种区域类型都是在这套机制上的扩展,学习曲线会平缓很多。至于SPF算法的具体实现细节,除非你要做协议开发或者深度调优,掌握"以自己为根、按Cost累加、构建最短路径树"这个主干就够了,剩下的可以在遇到具体问题时再深入。