ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

OSPF多区域配置与故障排查:ABR、LSA与路由汇总实践

OSPF多区域配置与故障排查:ABR、LSA与路由汇总实践

1. 分区这事,得从一次收敛说起

1.1 单区域撑不住的三个信号

早些年我接触过一个园区网,四十几台三层设备全塞在 Area 0 里,规模说大不大,说小也不小。刚开始跑得挺稳,等到接入层不断加网段、加设备,问题就冒出来了:任何一台接入交换机上闪断一下,核心几台路由器的 CPU 就跟着抖一下;每次排查问题,display ospf lsdb一屏一屏往下翻,找一条明细路由得花好几分钟。这里面的本质原因并不复杂——OSPF 是链路状态协议,同一个区域内所有路由器的 LSDB 必须完全一致,区域内任何一条链路发生变化,都要重新泛洪、重新跑一遍 SPF 计算。区域越大,LSA 数量越多,泛洪范围和计算量就成正比往上走。

我把当时遇到的现象归成三类,你可以对照自己手头的网络看看有没有中招。第一类是LSDB 膨胀,单区域跑到几百上千条 LSA 之后,display ospf lsdb的输出已经很难人工阅读;第二类是拓扑变化影响面过大,末端某个机房的一根网线抖动,都能让核心设备重算一次 SPF;第三类是路由明细无法收敛,一个区域里几十个连续网段,全部以 Type-3 的形式向其他区域扩散,路由表里全是碎片。多区域设计的价值就在这里:把大网络切成若干块,让拓扑变化的泛洪被限制在单个区域内部,让区域间的路由可以被汇总成一条,让每一台设备的 LSDB 规模控制在自己够用的范围内。

1.2 Area 0 不是"随便挑一个区域"

刚接触多区域的人最容易犯的错,是把 Area 0 当成一个普通编号,觉得"反正只要分区了就行,Area 0 给谁不是给"。这个理解是有问题的。OSPF 的规则很硬:所有非骨干区域必须通过骨干区域(Area 0)互联,区域间的路由信息必须先送到 Area 0,再由 Area 0 转发给其他区域。这就意味着 Area 0 在逻辑上必须是连通的、不能被割裂的,它承担的是区域间路由中转的角色。

如果某个区域的物理连接确实绕不开 Area 0,比如一个分支只连到了另一个分支上,那你只有两条路:要么用虚连接(vlink)把这条区域逻辑上"挂"回骨干,要么重新规划链路。虚连接不是万能药,它依赖穿越区域的稳定性,穿越区域一旦断了,虚连接跟着断,被挂接的区域就整个失联。所以我在实际项目里更倾向于在规划阶段就把 Area 0 的物理连通性解决掉,虚连接只作为过渡手段。

还有一点值得强调:ABR 必须至少有一个接口在 Area 0 里。这个条件不满足,设备即使配了两个区域,也不会产生 Type-3 LSA,区域间的路由根本传不出去。我在后面第 5 节会专门讲这个坑,因为它太常见了,配置看起来全对,路由就是不出现。

1.3 先把角色和 LSA 边界理清楚

配置之前有几个概念必须搞明白,否则后面看到display ospf lsdb的输出会一头雾水。内部路由器是所有接口都在同一个区域的设备;**ABR(区域边界路由器)**是同时连接骨干区域和至少一个非骨干区域的设备,它负责把一个区域的明细路由翻译成 Type-3 LSA 送到其他区域;**ASBR(自治系统边界路由器)**负责引入外部路由,产生 Type-5 LSA。这三种角色决定了设备在 LSDB 里能看到什么、不能看到什么。

LSA 类型这块我建议至少记住前五种。Type-1 是路由器 LSA,每台路由器在区域内各产生一条,描述自己的链路和邻居;Type-2 是网络 LSA,由广播网络上的 DR 产生;Type-3 是网络汇总 LSA,由 ABR 产生,描述"我这边有个网段,开销是多少";Type-4 是 ASBR 汇总 LSA,告诉其他区域"去 ASBR 该往哪走";Type-5 是外部 LSA,由 ASBR 产生并泛洪到整个 AS 域。记住一句话就够用:Type-1 和 Type-2 不出区域,Type-3 和 Type-4 由 ABR 产生、跨区域传播,Type-5 全域泛洪。后面配置 Stub 区域时,"不接受 Type-5"这条规则就是从这里来的。

2. 拓扑和地址规划:图纸画错后面全白搭

2.1 四台设备、三个区域怎么摆

我用的实验拓扑是四台路由器、三个区域,规模不大但把多区域里该踩的点基本都覆盖了。R1 单独在 Area 0,作为骨干区域的代表;R2 同时挂在 Area 0 和 Area 1 上,是第一个 ABR;R3 同时挂 Area 1 和 Area 2,是第二个 ABR;R4 只在 Area 2 里,是末端路由器。这个链式结构的好处是,你能清楚看到一条区域间路由是怎么从 Area 2 一路被"翻译"到 Area 0 的。

连接关系是这样的:R1 的 G1/0/1 接 R2 的 G1/0/1,网段 10.1.0.0/30;R2 的 G1/0/2 接 R3 的 G1/0/1,网段 10.1.1.0/30;R3 的 G1/0/2 接 R4 的 G1/0/1,网段 10.1.2.0/30。每台设备各配一个 LoopBack0,地址分别是 10.0.0.1 到 10.0.0.4,掩码 32 位。业务网段我放在 R2 的 Area 1 侧和 R4 的 Area 2 侧:R2 上挂 172.16.1.0/24、172.16.2.0/24、172.16.3.0/24 三个连续网段,用来演示区域间汇总;R4 上挂 192.168.10.0/24,用来验证 Stub 区域的默认路由下发。

为什么用 30 位掩码而不是 24 位?点到点链路只需要两个可用地址,30 位掩码正好提供两个,用 24 位会白白浪费 252 个地址空间,而且 OSPF 会把整个 /24 当成一个网段发布出去,路由表里看着别扭。这是我在实际组网里坚持的习惯,小细节但能减少后续排查时的干扰。

2.2 地址、区域、Router ID 规划表

规划表这种东西看着土,但在多区域环境里能救命。我见过太多案例,配置到一半发现 Router ID 撞了,或者某个网段被错误地通告进了两个区域,回头一条条display去查,时间全耗在这上面。下面这张表是我动手前必须写清楚的:

设备接口IP 地址/掩码所属区域角色
R1LoopBack010.0.0.1/32Area 0内部路由器
R1G1/0/110.1.0.1/30Area 0内部路由器
R2LoopBack010.0.0.2/32Area 0ABR
R2G1/0/110.1.0.2/30Area 0ABR
R2G1/0/210.1.1.1/30Area 1ABR
R3LoopBack010.0.0.3/32Area 1ABR
R3G1/0/110.1.1.2/30Area 1ABR
R3G1/0/210.1.2.1/30Area 2ABR
R4LoopBack010.0.0.4/32Area 2内部路由器
R4G1/0/110.1.2.2/30Area 2内部路由器

Router ID 这块我坚持手工指定,不去依赖自动选举。自动选举的规则是:先看有没有配置 LoopBack 接口,有就选 LoopBack 里最大的 IP;没有 LoopBack 就选物理接口里最大的 IP。这条规则本身没问题,问题在于网络一变,Router ID 可能跟着变,而 Router ID 一变,OSPF 进程就得重启才生效,邻居关系全部重建。生产环境里这种意外重建,往往就是一次短暂但真实的业务中断。所以我宁可多打一行router-id,把这事钉死。

2.3 上机前的四项自检

真正敲命令之前,有四件事我会先确认一遍。第一,接口的物理状态和协议状态是不是都 up,display interface brief里两个 up 缺一不可,物理层不通谈什么 OSPF。第二,直连能不能 ping 通,对端地址先 ping 一遍,这一步花十秒,能省掉后面半小时的猜测。第三,Router ID 有没有重复,四台设备四个 ID,肉眼比对一遍。第四,每个网段归属哪个区域,心里要有唯一答案,同一个网段绝对不能出现在两个区域里,OSPF 不允许,配置上去也不会按你想象的走。

这四项自检听起来像是废话,但我可以负责任地说,后来帮别人排查的多区域问题里,至少三成卡在这四步中的某一步。尤其是第二条,很多人配完 OSPF 发现邻居起不来,第一反应是去查 OSPF 参数,实际上底层链路压根没通。先 ping 再查协议,这个顺序别搞反。

3. H3C 设备上的配置落地

3.1 骨干区两台路由器的起底配置

R1 是 Area 0 里的普通路由器,配置最干净。先起 LoopBack 和物理接口,再进 OSPF 进程挂网段。这里我用的是 Comware V7 的命令行风格,接口编号以实际设备为准,我这份实验里用的是 G1/0/1 这种三段式命名:

<H3C> system-view [H3C] sysname R1 [R1] interface LoopBack 0 [R1-LoopBack0] ip address 10.0.0.1 32 [R1-LoopBack0] quit [R1] interface GigabitEthernet 1/0/1 [R1-GigabitEthernet1/0/1] ip address 10.1.0.1 30 [R1-GigabitEthernet1/0/1] quit [R1] ospf 1 router-id 10.0.0.1 [R1-ospf-1] area 0 [R1-ospf-1-area-0.0.0.0] network 10.0.0.1 0.0.0.0 [R1-ospf-1-area-0.0.0.0] network 10.1.0.0 0.0.0.3 [R1-ospf-1-area-0.0.0.0] quit [R1-ospf-1] quit

这里有两个细节必须说透。第一个是network后面跟的是反掩码,不是子网掩码。10.1.0.0 0.0.0.3表示 10.1.0.0 到 10.1.0.3 这个范围,正好覆盖 10.1.0.1 和 10.1.0.2 两个地址。如果你习惯性写成0.0.0.252,那通告的范围就变成 10.1.0.0 到 10.1.0.255,接口虽然也能进 OSPF,但以后同网段里加地址会出意外。反掩码写错是新手最高频的错误,没有之一。

第二个细节是network命令的本质是"匹配接口",不是"宣告网段"。它的逻辑是:遍历设备上所有接口,凡是 IP 地址落在这个范围内的接口,就把这个接口使能 OSPF 并划进对应区域。所以你可以用一条network 10.0.0.0 0.0.0.255把所有 10.0.0.x 的接口一次性挂进去。但我不推荐这么干,因为匹配范围越宽,误伤的可能性越大,某天你临时加一个 10.0.0.100 的管理口,它会被自动拽进 OSPF,而你根本没意识到。我自己的习惯是精确匹配,一个接口一条命令,宁可多写几行。

R2 是 ABR,配置要挂两个区域。这里的关键是同一台设备的 OSPF 进程只有一个,但可以划分多个区域,接口按网段归属分别挂到对应区域下:

[R2] ospf 1 router-id 10.0.0.2 [R2-ospf-1] area 0 [R2-ospf-1-area-0.0.0.0] network 10.1.0.0 0.0.0.3 [R2-ospf-1-area-0.0.0.0] network 10.0.0.2 0.0.0.0 [R2-ospf-1-area-0.0.0.0] quit [R2-ospf-1] area 1 [R2-ospf-1-area-0.0.0.1] network 10.1.1.0 0.0.0.3 [R2-ospf-1-area-0.0.0.1] network 172.16.1.0 0.0.0.255 [R2-ospf-1-area-0.0.0.1] network 172.16.2.0 0.0.0.255 [R2-ospf-1-area-0.0.0.1] network 172.16.3.0 0.0.0.255 [R2-ospf-1-area-0.0.0.1] quit [R2-ospf-1] quit

注意 R2 的 LoopBack0 我挂在 Area 0 里。这不是随便选的,LoopBack 地址通常用作设备的管理地址或者 Router ID 对应的稳定地址,挂在骨干区能保证它被其他区域正确学习到,而且不会因为区域划分问题导致 ping 不通。有些设计里会把 LoopBack 放到单独的区域,我不建议,除非你有明确的策略需求。

R3 的结构和 R2 类似,只是它跨的是 Area 1 和 Area 2:

[R3] ospf 1 router-id 10.0.0.3 [R3-ospf-1] area 1 [R3-ospf-1-area-0.0.0.1] network 10.1.1.0 0.0.0.3 [R3-ospf-1-area-0.0.0.1] network 10.0.0.3 0.0.0.0 [R3-ospf-1-area-0.0.0.1] quit [R3-ospf-1] area 2 [R3-ospf-1-area-0.0.0.2] network 10.1.2.0 0.0.0.3 [R3-ospf-1-area-0.0.0.2] quit [R3-ospf-1] quit

至于 R4,它只在 Area 2 里,配置最轻:

[R4] ospf 1 router-id 10.0.0.4 [R4-ospf-1] area 2 [R4-ospf-1-area-0.0.0.2] network 10.1.2.0 0.0.0.3 [R4-ospf-1-area-0.0.0.2] network 10.0.0.4 0.0.0.0 [R4-ospf-1-area-0.0.0.2] network 192.168.10.0 0.0.0.255 [R4-ospf-1-area-0.0.0.2] quit [R4-ospf-1] quit

跑完这四台,display ospf peer应该能在 R2 上看到两个邻居,R3 上看到两个邻居。如果邻居状态停在Full,说明邻接关系建立完成;如果停在2-Way,广播网络里非 DR/BDR 之间出现 2-Way 是正常现象,别慌。这个状态机的细节我放在第 5 节展开。

3.2 ABR 上双区域挂接的两种写法与取舍

配置 ABR 有两种写法,一种是在 OSPF 进程里用area划分,另一种是用接口视图下的ospf area命令绑定。我上面用的是第一种,原因是集中管理更清晰,所有区域归属在一个地方就能看全,display current-configuration configuration ospf一输出,整个进程的区域结构一目了然。第二种写法的好处是接口级操作更直接,比如某个接口要单独调 cost、调网络类型,在接口视图里顺手就做了。

# 写法二示例,效果等价 [R2] interface GigabitEthernet 1/0/2 [R2-GigabitEthernet1/0/2] ospf 1 area 1

两种写法能混用,但我建议一台设备上统一用一种。混用之后的后果是,你display ospf interface看到的区域归属是对的,但回头去 OSPF 进程里找network命令找不到,维护的时候会懵。我在一个项目里接手过别人的配置,同一个进程里两种写法各占一半,光理清区域划分就花了一个下午。

还有一个细节:同一接口不能被两个区域同时匹配。如果你在 Area 0 里写了network 10.1.0.0 0.0.0.3,又在 Area 1 里写了network 10.1.0.0 0.0.0.255,那么先匹配上的那个生效,后一个被忽略,设备日志里通常不会有明显提示。这种"静默失败"最坑人,所以第 2 节的规划表才那么重要。

3.3 区域间路由汇总:abr-summary 到底配在哪

R2 的 Area 1 侧挂了三个连续网段 172.16.1.0/24、172.16.2.0/24、172.16.3.0/24。如果不做汇总,这三条明细会各自以 Type-3 LSA 的形式进入 Area 0,再传到 Area 2。三个网段还能忍,想象一下三十个、三百个的场景,路由表会被切得稀碎。汇总命令在 ABR 上配,注意是在 OSPF 进程的区域视图下,不是全局:

[R2-ospf-1] area 1 [R2-ospf-1-area-0.0.0.1] abr-summary 172.16.0.0 255.255.0.0 [R2-ospf-1-area-0.0.0.1] quit

这条命令的含义需要说清楚,否则很容易配反。它的作用是:把 Area 1 内部产生的 Type-1/Type-2 明细路由,汇总成一条 172.16.0.0/16 的 Type-3 LSA,向其他区域发布。也就是说,汇总动作发生在"出口方向",配置在源区域视图下。如果你把这条命令配到area 0下面,那汇总的就是 Area 0 的路由往外发,跟你的意图完全是两码事。

汇总生效之后,Area 0 和 Area 2 的设备上看到的是 172.16.0.0/16 这一条,而不是三条 /24。但有一个行为需要留意:ABR 上仍然保留明细路由,因为它自己直连这些网段,汇总只影响它向外通告的内容。你在 R2 上display ip routing-table还能看到 172.16.1.0/24 这些明细,这是正常的,不代表汇总没生效。验证汇总是否生效,要去 R1 或 R4 上看路由表,或者直接display ospf lsdb network看 Type-3 LSA 的内容。

3.4 特殊区域、默认路由与虚连接

把 Area 2 配成 Stub 区域,是我在多区域实验里必做的一步。Stub 的设计目的是阻止 Type-5 外部 LSA 进入该区域,同时 ABR 会自动向区域内下发一条 Type-3 的默认路由,让末端设备不需要知道外部明细也能访问外面。配置要求是区域内所有路由器都要配stub,漏掉一台邻居就起不来:

[R3-ospf-1] area 2 [R3-ospf-1-area-0.0.0.2] stub [R3-ospf-1-area-0.0.0.2] quit [R4-ospf-1] area 2 [R4-ospf-1-area-0.0.0.2] stub [R4-ospf-1-area-0.0.0.2] quit

配完之后在 R4 上display ip routing-table,会看到一条0.0.0.0/0指向 R3,协议是 OSPF。这条默认路由不是你手工配的,是 ABR 自动下发的,属于 Stub 区域的附加福利。需要注意的禁忌是:Stub 区域内不能有 ASBR,也不能有虚连接穿越。原因很直接,ASBR 要产生 Type-5,而 Stub 区域明确拒绝 Type-5,两者互斥。如果业务上确实需要在末端区域引入外部路由,那就用 NSSA,把stub换成nssa,NSSA 允许 Type-7 存在并在 ABR 处转换回 Type-5。

虚连接的场景我单独说一下。假设某天拓扑变成"Area 2 没有物理链路连到 Area 0,只挂在 Area 1 上",那 R3 虽然跨了 Area 1 和 Area 2,但它缺少 Area 0 的接口,严格意义上不构成 ABR,Type-3 就产生不了,Area 2 整个变成孤岛。解决办法是在穿越区域(Area 1)两端打虚连接:

[R2-ospf-1] area 1 [R2-ospf-1-area-0.0.0.1] vlink-peer 10.0.0.3 [R2-ospf-1-area-0.0.0.1] quit [R3-ospf-1] area 1 [R3-ospf-1-area-0.0.0.1] vlink-peer 10.0.0.2 [R3-ospf-1-area-0.0.0.1] quit

虚连接必须两端都配,只配一端是起不来的,而且vlink-peer后面跟的是对端的 Router ID,不是接口地址。配置完成后display ospf vlink能看到状态为 Full。虚连接的实质是把 Area 1 内部的一条路径"借"给骨干用,所以穿越区域本身的稳定性至关重要,它不能是 Stub 区域,也不能是 NSSA,因为这两种区域的路由信息不完整,撑不起骨干的要求。

4. 验证:怎么确认它真按你想的在跑

4.1 邻居与接口状态的三条命令

配置敲完只是开始,验证才是重头戏。我常用的第一条命令是display ospf peer,它给出的是邻居清单和状态。正常的输出里你会看到邻居的 Router ID、地址、状态(Full)、以及 DR/BDR 的身份。如果只看这一条还不够,加verbose参数能看到更多细节:

[R2] display ospf peer verbose

加上 verbose 之后,输出里会包含邻居所在的区域、接口名、Hello/Dead 计时器、MTU、邻居的优先级和 DR 选举情况。这几个字段是排查问题的关键。比如邻居状态一直卡在ExStart,你对比两端的 MTU 字段,往往就能发现问题;如果 Hello 计时器一边是 10 一边是 30,那邻居压根不可能建立。

第二条命令是display ospf interface,它告诉你每个接口有没有真的使能 OSPF、挂在哪个区域、当前的 DR/BDR 是谁、cost 是多少。这条命令我特别推荐在配置完立刻跑一遍,因为network命令写错的时候,接口根本不会出现在这个列表里,一眼就能看出来。

[R2] display ospf interface [R2] display ospf interface GigabitEthernet 1/0/2

第三条是display ospf error,这条命令平时没人看,出问题的时候是宝。它会按类别统计 OSPF 收发报文过程中的错误次数,比如 Hello 报文里的区域 ID 不匹配、认证失败、MTU 不一致等等。邻居起不来又找不到原因的时候,先清一次计数,再观察几十秒,看哪一类错误在涨,方向基本就锁定了。

4.2 LSDB 里该出现什么、不该出现什么

display ospf lsdb是理解多区域最直观的入口。在 R2 上跑这条命令,你会看到 Area 0 和 Area 1 各自的 LSDB,两个区域的链路状态数据库是分开维护的,这正是分区的核心机制。Area 0 里能看到 R1 和 R2 的 Type-1,Area 1 里能看到 R2 和 R3 的 Type-1,两边的 Router LSA 不会互相串。

[R2] display ospf lsdb [R2] display ospf lsdb router 10.0.0.1 [R2] display ospf lsdb network [R2] display ospf lsdb summary

Type-3 的产生逻辑值得单独验证。在 R4 上执行display ospf lsdb summary,你应该能看到 R3 产生的若干条 Type-3,描述的是 Area 1 和 Area 0 里的网段。但如果你在 R4 的 LSDB 里搜到了 Type-5 的 LSA,那说明 Stub 配置没生效,得回去检查是不是两端都配了stub。这就是 LSDB 验证的价值——它不看路由表的结果,直接看协议内部的数据结构,比间接推断可靠得多。

还有一个容易被忽略的点:Area 0 里不应该出现 Area 1 的 Type-1 LSA。如果你翻 LSDB 发现某个区域里混进了别的区域的 Router LSA,那八成是区域划分出错,两个区域被配到了同一个接口,或者network范围写太宽误伤了。

4.3 路由表与转发面的交叉核对

邻居 Full、LSDB 正常,最后一步是看路由表。在 R1 上display ip routing-table,你应该能看到 10.0.0.2 到 10.0.0.4 这几条 /32 的 LoopBack 路由,以及 172.16.0.0/16 这条汇总路由,协议标识是 OSPF,下一跳指向 R2。如果 172.16.0.0/16 没出现,但明细路由出现了,那说明abr-summary没生效,回头查配置位置。

[R1] display ip routing-table [R1] display ip routing-table protocol ospf [R1] display ospf routing

display ospf routing和路由表是两回事,前者看的是 OSPF 自己计算出来的路由,后者是优选之后进入转发表的结果。两者不一致的时候,通常是路由优先级或者等价路由的问题,比如同一条路由既有静态又有 OSPF,静态默认优先级更高。这个命令在排查"OSPF 算出来了但没进路由表"的场景里特别有用。

最后别忘了ping和tracert。协议层面的验证再漂亮,最终还是要落到转发上。从 R4 ping R1 的 LoopBack,tracert 一下看路径是不是 R4 → R3 → R2 → R1,如果是,那整条链路的路由和转发就都通了。这一步花不了一分钟,但它是唯一能证明"业务真的能通"的证据。

5. 故障速查:邻居起不来和路由学不到

5.1 邻居状态机的七种卡点

OSPF 邻居建立要经过 Down、Init、2-Way、ExStart、Exchange、Loading、Full 七个状态,任何一步卡住都有对应的原因。我把最常见的几种列出来,配上定位方法。

卡在 Init,意思是本端收到了对端的 Hello,但自己的 Hello 没被对端收到。这是典型的单向通信问题,可能是链路上有 ACL 挡了出方向、可能是两端接口掩码不一致导致广播域不同、也可能是某一端的network没把接口套进去。排查方法是两端互相display ospf interface,看接口是不是都在列表里,然后检查 ACL 和掩码。

卡在 2-Way,如果是广播网络上的非 DR/BDR,这是正常状态,不用管。但如果所有邻居都是 2-Way,没有任何一对进入 Full,那说明 DR 选举出了问题,可能是所有接口的dr-priority都是 0,没有人愿意当 DR。

卡在 ExStart,两个路由器互相在争主从关系,通常的原因是MTU 不匹配或者Router ID 冲突。MTU 这个问题在某些厂商的设备上会严格检查,一端是 1500 一端是 9000,DD 报文就协商不下去。Router ID 冲突的话,display ospf peer里会看到两个邻居的 ID 一模一样,改掉其中一个重启进程即可。

卡在 Exchange 或 Loading,一般是 LSA 传输有问题,可能是 LSA 太大分片丢了,也可能是网络质量差导致重传超时。

还有一种情况是邻居根本不出现在列表里,display ospf peer一片空白。这时候先display ospf interface确认接口使能了 OSPF,再确认两端是不是同一个区域——区域 ID 不一致,邻居连 Init 都到不了,这是新手最常犯的错之一,因为两端配置看起来都"有 area 命令",只是编号不一样。

5.2 邻居正常但路由缺失的四类原因

邻居全 Full,路由表里却没东西,这种问题更隐蔽。我总结下来有四类原因。

第一类是 ABR 不成立。设备配了两个区域,但没有一个接口在 Area 0 里,那它就不是 ABR,不会产生 Type-3。表现出来就是两个非骨干区域之间互相学不到路由,但各自区域内部一切正常。验证方法是display ospf brief看设备角色,或者直接看它有没有 Area 0 的接口。

第二类是汇总掩码写错。abr-summary 172.16.0.0 255.255.0.0汇总的是 172.16.0.0 到 172.16.255.255,如果你的明细网段是 172.17.x.x,那这条汇总压根覆盖不到,路由自然消失。更隐蔽的情况是汇总掩码比明细还细,比如用 /24 去汇总 /16 的网段,结果是把明细吃掉了但没产生汇总,属于配置事故。

第三类是 Stub 区域配置不一致。一端配了stub,另一端没配,邻居会卡在 ExStart 附近反复重试,日志里可能只有一句含糊的提示。这种问题只能靠两端逐条比对配置来解决。

第四类是路由被过滤或者优先级压掉。filter-policy、import-route的引入策略、静态路由的优先级,都可能让 OSPF 算出来的路由进不了转发表。display ospf routing和display ip routing-table对比着看,能快速区分是"没算出来"还是"算出来没进去"。

5.3 一张贴在工位上的速查表

下面这张表我打印出来贴在显示器边上很多年,后来带新人的时候直接拍照发给他们,省了大量口舌:

现象高概率原因定位命令处理动作
邻居列表为空接口未使能 OSPF / 物理链路不通display ospf interface、ping补network,查链路
卡在 Init单向通信、掩码不一致、ACL 拦截两端display ospf interface统一掩码,检查 ACL
卡在 2-Way(全部)DR 优先级全为 0display ospf peer verbose调整dr-priority
卡在 ExStartMTU 不一致 / Router ID 冲突display ospf peer verbose统一 MTU,改 Router ID
邻居 Full 但无区域间路由设备不是 ABR,缺 Area 0 接口display ospf brief补骨干区接口或打 vlink
汇总后明细消失但无汇总路由汇总掩码覆盖不到明细display ospf lsdb summary修正汇总掩码
Stub 区域学不到默认路由一端未配 stub / ABR 配置缺失display ospf lsdb区域内全部配 stub
改了 router-id 不生效OSPF 进程未重启display ospf briefreset ospf process

最后一行那个reset ospf process需要额外提醒:这是有中断风险的操作,进程重启期间邻居全部断开,路由重新收敛,生产环境里务必挑窗口做。而且执行的时候会弹确认,别手快直接回车。

6. 参数调优与生产环境的几点体会

6.1 cost、参考带宽与路径选择

OSPF 选路靠 cost 累加,cost 的计算公式是参考带宽 ÷ 接口带宽,结果取整,最小为 1。默认参考带宽是 100Mbps,这就带来一个尴尬的现实:千兆口算出来是 0.1,取整后是 1;万兆口算出来是 0.01,也是 1。也就是说,在默认参数下,千兆和万兆的开销完全一样,OSPF 无法区分这两者的优劣,路径选择就变成了看谁先算出来。

解决办法是调大参考带宽:

[R1-ospf-1] bandwidth-reference 10000

把参考带宽设成 10000Mbps 之后,千兆口的 cost 变成 10,百兆口变成 100,万兆口变成 1,层次就出来了。这个参数必须在同一个区域内的所有设备上保持一致,否则两端的 cost 计算基准不同,算出来的路径会互相矛盾,可能出现次优路径甚至环路。我在一个项目里遇到过一端改了参考带宽、另一端没改的情况,表现是流量走了绕远的那条链路,查了两天才定位到。

除了全局参考带宽,也可以在接口上直接指定 cost:

[R1-GigabitEthernet1/0/1] ospf cost 20

手工 cost 的优先级高于自动计算,适合做精细的流量调度。但手工 cost 的维护成本高,接口一多就容易忘,我一般只在关键链路上用。

6.2 计时器、认证与稳定性

Hello 和 Dead 计时器决定了邻居探测的灵敏度。广播网络默认 Hello 10 秒、Dead 40 秒,也就是连着四个 Hello 没收到才认为邻居挂了。想加快收敛可以改小:

[R1-GigabitEthernet1/0/1] ospf timer hello 5 [R1-GigabitEthernet1/0/1] ospf timer dead 20

这里有个硬性约束:Dead 必须至少是 Hello 的 4 倍,H3C 设备上如果不满足这个比例,配置会直接报错拒绝。改计时器同样要求两端一致,一端 10/40 一端 5/20,邻居起不来。我个人对改计时器持保守态度,除非链路质量确实很好、业务对收敛时间极其敏感,否则默认值够用。把 Hello 改到 1 秒看起来收敛快了,代价是链路稍有抖动就误判邻居 down,反而引发不必要的重收敛。

区域认证是另一个值得配的东西,尤其是跨机房、跨楼栋的链路。H3C 支持简单口令和 MD5 两种:

[R1-ospf-1] area 0 [R1-ospf-1-area-0.0.0.0] authentication-mode md5 [R1-ospf-1-area-0.0.0.0] quit [R1] interface GigabitEthernet 1/0/1 [R1-GigabitEthernet1/0/1] ospf authentication-mode md5 1 cipher YourPassword

认证配错的表现是邻居起不来,display ospf error里认证失败计数会涨。这个功能的价值不在于防攻击,更多是防止误接入——有人把一台设备插进网络,随手配了个 OSPF,如果没有认证,它可能直接成为邻居并注入路由,这种事故我见过不止一次。

6.3 我在实际项目里踩过的坑

第一个坑是network反掩码写成子网掩码。看起来很蠢,但在赶工期的时候真的会发生。network 10.1.0.0 255.255.255.252这种写法,设备不会报错,只会默默不匹配任何接口,接口永远进不了 OSPF,而你在display ospf interface里什么都看不到。后来我养成了一个习惯:配完network立刻跑一次display ospf interface,确认接口数量对得上再往下走。

第二个坑是多区域环境下的 DR 选举失控。广播网络里 DR 是按优先级和 Router ID 选的,优先级默认都是 1,那就比 Router ID,谁大谁当 DR。问题在于 Router ID 大小跟设备性能毫无关系,可能一台性能很弱的设备因为 ID 大而当上了 DR,结果它的 LSDB 和 SPF 计算能力撑不住,整个区域的收敛都受影响。我的做法是在关键广播网段上,把希望当 DR 的设备ospf dr-priority调到 100 以上,不希望当的调到 0,把选举结果固定下来。而且要注意DR 是非抢占的,你改完优先级,得等当前 DR 挂了或者重启进程才会重新选。

第三个坑是改 Router ID 之后忘记重启进程。router-id命令敲下去,配置回显是成功的,但display ospf brief里看到的还是老 ID。这是因为 Router ID 在 OSPF 进程启动时就已经确定,改了配置得靠reset ospf process才生效。我第一次遇到这个现象的时候,反复检查配置,怀疑是不是命令敲错了,折腾了半个多小时才想起来这茬。

第四个坑跟 Stub 区域有关。有次我把一个末端区域配成了 Stub,配完发现那个区域里的一台设备上还跑着import-route,用来引入一条静态路由。结果自然是引入的路由死活传不出来,因为 Stub 区域不允许 ASBR 存在。这种情况只能改成 NSSA,把stub换成nssa,让 Type-7 在区域内传,到 ABR 再转成 Type-5。改完之后还要注意 NSSA 的默认路由需要手工配default-route-advertise,不像 Stub 那样 ABR 会自动下发,这个差异我当年也栽过跟头。

最后一个算不上坑,算个习惯:每次动 OSPF 配置之前,先display current-configuration configuration ospf存一份。多区域环境里区域和接口的对应关系不像单区域那么直观,改了一处很容易忘掉另一处的联动。有份快照在手,出问题至少能快速回滚,比凭记忆猜测强太多。

这套四台三区域的配置,我从最早的 Comware V5 一直用到 V7,命令主体几乎没变过,变的只是接口命名和个别参数的默认值。真正需要花时间理解的,从来不是那一行行命令,而是区域边界在哪、LSA 怎么流转、路由为什么这么选这三件事。把这三个问题想通了,换个厂商的设备,翻翻手册,照样能配出来。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进