1. 为什么NSSA区域的路由计算值得单独拿出来聊
OSPF这个协议,只要做过企业网或者运营商网络的兄弟都不陌生。但真要说到NSSA(Not-So-Stubby Area)区域里的路由计算,尤其是FA(Forwarding Address)值这个字段,很多人就开始含糊了。我见过不少工作了五六年的网工,配NSSA区域的时候就是照搬模板,area 1 nssa一敲,重分发一配,通了就完事。至于为什么这条外部路由进NSSA之后下一跳变成了某个奇怪的地址,为什么有时候FA是0.0.0.0有时候又是具体IP,为什么明明路由表里有条目但转发就是不通——这些问题一旦在现网里炸出来,没有扎实的理解根本排不掉。
这篇东西就是把我自己反复做实验、反复踩坑之后总结出来的NSSA路由计算逻辑和FA值行为,完整地拆一遍。核心关键词就三个:NSSA区域、路由计算过程、FA值。我会从LSA的类型和传播机制讲起,把Type-7 LSA怎么产生、怎么被翻译成Type-5、FA在什么条件下被置位、置位之后对路径计算有什么影响,全部用实验现象来验证。适合有一定OSPF基础、想彻底搞明白NSSA区域内部转发逻辑的读者,也适合正在准备高级网络认证、需要把协议细节吃透的朋友。
先给一个最直观的结论:NSSA区域里外部路由的下一跳,取决于FA字段。FA为0.0.0.0时,流量会绕到ASBR(自治系统边界路由器)那边去;FA为非零时,流量直接朝着FA所指向的地址走。这一个字段的差异,在拓扑稍微复杂一点的网络里,就是"流量路径完全不一样"的区别。下面我一步步展开。
2. NSSA区域的设计初衷与LSA类型基础
2.1 普通区域、Stub区域和NSSA区域到底差在哪
要理解NSSA,得先把OSPF的区域类型谱系理清楚。标准区域(Normal Area)允许所有类型的LSA通过,包括Type-1路由器LSA、Type-2网络LSA、Type-3汇总LSA、Type-4 ASBR汇总LSA、Type-5外部LSA。Stub区域则是一条路走到黑——不允许Type-4和Type-5进来,ABR(区域边界路由器)会用一条默认路由(Type-3的0.0.0.0)代替外部路由,好处是区域内的LSDB规模小、路由器负担轻。但Stub区域有个硬伤:它不能引入外部路由。也就是说,Stub区域里的路由器不能当ASBR,不能把区域外的路由重分发进来。
NSSA就是为了解决这个矛盾而生的。它既想享受Stub区域那种"不接收Type-5外部LSA"的清爽,又需要有能力引入少量外部路由。于是协议设计者在NSSA里引入了一种新的LSA类型——Type-7 LSA,也叫NSSA外部LSA。Type-7只能在NSSA区域内部泛洪,到了ABR那里,由ABR负责把它翻译成Type-5 LSA再送到骨干区域去。这个"翻译"动作,就是NSSA区域路由计算的核心环节之一。
我用一个生活化的类比来解释:普通区域像一个开放的市场,什么货都能进来;Stub区域像一个封闭小区,外面的大宗货物一律不进,只在门口放一个"默认提货点";NSSA区域则像一个保税区,外面的货不能直接进来卖,但区内的企业可以自己生产货(引入外部路由),生产出来的货要出口到外面市场,得经过海关(ABR)重新贴标(Type-7翻译成Type-5)。
2.2 Type-7 LSA的字段结构与关键位
Type-7 LSA的格式和Type-5 LSA非常相似,但多了几个NSSA特有的字段。我把关键字段列一下:
| 字段 | 含义 | 对路由计算的影响 |
|---|---|---|
| Link State ID | 外部网络地址 | 标识这条外部路由 |
| Advertising Router | 产生Type-7的ASBR的Router ID | 标识谁引入的 |
| Network Mask | 外部网络的掩码 | 决定路由前缀长度 |
| Forwarding Address | 转发地址 | 决定下一跳走向 |
| External Metric | 外部度量值 | 影响选路 |
| External Metric Type | 度量类型(E1/E2) | 影响度量累加方式 |
| P-bit | Propagate位 | 决定ABR是否翻译成Type-5 |
| T-bit | Type-7翻译位 | 标识是否由翻译产生 |
这里面最值得关注的就是Forwarding Address和P-bit。P-bit全称是Propagate bit,当它置1时,ABR才会把这条Type-7翻译成Type-5发到骨干区域;如果P-bit为0,这条Type-7就只在NSSA内部有效,不会被翻译出去。而FA字段则直接决定了NSSA内部路由器计算这条外部路由时,下一跳指向哪里。
2.3 NSSA区域内的LSA泛洪规则
NSSA区域内部允许泛洪的LSA类型包括:Type-1、Type-2、Type-3,以及Type-7。Type-4和Type-5被禁止进入。ABR会向NSSA区域内注入一条默认路由(Type-7的0.0.0.0/0),这样区域内的路由器即使没有具体的外部路由,也能通过默认路由出去。
这里有个容易搞混的点:NSSA的ABR向区域内注入默认路由,用的是Type-7 LSA,而不是Type-3。这和Stub区域用Type-3注入默认路由不一样。原因是NSSA区域内需要统一用Type-7来承载外部信息,包括默认路由。这个细节在做路由过滤和策略的时候非常关键,因为你要匹配的是Type-7而不是Type-3。
注意:NSSA区域内的默认路由是否产生,取决于ABR上的配置。默认情况下,NSSA ABR不会自动注入默认路由,需要显式配置
area X nssa default-information-originate。这一点和Stub区域不同,Stub区域的ABR是自动注入默认路由的。
3. FA值的行为逻辑与置位条件深度拆解
3.1 FA为0.0.0.0意味着什么
FA字段为0.0.0.0,是NSSA外部路由最常见的一种情况。它的含义是:这条外部路由的下一跳,应该通过产生这条Type-7 LSA的ASBR来到达。换句话说,NSSA区域内的路由器收到这条Type-7之后,会去查ASBR的Router ID对应的路由,然后朝着ASBR的方向转发。
这个逻辑听起来简单,但在实际转发路径上会带来一个"绕行"效果。假设NSSA区域内有R1、R2、R3三台路由器,R3是ASBR,引入了一条外部路由。R1收到Type-7后,FA为0.0.0.0,那么R1会把下一跳指向R3。即使R1和R2之间有一条更近的路径可以到达外部网络,R1也不会走那条路,因为FA没有告诉它"你可以直接去那个地址"。
什么时候FA会是0.0.0.0?通常出现在以下场景:ASBR引入外部路由时,没有在引入接口上启用OSPF,或者引入接口的地址不在OSPF的network范围内。这时候ASBR无法提供一个有效的转发地址,只能把FA置为0.0.0.0,让流量绕到自己这里。
3.2 FA为非零地址的触发条件
FA被置为非零地址,需要满足几个条件。我把它总结成一张速查表:
| 条件编号 | 条件描述 | 说明 |
|---|---|---|
| C1 | 引入外部路由的接口启用了OSPF | 接口必须在OSPF的network声明范围内 |
| C2 | 该接口不是被动接口 | passive-interface会导致FA无法置位 |
| C3 | 该接口的网络类型不是Point-to-Point或Point-to-Multipoint | 这两种网络类型下FA行为有特殊处理 |
| C4 | 接口地址与外部路由的下一跳在同一网段 | 确保FA地址可达 |
当这些条件满足时,ASBR会把引入接口的IP地址填入FA字段。NSSA区域内的路由器收到Type-7后,看到FA非零,就会直接朝着FA地址转发,而不再绕到ASBR。
这个差异在拓扑中的体现非常明显。我做过一个实验,拓扑是这样的:R1和R2在NSSA区域内,R2是ASBR,R2上有一个Loopback接口引入了一条外部路由。当Loopback接口没有启用OSPF时,FA为0.0.0.0,R1去往外部路由的下一跳是R2的Router ID对应地址;当Loopback接口启用OSPF后,FA变成了Loopback的地址,R1去往外部路由的下一跳直接变成了Loopback地址对应的直连路径。
3.3 FA地址的可达性计算过程
FA非零之后,NSSA区域内的路由器并不是无脑信任这个地址,它需要先确认FA地址是可达的。可达性计算的过程是这样的:
第一步,路由器收到Type-7 LSA,提取FA字段。第二步,在OSPF的LSDB中查找FA地址对应的路由。这个查找是在OSPF内部路由(Type-1和Type-2计算出来的路由)中进行的,不会去查外部路由。第三步,如果找到了匹配的路由,就用这条路由的下一跳作为转发下一跳;如果没找到,这条Type-7路由会被标记为不可用,不会进入路由表。
这个机制保证了FA地址必须是OSPF域内可达的。如果FA地址是一个孤立的、没有通过OSPF宣告的网段,那么这条外部路由就不会被安装。这也是为什么在配置NSSA的时候,一定要确保引入接口的地址在OSPF的network范围内——不仅仅是为了FA置位,更是为了FA地址的可达性。
提示:在实际排障中,如果发现NSSA区域内的外部路由没有出现在路由表里,第一件事就是检查FA地址是否可达。用
show ip ospf database nssa-external查看Type-7的FA字段,然后在路由表里查这个地址有没有对应的OSPF路由。
3.4 P-bit与FA的联动关系
P-bit和FA虽然都是Type-7 LSA里的字段,但它们的作用维度不同。P-bit决定这条Type-7要不要被ABR翻译成Type-5传播到骨干区域,FA决定NSSA内部路由器怎么转发。两者之间有一个隐含的联动:当FA为0.0.0.0时,P-bit通常也会被置0,因为这条路由的转发信息依赖于ASBR本身,翻译到骨干区域后可能会引起次优路径。当FA非零时,P-bit通常置1,因为FA提供了一个独立的转发地址,翻译出去不会造成环路或次优。
但这个规则不是绝对的。在某些厂商的实现中,P-bit的置位还受到area X nssa translate相关配置的影响。我在实验中遇到过一种情况:FA非零但P-bit为0,原因是ABR上配置了nssa translate never,禁止了翻译动作。这时候Type-7只在NSSA内部有效,骨干区域完全看不到这条外部路由。
4. 完整实验拓扑与路由计算全流程验证
4.1 实验拓扑设计与地址规划
我设计的实验拓扑包含四台路由器,分两个区域。R1和R2在Area 0(骨干区域),R2和R3在Area 1(NSSA区域),R3和R4也在Area 1。R2是ABR,同时连接Area 0和Area 1。R3是NSSA区域内的ASBR,负责引入外部路由。R4是NSSA区域内的普通路由器,用来观察路由计算结果。
地址规划如下:
| 设备 | 接口 | IP地址 | 所属区域 |
|---|---|---|---|
| R1 | Lo0 | 1.1.1.1/32 | Area 0 |
| R1 | G0/0 | 10.0.12.1/24 | Area 0 |
| R2 | G0/0 | 10.0.12.2/24 | Area 0 |
| R2 | G0/1 | 10.0.23.2/24 | Area 1 |
| R3 | G0/0 | 10.0.23.3/24 | Area 1 |
| R3 | G0/1 | 10.0.34.3/24 | Area 1 |
| R3 | Lo1 | 3.3.3.3/32 | 引入的外部路由 |
| R4 | G0/0 | 10.0.34.4/24 | Area 1 |
| R4 | Lo0 | 4.4.4.4/32 | Area 1 |
R3上把Lo1的3.3.3.3/32通过重分发引入OSPF。我会分两个阶段做实验:第一阶段Lo1不启用OSPF,观察FA为0.0.0.0的行为;第二阶段Lo1启用OSPF,观察FA非零的行为。
4.2 基础配置与NSSA区域参数
先看R2的配置,它是ABR,需要配置NSSA区域:
R2(config)# router ospf 1 R2(config-router)# router-id 2.2.2.2 R2(config-router)# network 10.0.12.0 0.0.0.255 area 0 R2(config-router)# network 10.0.23.0 0.0.0.255 area 1 R2(config-router)# area 1 nssaR3的配置,它是ASBR:
R3(config)# router ospf 1 R3(config-router)# router-id 3.3.3.3 R3(config-router)# network 10.0.23.0 0.0.0.255 area 1 R3(config-router)# network 10.0.34.0 0.0.0.255 area 1 R3(config-router)# area 1 nssa R3(config-router)# redistribute connected subnetsR4的配置:
R4(config)# router ospf 1 R4(config-router)# router-id 4.4.4.4 R4(config-router)# network 10.0.34.0 0.0.0.255 area 1 R4(config-router)# area 1 nssa注意,R3上redistribute connected subnets会把所有直连网段都引入,包括Lo1的3.3.3.3/32。但此时Lo1没有在OSPF的network范围内,所以FA会是0.0.0.0。
4.3 第一阶段:FA为0.0.0.0时的路由计算
配置完成后,在R4上查看OSPF数据库中的Type-7 LSA:
R4# show ip ospf database nssa-external OSPF Router with ID (4.4.4.4) (Process ID 1) Type-7 AS External Link States (Area 1) LS age: 120 Options: (No TOS-capability, Type 7/5 capability) LS Type: AS External Link Link State ID: 3.3.3.3 (External Network Number) Advertising Router: 3.3.3.3 LS Seq Number: 80000001 Checksum: 0xABCD Length: 36 Network Mask: /32 Metric Type: 2 (Larger than any link state path) TOS: 0 Metric: 20 Forward Address: 0.0.0.0 External Route Tag: 0可以看到FA字段是0.0.0.0。再看R4的路由表:
R4# show ip route ospf O E2 3.3.3.3/32 [110/20] via 10.0.34.3, 00:01:23, GigabitEthernet0/0下一跳是10.0.34.3,也就是R3的接口地址。这是因为FA为0.0.0.0,R4需要把流量发给ASBR(R3)。在这个拓扑里,R4和R3直连,所以下一跳就是R3的接口地址。如果拓扑更复杂,比如R4和R3之间还有一台路由器,那么下一跳会指向中间路由器,但最终流量还是会绕到R3。
这里有一个关键点:FA为0.0.0.0时,NSSA区域内的路由器计算下一跳,用的是ASBR的Router ID对应的路由。在R4上,ASBR的Router ID是3.3.3.3,R4会去查3.3.3.3对应的OSPF路由。由于R3的Router ID地址没有单独宣告,R4查到的是10.0.34.0/24网段的路由,下一跳是10.0.34.3。所以最终路由表里显示的是via 10.0.34.3。
4.4 第二阶段:FA非零时的路由计算变化
现在把R3的Lo1接口加入OSPF:
R3(config)# router ospf 1 R3(config-router)# network 3.3.3.3 0.0.0.0 area 1再次在R4上查看Type-7 LSA:
R4# show ip ospf database nssa-external LS age: 45 Options: (No TOS-capability, Type 7/5 capability) LS Type: AS External Link Link State ID: 3.3.3.3 (External Network Number) Advertising Router: 3.3.3.3 LS Seq Number: 80000002 Checksum: 0xEFGH Length: 36 Network Mask: /32 Metric Type: 2 (Larger than any link state path) TOS: 0 Metric: 20 Forward Address: 3.3.3.3 External Route Tag: 0FA字段变成了3.3.3.3。再看R4的路由表:
R4# show ip route ospf O E2 3.3.3.3/32 [110/20] via 10.0.34.3, 00:02:45, GigabitEthernet0/0咦,下一跳还是10.0.34.3?这不是和FA为0.0.0.0时一样吗?别急,这是因为在这个简单拓扑里,FA地址3.3.3.3对应的路由下一跳恰好也是10.0.34.3。要看出差异,需要把拓扑改一下,让FA地址的可达路径和ASBR的路径不同。
4.5 构造FA路径与ASBR路径不同的场景
我修改一下拓扑,在R3和R4之间加一台R5,R5也在Area 1。R3连接R5,R5连接R4。同时R3的Lo1地址改为5.5.5.5/32,并且这个地址通过R5宣告到Area 1。这样FA地址5.5.5.5的可达路径是R4->R5->R3,而ASBR的Router ID路径也是R4->R5->R3,看起来还是一样。要真正区分,需要让FA地址的可达路径不经过ASBR。
更直接的办法是:在R3上引入一个外部网段,这个网段的下一跳是R5,但ASBR是R3。这样FA地址会指向R5的接口地址,而ASBR是R3。NSSA内部路由器收到Type-7后,FA非零,下一跳会指向R5,而不是R3。
我重新设计一个场景:R3上有一个静态路由ip route 6.6.6.0 255.255.255.0 10.0.35.5,指向R5。然后把这条静态路由重分发进OSPF。R3的G0/2接口连接R5,地址是10.0.35.3/24,这个接口启用了OSPF。重分发之后,Type-7的FA字段会是10.0.35.3(R3连接R5的接口地址),而不是R3的Router ID。
在R4上查看路由表:
R4# show ip route ospf O E2 6.6.6.0/24 [110/20] via 10.0.45.5, 00:00:30, GigabitEthernet0/1下一跳是10.0.45.5,也就是R5的接口地址。而如果FA为0.0.0.0,下一跳会指向R3。这就是FA值对转发路径的实际影响:FA非零时,流量直接朝着FA地址走,不再绕到ASBR。
这个实验做下来,我对FA的理解就非常清晰了。FA的本质是告诉NSSA区域内的路由器:"这条外部路由的入口不在ASBR那里,而在我指定的这个地址。" 这个机制在ASBR和外部网络入口不在同一台设备上时特别有用,可以避免流量绕行。
5. 常见问题排查与实战避坑指南
5.1 Type-7 LSA不产生或P-bit为0的排查
在实际项目中,最常见的问题就是NSSA区域内的外部路由没有传播出去,或者传播出去了但骨干区域看不到。排查思路如下:
先确认ASBR上是否真的产生了Type-7 LSA。用show ip ospf database nssa-external查看,如果没有任何输出,说明重分发没有生效。检查重分发配置是否正确,redistribute命令是否匹配到了路由,subnets关键字是否加上(对于非自然分类网段必须加)。
如果Type-7产生了但P-bit为0,检查ABR上的翻译配置。默认情况下,ABR会自动翻译P-bit为1的Type-7。如果配置了area X nssa translate never,翻译会被禁止。另外,如果NSSA区域内有多个ABR,翻译动作由Router ID最大的ABR执行,其他ABR不翻译。这个规则在双ABR场景下容易导致困惑,需要确认哪台ABR是翻译器。
5.2 FA地址不可达导致路由不安装
FA地址不可达是NSSA排障中的高频问题。现象是:Type-7 LSA在数据库里能看到,FA字段也有值,但路由表里就是没有这条外部路由。原因通常是FA地址没有通过OSPF宣告,或者宣告在了错误的区域。
排查步骤:第一步,在收到Type-7的路由器上,用show ip route <FA地址>查看是否有OSPF路由。如果没有,说明FA地址不可达。第二步,回到ASBR上,检查引入接口是否在OSPF的network范围内。第三步,检查该接口是否被配置为passive-interface,被动接口不会参与OSPF邻居建立,也不会产生FA。第四步,检查接口的网络类型,Point-to-Point和Point-to-Multipoint类型下FA行为有特殊处理,可能需要调整。
注意:在某些厂商的实现中,如果FA地址是0.0.0.0,路由器会尝试用ASBR的Router ID来计算下一跳。如果ASBR的Router ID地址也没有通过OSPF宣告,这条路由同样不会安装。所以确保ASBR的Router ID地址可达,也是一个隐藏的检查点。
5.3 双ABR场景下的翻译器选举问题
NSSA区域如果有两个ABR同时连接骨干区域,翻译器的选举就变得很重要。选举规则是:Router ID最大的ABR成为翻译器。但如果Router ID最大的ABR上配置了nssa translate never,它会放弃翻译,由次大的ABR接管。这个切换过程中,Type-5 LSA可能会短暂消失,导致骨干区域的路由抖动。
我在一个项目里遇到过这个问题:两台ABR的Router ID分别是10.0.0.1和10.0.0.2,10.0.0.2是翻译器。后来10.0.0.2被重启,翻译器切换到10.0.0.1,切换期间骨干区域的路由消失了大约3秒。对于延迟敏感的业务,这3秒就是事故。解决办法是显式指定翻译器,或者让两台ABR的Router ID差距拉大,避免频繁切换。
5.4 常见问题速查表
| 现象 | 可能原因 | 排查命令 | 解决方法 |
|---|---|---|---|
| Type-7不产生 | 重分发未生效 | show ip ospf database nssa-external | 检查redistribute配置和subnets关键字 |
| P-bit为0 | 翻译被禁止 | show ip ospf database nssa-external | 检查area X nssa translate配置 |
| FA不可达 | 引入接口未启用OSPF | show ip route <FA> | 将引入接口加入OSPF network |
| 路由不安装 | FA地址无匹配路由 | show ip route <FA> | 确保FA地址在OSPF域内可达 |
| 骨干区域看不到路由 | 翻译器未工作 | show ip ospf | 检查ABR的翻译器状态 |
| 下一跳绕行 | FA为0.0.0.0 | show ip ospf database nssa-external | 启用引入接口的OSPF,使FA置位 |
5.5 实操心得:FA值的设计建议
根据我自己的经验,在设计NSSA区域时,FA值的行为应该提前规划好。如果希望NSSA内部流量直接朝着外部网络入口走,就要确保引入接口启用OSPF,让FA置位。如果希望流量统一绕到ASBR,那就保持FA为0.0.0.0。两种方式没有绝对的好坏,取决于网络架构。
对于有多个外部入口的NSSA区域,FA非零可以带来更优的路径选择。比如NSSA区域有两个ASBR,分别连接不同的外部网络,如果FA都置位,NSSA内部路由器可以根据FA地址的可达性选择最近的入口。如果FA都是0.0.0.0,所有流量都会绕到各自的ASBR,可能造成次优路径。
还有一个细节:FA地址最好使用Loopback接口的地址,而不是物理接口地址。Loopback接口稳定,不会因为物理链路故障而消失。如果FA地址是物理接口地址,接口一down,FA就不可达,外部路由就会撤销,引起路由抖动。这个坑我在现网里踩过,后来全部改成Loopback地址作为FA,稳定性提升明显。
6. 从实验到现网:NSSA部署的几点个人体会
把实验做透之后,回到现网部署NSSA,还有几个点值得注意。第一,NSSA区域的默认路由注入要显式配置,不要指望ABR自动产生。我见过有人配了NSSA但忘了加default-information-originate,结果区域内的路由器没有默认路由,上不了外网。第二,NSSA区域内的路由器数量不宜过多,虽然NSSA比普通区域轻量,但Type-7的泛洪和翻译仍然会消耗ABR的资源。一般建议NSSA区域内的路由器不超过20台,超过的话考虑拆分区域。
第三,Type-7到Type-5的翻译是有开销的,ABR需要维护翻译后的Type-5 LSA,并且要在Type-7撤销时及时撤销Type-5。如果NSSA区域内的外部路由频繁抖动,ABR的CPU会受到影响。对于路由条目特别多的场景,可以考虑用nssa translate always强制翻译,或者用路由汇总减少Type-7的数量。
最后说一个我自己的习惯:每次配完NSSA,我都会在ABR和ASBR上分别抓一次LSDB快照,对比Type-7和Type-5的对应关系。这个习惯帮我发现过好几次P-bit异常和FA置位失败的问题。LSDB不会骗人,路由表有时候会因为各种原因隐藏真相,但LSDB里的字段是协议计算的直接结果。把LSDB看懂了,NSSA的路由计算就没有秘密了。