OSPF(Open Shortest Path First,开放最短路径优先)是链路状态型内部网关协议(IGP)的两大代表之一,另一派是 IS-IS(RFC 1142)——两者思想同源、实现各异:IS-IS 直接跑在二层、靠 TLV 灵活扩展,OSPF 跑在 IP 之上、与 TCP/IP 生态贴合更紧,是企业网与运营商域内最常见的 IGP。它与域间协议 BGP 的分工是经典的 IGP/EGP 之分:OSPF 管「AS 内部怎么最快、无环地到」,BGP 管「AS 之间按策略怎么走」(对照 BGP 页 第 1 节)。
链路状态协议的工作循环可以概括为一行三步——这正是 RFC 2328 §4 给出的协议骨架:
因为所有人拿的是同一张地图、跑的是同一个算法,计算结果天然一致且无环——这是链路状态相对距离矢量(RIP 一类)的根本优势:收敛快、无计数到无穷、拓扑完全可见。代价是每台路由器都要保存全网 LSDB 并跑 SPF,因此 OSPF 用「区域」做层次化来控制规模(第 7 节)。
OSPF 报文不经过 TCP 或 UDP,直接封装在 IP 数据报里,IP 协议号 89。这意味着传输层能给的可靠性它一样都拿不到:没有握手、没有确认、没有重传、没有排序。OSPF 的对策是自给自足:
这与 BGP 恰成鲜明对照:BGP 把可靠性整体外包给 TCP(TCP/179,见 BGP 页),OSPF 则是在裸 IP 上自己造了一个迷你可靠层。抓包时两者长相也完全不同——BGP 是 TCP 流,OSPF 是独立的 IP 协议号。
在具备组播/广播能力的网络上,OSPF 大量使用链路本地组播(只走一跳,不参与组播路由,RFC 2328 §4.5):
| 组播地址 | 谁监听 | 谁向它发 |
|---|---|---|
224.0.0.5(AllSPFRouters)FF02::5(v3) | 所有 OSPF 路由器 | Hello 永远发往此地址;DR/BDR 发出的 LSU/LSAck 也发到这里(§9.4/§8.1)。 |
224.0.0.6(AllDRouters)FF02::6(v3) | 仅 DR 与 BDR | DROther 把 LSU/LSAck 发到这里——先把变化汇报给 DR/BDR,再由 DR 归并后从 224.0.0.5 广播给全员(第 6 节)。 |
OSPFv1(RFC 1131,1989)很快被 v2 取代;v2 历经 RFC 1247 → 1583 → 2178 三次修订,定型于 RFC 2328(1998 年 4 月,STD 54),服务 IPv4,是今天所有 OSPFv2 实现的基准。RFC 5340(2008 年 7 月) 定义服务 IPv6 的 OSPFv3:算法骨架(五种报文、邻居状态机、DR 选举、区域模型、LSA 新旧判定)原封不动,报文与 LSA 则借 v6 之机做了重构——地址信息从报文与主干 LSA 中剥离、认证交还 IPsec、泛洪范围显式编码(本文第 8 节专章对照)。
Router ID(RID)是一个 32 位无符号整数,按点分十进制书写(如 10.0.0.1),在 OSPF 域内唯一标识一台路由器。它只作标识、不作寻址——协议报文的收发从不依赖 RID 可达。选取规则 RFC 只要求「唯一」(附录 C.1 建议可取路由器上最大或最小的 IP 地址),厂商惯例是:手工配置 > 最高 loopback 接口地址 > 最高活动接口地址。RID 一经选定应保持稳定:变更 RID 需重启 OSPF 进程,且应先把自己产生的 LSA 从域内冲刷掉,否则旧 RID 名下的 LSA 会在全网残留最长 MaxAge(1 小时,附录 B)。邻居建连的 DBD 主从仲裁、DR 选举决胜、LSA 的产生者标识,全都围绕 RID 展开。
OSPF 的路径度量是 Cost:每个接口一个出向代价(必须大于 0,附录 C.3),随 Router-LSA 泛洪;一条路径的代价 = 沿途各出接口 Cost 之和,SPF 即按总代价最小选路。RFC 2328 没有规定 Cost 的取值算法,厂商默认是「参考带宽 ÷ 接口带宽」,而参考带宽默认值为 10⁸ bps = 100 Mbps——后果是 100M、1G、10G 接口的 Cost 全都是 1,SPF 无法区分快慢链路。现代网络必须把参考带宽调大(如 100G),并保证全网一致,否则同一张地图上的「尺子」各不相同,选路结果互相矛盾。
多路访问网上,DROther 之间只做到 2-Way 邻居,邻接全部收敛到 DR/BDR 身上——这正是 DR 存在的意义(第 6 节),也是「邻居一堆、邻接两对」这一常见现象的出处。
LSDB 的规模就是泛洪与 SPF 的规模,因此 OSPF 把路由域划分为若干区域:1、2 类 LSA 只在本区域泛洪,SPF 也只算本区域的详细拓扑;区域之间由 ABR 用 3 类摘要 LSA 转述路由,等于把另一个区域「折叠」成几条距离矢量式的路由。两条铁律:必须存在骨干区域 Area 0(Area ID 0.0.0.0);所有非骨干区域必须直连骨干,区域间流量一律经骨干中转(详见第 7 节)。两个关键角色:ABR(Area Border Router,坐跨区域边界,做 3/4 类汇总)与 ASBR(AS Boundary Router,把外部路由以 5/7 类 LSA 注入 OSPF 域)。
每个 OSPF 报文都以一个 24 字节标准首部开头(A.3.1),其后按类型(Type 字段)接 Hello / DBD / LSR / LSU / LSAck 五种报文体。下图为交互式首部结构图:把鼠标悬停在任意字段上即可在下方说明栏查看详解;单击字段可以「钉住」当前说明,方便滚动阅读,再次单击取消。
24 字节首部之后的内容由 Type 字段决定。五种报文各司其职,串起「发现邻居 → 同步数据库 → 泛洪更新」的完整生命周期:
| Type | 报文 | 职责 | 要点 |
|---|---|---|---|
1 | Hello | 发现/维持邻居;协商建邻参数;选举 DR/BDR | 默认 10s 一发(NBMA 30s);Dead 默认 40s |
2 | Database Description | LSDB 摘要交换(目录比对);主从协商 | MS/M/I 位 + DD 序列号;含 Interface MTU |
3 | Link State Request | 按三元组点名索取缺失/过旧的 LSA | 12 字节一条,可多条合并 |
4 | Link State Update | 携带完整 LSA 泛洪/应答 | 一包可装多条 LSA;大包对 MTU 敏感 |
5 | Link State Acknowledgment | 显式确认 LSA,撑起可靠泛洪 | OSPF 自建的「TCP ACK」 |
Hello 是出现频率最高、也最「多事」的报文:邻居发现、参数协商、DR 选举三副担子一肩挑。报文体字段如下:
| 字段 | 位数 | 说明 |
|---|---|---|
| Network Mask | 32 | 接口掩码;广播网两端必须一致(p2p/虚链路豁免) |
| HelloInterval | 16 | 默认 10s(NBMA 30s);全网必须一致 |
| Options | 8 | 能力位:E/N/P/DC…;E、N 位邻居间必须一致 |
| Rtr Pri | 8 | DR 优先级,默认 1,0 = 弃权 |
| RouterDeadInterval | 32 | 默认 40s(4×HelloInterval);全网必须一致 |
| Designated Router | 32 | 我眼中的 DR(接口 IP 标识);未选出 = 0.0.0.0 |
| Backup DR | 32 | 我眼中的 BDR;DR 失效即接任 |
| Neighbor | 32×n | 我见过的邻居 RID 列表;互见 = 2-Way |
LSDB 是「地图」,LSA(Link State Advertisement)就是图元:每台路由器把自己的局部状态(链路、邻居、代价)写成一条条 LSA 泛洪出去,全网收敛后,每台路由器的 LSDB 里装着同一个区域内所有 LSA 的同一份拷贝。所有 LSA 都以一个 20 字节公共首部(A.4.1)开头——它足以唯一标识一条 LSA(LS type + Link State ID + Advertising Router 三元组),并判定多个实例的新旧(LS age + 序列号 + 校验和)。悬停下图各字段查看详解:
| 类型 | 名称 | 谁产生 | 泛洪范围 | 内容 |
|---|---|---|---|---|
1 | Router-LSA | 每台路由器 | 本区域 | 我的链路、邻居与代价(拓扑主体) |
2 | Network-LSA | DR | 本区域 | 多路访问网的成员列表(伪节点) |
3 | Summary-LSA(网络) | ABR | 区域间 | 到其他区域网段的路由(区域间路由) |
4 | Summary-LSA(ASBR) | ABR | 区域间 | ASBR 的位置(怎么到 ASBR) |
5 | AS-external-LSA | ASBR | 全 OSPF 域 | 外部路由;E1/E2 两种度量 |
7 | NSSA-LSA | NSSA 内 ASBR | NSSA 区域 | NSSA 的外部路由;ABR 转译为 5 类 |
每个被发现的邻居由一台独立的状态机驱动(§10.1 定义 8 个状态、§10.2 定义迁移事件)。正向主线是「Hello 互见 → 主从与序列号商定 → 摘要互换 → 补缺同步 → 完全邻接」;任何环节失败都有明确的回退路径。图中实线为正向建邻流程,虚线为回退与 NBMA 分支;悬停状态节点查看含义与排障提示,单击可钉住。
| 状态 / 迁移 | 触发事件 | 含义与动作 |
|---|---|---|
| Down → Attempt | Start(仅 NBMA) | 对配置的邻居改按 HelloInterval 主动单播 Hello。 |
| Down / Attempt → Init | HelloReceived | 收到对方 Hello;把对方列入本端 Hello 的 Neighbor 字段。 |
| Init → 2-Way | 2-WayReceived | 在对方 Hello 的 Neighbor 列表里看到自己 → 双向确认。 |
| 2-Way(保持) | AdjOK? 否决 | 无需建邻接:DROther 之间的常态终点。 |
| 2-Way → ExStart | AdjOK? 通过 | 决定建邻接:互发空 DBD(I/M/MS=1)起协商。 |
| ExStart → Exchange | NegotiationDone | 主从商定(RID 大者为主)+ DD 初始序列号确定。 |
| Exchange → Loading | ExchangeDone | 双方 DBD 摘要(M 位均清 0)交换完毕,请求清单就绪。 |
| Loading → Full | LoadingDone | 请求清单清空,LSDB 同步完成 → 完全邻接。 |
| ≥2-Way → Init | 1-Way | 对方 Hello 里不再有我(对端重启/单向化)→ 推倒重来。 |
| Exchange/Loading → ExStart | SeqNumberMismatch / BadLSReq | DD 序列号错乱 / 请求到坏 LSA → 回 ExStart 重新协商。 |
| 任意 → Down | KillNbr / InactivityTimer / LLDown | 管理清除 / Dead 超时 / 链路 down → 邻接拆除。 |
在以太网这类多路访问网络上,若 n 台路由器两两建邻接,邻接数是 n(n−1)/2——10 台 45 条、50 台 1225 条;每条邻接都要同步 LSDB,一条 LSA 变化会在网内被两两互发、复制成平方级流量。指定路由器(Designated Router, DR)把星形代替全互联:
泛洪也随之收敛:DROther 把 LSU 发向 AllDRouters(224.0.0.6,只有 DR/BDR 收听),DR 归并后再发向 AllSPFRouters(224.0.0.5,全员收听)——一次扩散从 n² 份拷贝变成 2n 份。BDR 与全网同样建立 Full 邻接、与 DR 同步待命:DR 失效时 BDR 直接升任(再补选新 BDR),邻接与 LSDB 无需推倒重来。DR 的另一职责是代表该网络产生 Network-LSA(2 类),把多路访问网抽象成 SPF 图里的伪节点(4.1 表)。
NBMA(帧中继/ATM 一类)没有组播能力:Hello 只能对手工配置的邻居单播发送(Down 态按 PollInterval 低频、Attempt 态起按 HelloInterval);DR 选举要求候选路由器之间具备全互联可达,否则选出的 DR 可能与部分 DROther 不通——部分互联的 NBMA 拓扑要刻意用优先级把 DR 资格钉在全互联节点上,或改用点到多点(Point-to-MultiPoint,不选 DR)组网。
OSPF 的两级层次结构有一条不可违背的拓扑铁律(§3.1):必须存在骨干区域 Area 0(Area ID 0.0.0.0),所有非骨干区域都必须直连骨干,区域间流量一律经骨干中转。原因藏在算法里:区域内部靠链路状态算法(1/2 类 LSA + SPF),天然无环;但区域之间,ABR 只把 3 类摘要 LSA「注入」邻区——对另一个区域而言,这本质上是距离矢量信息(只知道 ABR 声明的代价,看不见对端拓扑)。距离矢量的防环不能靠算法,只能靠结构:星形的区域拓扑(一切过骨干)+ 3 类 LSA 的使用规则(如 ABR 只使用来自骨干的 3 类 LSA 参与计算,§16.2),环路便无从形成。
| 类型 | 来源 LSA | 代价计算与要点 |
|---|---|---|
| O(区域内) | 1 / 2 类 | SPF 全图最短路;优先级最高 |
| O IA(区域间) | 3 / 4 类 | 到 ABR 的代价 + ABR 声明代价 |
| O E1 | 5 类 | 外部度量 + 内部代价(多出口可比) |
| O E2(默认) | 5 类 | 只看外部度量;内部代价仅平局决胜 |
| O N1 / O N2 | 7 类 | NSSA 版 E1/E2;出区转 5 类 |
Stub 系列区域的设计动机一致:边缘区域不需要知道全域的每一条外部路由,一条默认路由足矣——于是把特定类型的 LSA 拒之门外,换来 LSDB 与 SPF 的规模缩减。
| 区域类型 | 拒什么 | 默认路由怎么来 | 允许本区 ASBR 注入外部? |
|---|---|---|---|
| Stub | 5 类(连带 4 类) | ABR 注入 3 类默认(0.0.0.0/0) | ✘ 不允许 |
| Totally Stub | 5 类 + 3 类明细 | 仅留 3 类默认 | ✘ 不允许 |
| NSSA | 5 类 | ABR 注入默认(7 类或 3 类) | ✔ 允许(以 7 类) |
| Totally NSSA | 5 类 + 3 类明细 | 3 类默认 | ✔ 允许(以 7 类) |
OSPFv3(RFC 5340,2008 年 7 月)让 OSPF 服务 IPv6。它不是「v2 换个地址族」:借 v6 之机,报文与 LSA 做了一次「地址语义剥离」的重构;但算法骨架原封不动——LSA 首部格式、五种报文、邻居状态机、DR 选举、区域模型、新旧判定规则全部沿用 v2,会 v2 即会 v3 的九成。逐项差异对照如下(悬停行查看展开说明):
| 维度 | OSPFv2(RFC 2328) | OSPFv3(RFC 5340) |
|---|---|---|
| 运行粒度 | 按 IP 子网(掩码检查) | 按链路;Hello 带 Interface ID;多实例用 Instance ID 区分 |
| Router/Network-LSA 内容 | 拓扑 + 地址前缀合一 | 只留拓扑;前缀剥离到 8 类 Link-LSA 与 9 类 Intra-Area-Prefix-LSA |
| 认证与校验 | AuType 0/1/2 + 标准 IP 校验和(协议自带) | AuType/Auth 字段删除,认证交 IPsec;校验复用 IPv6 伪首部校验和 |
| LSA 类型编码 | 小整数 1–5(+7),范围由类型隐含 | U 位 + S2/S1 泛洪范围位 + 功能码(0x2001 起) |
| 源地址 / 组播 / 邻居标识 | 接口 IPv4 为源;224.0.0.5 / 224.0.0.6;广播网邻居按接口 IP 标识 | 链路本地地址为源;FF02::5 / FF02::6;邻居一律按 RID 标识 |
| 杂项 | — | Options 扩为 24 位(R/V6 位等);各类 ID 保持 32 位 |
BGP 抓包找 tcp.port == 179 的思路在这里完全失效——OSPF 直接坐在 IP 上,协议号 89:
抓包时的判读要点:Hello 周期出现(默认 10 秒)属背景噪声;建邻或拓扑变化时会看到 DBD → LSR → LSU → LSAck 的突发序列;广播网上注意目的地址的分流——全员收 224.0.0.5,只有 DR/BDR 收 224.0.0.6。
抓包对照:若看到双方反复互发空 DBD 而始终进不了 Exchange——回到第 5 节的提醒,先查 MTU 与 RID;若 LSU 发出后迟迟不见 LSAck、同一 LSU 按约 5 秒周期重现——是丢包或对端处理不过来。
| 现象 | 头号嫌疑 | 怎么验证 |
|---|---|---|
| 邻居起不来 | 掩码 / Hello·Dead 区间 / Area / 认证 / Stub 标志不一致;网络类型不匹配;组播被拦 | 两端 show ospf interface 比对参数;抓包看 Hello 是否互发 |
| 卡 Init | 单向 Hello:ACL / 组播被拦 / 二层单通 | 抓包看 Neighbor 字段是否互见 |
| 卡 2-Way | 优先级全 0(故障)/ DROther 之间(正常) | show ospf neighbor 看角色与优先级 |
| 卡 ExStart / Exchange | MTU 不匹配(最经典);RID 冲突 | 两端 show interface 比 MTU;比 RID;抓包看是否反复空 DBD |
| 卡 Loading | LSR 重传:MTU / 丢包 / LSDB 过大 | 抓包看 LSR 重传;show 看 LSDB 规模 |
| Full 但路由不进表 | 区域规则 / LSA 过滤 / 转发地址不可达 / AD 压制 | show ospf database 查 LSA 是否存在;查到 ASBR / 转发地址的可达性 |
| 邻居反复震荡 | 链路抖动 / 对端 CPU / 计时器过激 | 接口误码统计;对端 CPU;考虑 BFD |
| 命令 | 看什么 |
|---|---|
show ip ospf neighbor | 邻居 RID、状态(FULL/2-WAY/EXSTART…)、Dead 倒计时、邻居地址与接口;DR/BDR/DROTHER 角色。 |
show ip ospf interface [brief] | 接口的区域、网络类型、Cost、Hello/Dead 计时器、DR/BDR 是谁、邻居数——参数匹配排查第一站。 |
show ip ospf database | LSDB 分类浏览(router/network/summary/external/nssa);… adv-router x.x.x.x 追踪某 LSA 的产生者。 |
show ip route ospf | 装进路由表的 O 家族:O / O IA / O E1 / O E2 / O N1 / O N2 及各条代价。 |
show ipv6 ospf … | v3 对应族(neighbor / interface / database / route)。 |
| 术语 | 含义 |
|---|---|
RID(Router ID) | 32 位路由器标识,点分十进制书写;唯一即可,选取惯例:手工 > 最高 loopback > 最高活动接口;主从仲裁与 DR 决胜的依据。 |
LSA | 链路状态通告:LSDB 的图元,20 字节公共首部 + 类型主体;v2 类型 1–5(+7),v3 编码 U/S2/S1 位并新增 8/9 类。 |
LSDB | 链路状态数据库:一个区域内所有路由器持有的同一副「地图」,SPF 的输入。 |
SPF / Dijkstra | 最短路径优先算法:以自己为根在 LSDB 上算最短路树(§16.1);拓扑变化触发(可增量)。 |
Cost | 接口出向代价(>0);厂商默认 = 参考带宽 ÷ 接口带宽,参考带宽默认 10⁸ bps,现代网络需调大。 |
邻居 / 邻接 | 邻居 = Hello 互见(≥2-Way);邻接 = LSDB 同步完成(Full),只有邻接交换 LSA、参与泛洪。 |
Area 0(骨干区) | Area ID 0.0.0.0;所有非骨干区域必须直连骨干,区域间流量经骨干中转。 |
ABR | 区域边界路由器:坐跨区域边界,产生 3/4 类摘要 LSA,执行区域间路由转述与 LSA 过滤。 |
ASBR | 自治系统边界路由器:把外部路由以 5 类(或 NSSA 内 7 类)LSA 注入 OSPF 域。 |
DR / BDR / DROther | 多路访问网的指定路由器 / 备份指定路由器 / 其余路由器;DR 产生 2 类 LSA 并收敛泛洪,BDR 待命接任。 |
Hello / Dead | HelloInterval(默认 10s,NBMA 30s)与 RouterDeadInterval(默认 4 倍 = 40s);邻居保活计时器,全网须一致。 |
2-Way | 邻居状态机第三态:Hello 互见、双向确认;DROther 之间的常态终点。 |
ExStart / Exchange / Loading / Full | 邻接建立四段:主从与 DD 序列号商定 → DBD 摘要互换 → LSR/LSU/LSAck 补缺 → 完全邻接。 |
LS Sequence Number | LSA 新旧序号:0x80000001 起每次 +1,越大越新,上限 0x7fffffff。 |
MaxAge / LSRefreshTime | 3600s:LSA 寿命上限,到期泛洪删除;1800s:产生者主动刷新周期。 |
E1 / E2 | 5 类外部路由两种度量:E1 = 外部 + 内部代价(多出口可比);E2(默认)= 只看外部;E1 优先于 E2。 |
Stub / NSSA | 特殊区域:Stub 拒 5 类、默认路由兜底、不许有 ASBR;NSSA(RFC 3101)允许 7 类注入外部路由,ABR 转译为 5 类。 |
Virtual Link | 虚链路:穿越普通区域把远端 ABR 逻辑焊回骨干的点对点隧道;设计上是补丁。 |
NBMA | 非广播多路访问网(帧中继/ATM):无组播,邻居需手工配置,Attempt 态与 PollInterval 轮询为其而设。 |
224.0.0.5 / 224.0.0.6 | AllSPFRouters / AllDRouters:v2 两个保留组播;v3 对应 FF02::5 / FF02::6。 |
Instance ID | v3 首部新增的 8 位实例号:同一条链路跑多个 OSPF 实例时区分报文归属。 |
| 编号 | 内容 |
|---|---|
| RFC 2328 | OSPF Version 2,STD 54,1998-04。本文的主要依据(§4 概览、§7 邻接、§9.4 DR 选举、§10 状态机、§11 泛洪、§12 LSA、§13 LSDB、§16 SPF、附录 A.3 报文格式);废止 RFC 2178。 |
| RFC 5340 | OSPF for IPv6(OSPFv3),2008-07。第 8 节的依据(§2 差异清单、附录 A.4.2.1 类型编码)。原文附有若干已收录勘误(errata),对照实现细节时建议连同勘误一并阅读。 |
| RFC 1131 / 1247 / 1583 / 2178 | 沿革:OSPFv1(1989)→ v2 初版(1991)→ 两次修订(1994 / 1997)→ 2328 定型。配套分析文档 RFC 1245(协议分析)与 RFC 1246(部署经验)记录了早期设计决策。 |
| RFC 3101 | The OSPF Not-So-Stubby Area (NSSA) Option,2003-01:7 类 LSA 与 7 转 5 的定义;废止 RFC 1587。 |
| RFC 3137 | OSPF Stub Router Advertisement,2001-06:以 LSInfinity 通告自身「暂不可中转」,实现设备优雅上下线。 |
| RFC 3623 | Graceful OSPF Restart,2003-11:Grace LSA 支撑的重启不震荡机制(控制面重启、转发面不中断)。 |
| RFC 4750 | OSPF Version 2 Management Information Base,2006-12:v2 的 SNMP 管理信息库(替代 RFC 1850);运维监控取数的标准入口。 |
| RFC 1142 | IS-IS(OSI 域内路由协议):链路状态 IGP 的另一流派,直接承载于二层、TLV 结构易扩展——与 OSPF 对照阅读最能看清「链路状态」这一思想的两种工程化身。 |