Appearance
OSPF 路由协议(链路状态)
2026 大纲 四(五)4 OSPF,同时是 四(二)3 链路状态路由算法在具体协议上的落地。链路状态算法本身的推导(为什么交换"原料"、Dijkstra 每步"挑最小就能定死"的反证、LS 为什么反而开销小)在《路由算法》。
一、名字里有两个坑
RIP 那一篇的结论是:它的全部麻烦都来自"报距离不报路径"。OSPF 换了个思路——不报结论,报原料,让每台路由器自己拿着完整地图算。这一篇讲这个思路落成协议以后的样子。
先把名字拆开。Open 表明这个协议不受某一家厂商控制、是公开发表的;SPF 是因为它使用了 Dijkstra 提出的最短路径算法。
第一个坑就在"最短路径优先"这五个字上。 它不是 OSPF 独有的目标——所有在自治系统内部使用的路由选择协议(包括 RIP)都是要寻找一条最短路径。OSPF 只是一个协议的名字。两者的区别在怎么找,不在找什么。
第二个坑在"链路状态"到底指什么。 它说明的是:本路由器和哪些路由器相邻、以及该链路的度量(metric)是多少。这个度量可以表示费用、距离、时延、带宽等,由管理员决定,也常被叫作"代价"。还有一处措辞要留意——这里的"链路"实际指的是"和这两个路由器都有接口的那个网络"。
代价能自己设定,带来了 RIP 完全做不到的灵活性:可以给每条路由指派不同的代价。同一条高带宽卫星链路,对非实时业务把代价设得很低、对时延敏感业务设得很高,于是对不同类型的业务就能算出不同的路由。商用网络里通常按带宽换算代价。
交互可视化
二、五种报文与邻居关系的建立
要让各机拿到同一张地图,先得把地图同步过去。OSPF 用五种报文完成这件事:
| 类型 | 名称 | 功能 |
|---|---|---|
| 1 | Hello(问候) | 发现和维护邻居关系,周期性发送 |
| 2 | DBD(数据库描述) | 向邻居概述 LSDB 里已有哪些项及其序号(只发摘要) |
| 3 | LSR(链路状态请求) | 请求自己缺少的那些项的详细信息 |
| 4 | LSU(链路状态更新) | 发送 LSA,是洪泛的核心报文 |
| 5 | LSAck(链路状态确认) | 对收到的 LSU 确认 |
为什么中间要插 DBD 和 LSR 两步? 所有路由器都把本地链路状态直接对全网广播,各自综合起来当然也能得出数据库,但这样做开销太大。改成"先换摘要、再按需请求",开销就从"全量广播"降到"只补差集"。
三、LSA 与可靠洪泛
每个路由器产生的 LSA 只描述它与哪些网络 / 路由器直接相连、各链路代价多少。里面没有任何"到远处有多远"的信息——这就是"发原料不发结论"的具体含义。
路由器收到一条新 LSA 后,从除接收接口外的所有接口转发出去。三个配套机制保证它不出错:
| 机制 | 解决什么问题 |
|---|---|
| 除来路外转发 | 防止立刻原路弹回,减少无谓复制 |
| 每条 LSA 带序列号 | 防止旧 LSA 覆盖新 LSA;也让收到重复副本的路由器识别出"这条我已经有了"从而停止再转发——这才是洪泛能终止的真正原因 |
| 收到 LSU 要发 LSAck | 洪泛是可靠的,确认丢失会重发 |
此外还规定每隔一段时间(如 30 分钟)刷新一次链路状态,即使什么都没变——防止数据库因丢包而长期偏离。
"洪泛"不是"广播",这两个词别混。 洪泛是网络层的逐跳复制转发,跨越多个网段;广播是数据链路层的一次发送、同一网段所有站都收到。效果都像"传遍所有节点",机制完全不同。
各机拿到同一张地图之后,还有一句必须说准:LSDB 相同,路由表各不相同。 同一区域内所有路由器的链路状态数据库内容完全一致(这是 OSPF 的关键不变量);但每台是以自己为根跑 Dijkstra 的,算出来的最短路径树自然不同。"数据库一致"和"路由表一致"是两回事。
在给定拓扑上把 Dijkstra 逐步跑一遍,以及断一条链路后最短路径树怎么变(想手动模拟一次收敛时展开)
拓扑(自造数据):某 OSPF 区域内 6 台路由器,求 R1 到各路由器的最短距离与路径。
| 步骤 | 本步定死 | 到 R2 | 到 R3 | 到 R4 | 到 R5 | 到 R6 | 说明 |
|---|---|---|---|---|---|---|---|
| 初始 | R1( | 5 | 3 | 只填 R1 的直连链路 | |||
| 1 | R3(3) | 5 | 3 | 9 | 松弛 R5: | ||
| 2 | R2(5) | 5 | 3 | 7 | 6 | 松弛 R4 得 7;R5 由 9 降为 | |
| 3 | R5(6) | 5 | 3 | 7 | 6 | 7 | 松弛 R6: |
| 4 | R4(7) | 5 | 3 | 7 | 6 | 7 | R4 与 R6 都是 7,任取其一。松弛 R6: |
| 5 | R6(7) | 5 | 3 | 7 | 6 | 7 | 全部定死,结束 |
第 2 步值得单独看:R5 的距离从 9 被改小成 6。先走 R3 看起来近(只要 3),但从 R3 再到 R5 要 6、总共 9;绕远一点先到 R2(5)再到 R5 只要 1、总共 6 更划算。Dijkstra 的松弛就是在不断推翻这种"贪一步"的错觉——但只推翻尚未定死的节点,已定死的永不回头。第 4 步两点距离相同时先定死哪个都不影响结果;若要做等价多路径负载均衡,这里正是两条等价路径的来源。
结果:R2=5(R1→R2)、R3=3(R1→R3)、R4=7(R1→R2→R4)、R5=6(R1→R2→R5)、R6=7(R1→R2→R5→R6)。核对 R1→R2→R5→R6
断链重算:R2–R5 故障,R2 与 R5 各产生新 LSA 洪泛到全区域,各路由器更新 LSDB 后重跑:
| 步骤 | 本步定死 | 到 R2 | 到 R3 | 到 R4 | 到 R5 | 到 R6 | 说明 |
|---|---|---|---|---|---|---|---|
| 初始 | R1(0) | 5 | 3 | 同上 | |||
| 1 | R3(3) | 5 | 3 | 9 | 松弛 R5: | ||
| 2 | R2(5) | 5 | 3 | 7 | 9 | 松弛 R4 得 7。R5 这次没被改小——R2–R5 已经没了 | |
| 3 | R4(7) | 5 | 3 | 7 | 9 | 11 | 松弛 R6: |
| 4 | R5(9) | 5 | 3 | 7 | 9 | 10 | 松弛 R6: |
| 5 | R6(10) | 5 | 3 | 7 | 9 | 10 | 结束 |
新旧对照:R2、R3、R4 全不变;R5 由 6 变 9(R1→R2→R5 改成 R1→R3→R5),R6 由 7 变 10(改走 R3)。核对:R1→R3→R5→R6
这一问真正要看的是:一条链路的变化只需要 R2 和 R5 各自重发一条 LSA(每条只描述本地几条链路),全区域收到后各自重跑一次 Dijkstra 就全部收敛。对比 RIP——同一件事要靠整张路由表一轮轮周期性传播,坏消息还可能陷入无穷计数。这就是"LS 用 CPU 和内存换收敛时间"的具体样子。
四、区域划分
要让 OSPF 用于很大的网络,就必须把洪泛范围关小:把一个自治系统再划分为若干区域(area),每个区域有一个 32 位标识符,区域内路由器最好不超过 200 个。好处是把洪泛法交换链路状态信息的范围局限于每一个区域,而不是整个自治系统。
| 角色 | 职责 |
|---|---|
| 区域边界路由器 ABR | 跨在两个区域之间,把本区域拓扑概括成摘要送进主干区域;每个区域至少一个 |
| 主干路由器 | 在主干区域内转发。一台主干路由器可以同时是 ABR |
| 自治系统边界路由器 ASBR | 在主干区域内,专门和其他自治系统交换路由信息(跑 BGP 那台) |
| 内部路由器 | 完全在某一非主干区域内,只知道本区域拓扑 |
划完区域,"每台路由器都知道全网拓扑"这句话就不再成立了。 准确说法是:区域内部的路由器只知道本区域的完整拓扑,不知道其他区域的拓扑情况,跨区信息由 ABR 概括后传过来。前面那句只在单区域时成立。
分层使协议更复杂,换来的是每个区域内部交换路由信息的通信量大大减小。所有非主干区域必须与主干区域相连,物理上无法直连时用虚链路"接"上去。
LSA 也因此分了类型,只要求理解洪泛范围:类型 1、2(Router-LSA 与 DR 产生的 Network-LSA)描述"拓扑",只在本区域洪泛;类型 3、4、5(ABR 产生的摘要与 ASBR 产生的外部 LSA)描述"路由",要跨区域走。区域这道墙拦住的是拓扑细节,放行的是可达性摘要。
五、DR/BDR 与邻居、邻接
多路访问网络(如以太网)上,
省了多少可以直接数出来。邻接数是
| 两两全邻接 | 有 DR/BDR | 省下 | |
|---|---|---|---|
| 4 | 6 | 5 | 1 |
| 6 | 15 | 9 | 6 |
| 10 | 45 | 17 | 28 |
| 20 | 190 | 37 | 153 |
选举比优先级(0~255,默认 1,为 0 则不参选),优先级相同比 Router ID,且非抢占:新上线的高优先级设备不夺权,只有 DR 故障时 BDR 才升为 DR。抢占会导致每次有新设备上线就重新同步一次 LSDB、网段短暂震荡——稳定性优先于"谁更该当"。
邻居是通过 Hello 互相发现的路由器,交换 Hello 即可;邻接(完全邻接)是完成了 LSDB 同步的路由器对,要走完整的 DBD → LSR → LSU → LSAck。不是完全邻接的路由器,表明它们虽然在物理上相邻,但链路状态数据库并没有达到一致。多路访问网络上邻居很多、邻接很少是正常状态,不是故障。
六、OSPF vs RIP
| 对比项 | RIP | OSPF |
|---|---|---|
| 算法 | 距离向量(Bellman-Ford) | 链路状态(Dijkstra SPF) |
| 交换的信息 | 整张路由表(结论) | 本机的链路状态(原料) |
| 交换给谁 | 仅相邻路由器 | 洪泛到区域内所有路由器 |
| 何时交换 | 每 30 s 周期性 | 链路状态变化时;另加约 30 分钟刷新 |
| 度量 | 跳数,只能是跳数 | 代价可以是 |
| 最大规模 | 15(16 = 不可达) | 无此限制,靠区域划分扩展 |
| 收敛速度 | 慢(坏消息传得慢) | 快,响应网络变化小于 100 ms |
| 路由环路 | 可能(无穷计数) | 靠 LSDB 一致性避免 |
| 分层 | 不支持 | 支持(主干区域 0.0.0.0) |
| 负载均衡 | 不支持 | 支持等价多路径 |
| 封装 | UDP 端口 520 | 直接封装在 IP 中,协议号 89(BGP 是 TCP 179,三个一起记) |
本节小结
- OSPF 的三个要点全都与 RIP 相反:向区域内所有路由器用洪泛法发、发的是链路状态这个原料、状态变化时才发(另加约 30 分钟刷新兜底)。代价可取 1~65535 并按业务类型分别设定,支持等价多路径。
- 可靠洪泛靠三件事立住:除来路外转发、序列号防旧覆新并终止洪泛、LSAck 确认。DBD 与 LSR 两段式存在的理由是把开销从"全量广播"降到"只补差集"。各机 LSDB 相同,但以自己为根算,路由表并不相同。
- 区域划分与 DR 都在换可扩展性:划区域后只知道本区域拓扑,跨区靠 ABR 概括;选 DR/BDR 把邻接数从
降到 , 时两者相等,故点对点链路不选 DR。
考点速记
OSPF 在真题里被考过的形式有两种:一道选择题只问"哪个 IGP 能分区域",一道 9 分综合题把 LSI 表铺开让你自己算最短路。
① 哪个内部网关协议能把 AS 划成多个区域(cn-2026-38)。三个候选 OSPF、RIP、BGP,答 A:仅 Ⅰ。这道题一次卡两个点:BGP 根本不是 IGP(它是外部网关协议,跑在 AS 之间),先出局;RIP 是 IGP 但不支持分层,它没有区域的概念。只有 OSPF 两条都满足。
② 给一张 LSI 表和拓扑,写路由表、算 TTL、补默认路由(cn-2014-43,9 分)。这道题的三问正好覆盖 OSPF 落地的三个动作。
第 (1) 问要"路由项尽可能少"。先按 LSI 里的 metric 跑 Dijkstra:到 192.1.5.0/24 走 R3 代价 3,到 192.1.6.0/24 走 R2 代价 4,到 192.1.7.0/24 有两条路——经 R3 是 192.1.6.0/24 与 192.1.7.0/24 的第三字节是 00000110 与 00000111,前 7 位相同、末位取遍 0 和 1,且下一跳同为 R2、出接口同为 L0,可以合成 192.1.6.0/23。而 192.1.5.0/24(00000101)下一跳是 R3,不能并进来。最终 R1 只需 3 条。
第 (2) 问问 TTL。目的 192.1.7.211 落在聚合后的 /23 里,R1 从 L0 转发。TTL 的减法有一条硬规则:每经过一个路由器减 1,主机不减,链路本身也不消耗。这条分组走 R1 → R2 → R4 共三个路由器,所以目的主机收到时是
第 (3) 问,R1 新增一条 metric 为 10 的链路连 Internet,LSI 要加什么。Internet 不是一个具体子网,只能写成默认路由的形式:Prefix = 0.0.0.0/0、Metric = 10。这条 LSI 洪泛出去以后,R2/R3/R4 的路由表里就都有了一条经 R1 出网的默认路由。
这道题最值得记的是第 (1) 问那个动作次序:先跑 Dijkstra 定下每个子网的下一跳,再拿下一跳去判能不能聚合。 反过来先看前缀像不像、再去凑下一跳,必然把 192.1.5.0/24 错并进去。
本篇练习区里还会出现另外四道题,机制分别讲在别处:cn-2010-35 与 cn-2016-37 考 RIP 的距离更新,在 RIP;cn-2013-47 与 cn-2017-37 考 BGP,在 BGP;cn-2021-37 考距离向量的一轮计算,在路由算法。
易错:BGP 不是 IGP。 问"内部网关协议"时它一定出局。
易错:RIP 不支持分区域。 能把 AS 划成多个区域的 IGP 只有 OSPF。
易错:TTL 每经过一个路由器减 1,主机不减、链路不消耗。 数的是路由器个数,不是链路条数。
易错:聚合前必须先确定下一跳。 前缀连续但下一跳不同的路由不能合并。
易错:"最短路径优先"不是 OSPF 独有的目标,所有 IGP 都在找最短路。区别在怎么找。
易错:划分区域后只知道本区域拓扑,跨区靠 ABR 概括。"每台都有全网拓扑"只在单区域时成立。
易错:LSDB 相同不等于路由表相同。 每台以自己为根算,最短路径树各不相同。
易错:邻接数是
,因为 DROther 之间不建邻接; 时它等于 1,所以点对点链路不选 DR。
易错:洪泛是网络层的逐跳复制转发,不是数据链路层的广播。
教材出处
- 谢希仁《计算机网络》(第 8 版)4.6.3 内部网关协议 OSPF,印刷版 p164–p168:
- 命名与澄清见 p164——"'开放'表明 OSPF 协议不是受某一家厂商控制,而是公开发表的。'最短路径优先'是因为使用了 Dijkstra 提出的最短路径算法 SPF";"请注意:OSPF 只是一个协议的名字,它并不表示其他的路由选择协议不是'最短路径优先'。实际上,所有的在自治系统内部使用的路由选择协议(包括协议 RIP)都是要寻找一条最短的路径"。
- 三条特点(向本自治系统中所有路由器用洪泛法发送、发送的是与本路由器相邻的所有路由器的链路状态、链路状态变化或每隔一段时间如 30 分钟发送)在 p164;同页给出"链路状态"的定义——"说明本路由器都和哪些路由器相邻,以及该链路的'度量'(metric)。OSPF 将这个'度量'用来表示费用、距离、时延、带宽,等等",并在脚注中说明 OSPF 的"链路"实际上就是指"和这两个路由器都有接口的网络"。
- 链路状态数据库与其同步见 p164–p165——"这个数据库实际上就是全网的拓扑结构图。这个拓扑结构图在全网范围内是一致的(这称为链路状态数据库的同步)"。
- 区域划分见 p165——"OSPF 将一个自治系统再划分为若干个更小的范围,叫作区域(area)。每一个区域都有一个 32 位的区域标识符……在一个区域内的路由器最好不超过 200 个";"划分区域的好处就是把利用洪泛法交换链路状态信息的范围局限于每一个区域而不是整个的自治系统";关键的一句——"在一个区域内部的路由器只知道本区域的完整网络拓扑,而不知道其他区域的网络拓扑的情况"。主干区域标识符 0.0.0.0、区域边界路由器"进行概括"、主干路由器、自治系统边界路由器四类角色同在 p165。
- 代价的灵活性与负载均衡见 p165–p166——"链路的代价可以是 1 至 65535 中的任何一个无量纲的数";"OSPF 对于不同类型的业务可计算出不同的路由";"如果到同一个目的网络有多条相同代价的路径,那么可以将通信量分配给这几条路径。这叫作多路径间的负载均衡……RIP 只能找出到某个网络的一条路径"。
- 邻接的定义在 p167——"两个同步的路由器叫作'完全邻接的'(fully adjacent)路由器。不是完全邻接的路由器表明它们虽然在物理上是相邻的,但其链路状态数据库并没有达到一致";同页说明 DBD/LSR 两段式交换的动机是"如果所有的路由器都把自己的本地链路状态信息对全网进行广播……但这样做开销太大",并给出可靠洪泛与"每隔一段时间,如 30 分钟,要刷新一次数据库中的链路状态",以及收敛速度实测——"据统计,其响应网络变化的时间小于 100 ms"。
- DR 的动机与作用在 p167–p168——"若 N 个路由器连接在一个以太网上,则每个路由器要向其他 (N−1) 个路由器发送链路状态信息,因而共有 N(N−1) 个链路状态要在这个以太网上传送。OSPF 协议对这种多点接入的局域网采用了指定的路由器(designated router)的方法,使广播的信息量大大减少。指定的路由器代表该局域网上所有的链路向连接到该网络上的各路由器发送状态信息"。
- ⚠️ 本篇未引教材的部分:LSA 的五种类型编号、DR/BDR 的选举规则细节(优先级 0~255、Router ID、非抢占)与
这个计数结果,谢希仁书中没有对应表述——它们出自 OSPFv2 的协议规范,属于了解性内容。 是按邻接对分类穷举得到的(DR↔BDR 一条 + DR、BDR 各连 台 DROther + DROther 之间 0 条),读者可自行复核。
相关知识
路由算法:距离向量 vs 链路状态|RIP 路由协议|BGP 路由协议|网络层功能:路由、转发与异构网络互联