OSPF 不数跳数,它算代价:代价等于参考带宽除以接口带宽。 所以它能分出「千兆比百兆快」,这是 RIP 做不到的。
7.4 把 RIP 这条线走完了,这一节换到链路状态。 7.3.2 讲的是算法,这一节讲它落地成 OSPF 之后的样子。
一、OSPF 的四个特征
第一,它是链路状态型:每台路由器拿到全网的拓扑,自己算最短路树。 所以它不会「计数到无穷」——路断了一眼看得出来,不靠传闻。 第二,它的度量是代价:公式是「参考带宽除以接口带宽」, 默认参考带宽 100 Mbps,所以百兆接口代价是 1,十兆是 10。 这个度量能表达「这条路快」,所以选路能选优。 第三,它直接跑在 IP 上:IP 首部里的协议号是 89,不经过 TCP 也不经过 UDP。 所以它要自己实现可靠传输(用 LSAck 确认加重传)。 第四,它支持无类路由:报文里带掩码,能传 VLSM 和 CIDR, 7.4.3 那个「子网被压成主类」的灾难在 OSPF 里不存在。
二、为什么不用 TCP 或 UDP
这是一个值得琢磨的设计选择: BGP 用 TCP(端口 179),RIP 用 UDP(端口 520),OSPF 什么都不用,直接挂在 IP 上。 理由有三条:一是「启动顺序」——OSPF 要在「还没有路由」的时候工作, 如果它依赖 TCP,而 TCP 又依赖路由,就死锁了。 二是「开销」——OSPF 的报文很短(Hello 才 44 字节正文), 套一层 TCP 头(20 字节)不划算。 三是「多播」——OSPF 用 224.0.0.5 和 224.0.0.6 两个多播地址,TCP 不支持多播。 第一条是最关键的:路由协议是「给别的协议提供路由」的,它自己必须是「最底层能跑」的那个。 所以它不能依赖任何需要路由才能工作的东西。 BGP 可以用 TCP,是因为 BGP 只在「已经能通」的边界路由器之间跑——它不负责「让自己能通」。
三、代价怎么算,以及它的坑
默认参考带宽是 100 Mbps,也就是 10 的 8 次方。 所以代价等于 10 的 8 次方除以带宽(bps)。
| 接口 | 算出来的值 | 实际代价 |
|---|---|---|
| 10 Mbps | 10 | 10 |
| 100 Mbps | 1 | 1 |
| 1 Gbps | 0.1 | 1(取整后最小值) |
| 10 Gbps | 0.01 | 1(同上) |
最后两行都是 1,这就是「默认参考带宽太小」的后果—— 千兆和万兆在 OSPF 眼里一样快,选路就选不出优劣。 解决办法是把参考带宽调大(比如调到 10 Gbps),让百兆、千兆、万兆分别算出 100、10、1。 但调参考带宽有个坑: 它是「全区域一致」的参数—— 如果一台设备调了、另一台没调,两台对同一条链路的代价算得不一样,SPF 就会算出不对称的路径。 所以这一步必须全网统一改,不能只改一台。 这也是「OSPF 参数要一致」这条规矩里最容易忘的一条。
四、和 RIP 的取舍对比
| 维度 | RIP | OSPF |
|---|---|---|
| 算法 | 距离向量 | 链路状态 |
| 度量 | 跳数 | 代价 |
| 上限 | 15 跳 | 没有跳数限制 |
| 收敛 | 30 秒一轮 | 事件触发,秒级 |
| 内存 | 只存表 | 要存拓扑图 |
| 配置 | 两行 | 要配区域、Router ID |
最后两行是「OSPF 的代价」: 它要存整张图,所以吃内存;它要配区域和 Router ID,所以配错的机会多。 所以「OSPF 更好」这句话要加限定:「在网大到 RIP 撑不住的场景里,OSPF 更好」。 十来台设备的小网,RIP 的两行配置反而是优势。 第五行那个差别在排错时最明显:RIP 出问题,看一张表就知道「谁告诉我什么」; OSPF 出问题,要看邻居状态、要看 LSDB、要看 SPF 树,层次深得多。 所以「工具越强,用错的机会越大」这句话在路由协议上也成立。
五、动手 Demo:OSPF 的「代价」怎么算
按默认参考带宽算六种接口的代价,再看调大参考带宽之后的变化。 重点看「千兆和万兆都被压成 1」那两行。
ref = 10 ** 8 # 默认参考带宽 100 Mbps
for name, mbps in (('10M', 10), ('100M', 100),
('1G', 1000), ('10G', 10000)):
raw = ref / (mbps * 10 ** 6)
print('%-6s %8.2f 代价 %d' % (name, raw, max(1, int(raw))))
print('---- 参考带宽调到 10G ----')
ref = 10 ** 10
for mbps in (100, 1000, 10000):
print('%6dM 代价 %d' % (mbps, max(1, int(ref / (mbps * 10 ** 6)))))
实跑输出:
--------------------------------------------------------------------
OSPF 的「代价」怎么算
--------------------------------------------------------------------
**OSPF 是链路状态型**:**每台路由器拿到全网的拓扑,自己算最短路。**
**它和 RIP 最根本的差别在「度量」**——**RIP 数跳数,OSPF 算代价。**
接口 带宽 参考带宽除以带宽 OSPF 代价
-------------------------------------------------------------
调制解调器 0.056 Mbps 1785.71 1785
ISDN 0.128 Mbps 781.25 781
以太网 10 Mbps 10.00 10
快速以太网 100 Mbps 1.00 1
千兆以太网 1000 Mbps 0.10 1
万兆以太网 10000 Mbps 0.01 1
**公式就是「参考带宽除以接口带宽」**,**参考带宽默认是 100 Mbps,也就是 10 的 8 次方。**
**所以 100 Mbps 的接口代价是 1,10 Mbps 是 10。**
**注意最后两行都是 1**:**千兆算出来 0.1,万兆算出来 0.01,取整之后都被压到最小值 1。**
**这就是「默认参考带宽太小」的后果**——**千兆和万兆在 OSPF 眼里一样快,选路就选不出优劣。**
**解决办法是把参考带宽调大**:
参考带宽 百兆代价 千兆代价 万兆代价
--------------------------------------------------
100 Mbps 1 1 1
1000 Mbps 10 1 1
10000 Mbps 100 10 1
**第二行(1000 Mbps)就能把三者拉开成 10、1、1**——**还是没分开千兆和万兆**。**第三行才行。**
**所以「调参考带宽」这条经验,本质是「让整数除法别把差异抹平」。**
**顺带对比一下 RIP 的度量有多粗**:**一条经过三台 10 Mbps 路由器的路,RIP 看到的是「3 跳」。**
**一条经过两台千兆路由器的路,RIP 看到的是「2 跳」。**
**RIP 会选后者——这次碰巧对了。**
**但如果千兆那条要绕 4 跳,RIP 就会选那条慢的。**
**它压根看不见带宽。**
注意最后两行都是 1:千兆算出来 0.1,万兆算出来 0.01,取整之后都被压到最小值 1。 这就是「默认参考带宽太小」的后果——千兆和万兆在 OSPF 眼里一样快,选路就选不出优劣。 调大参考带宽之后,百兆、千兆、万兆变成 100、10、1,差别出来了。 但注意「1 仍然是最小值」——如果参考带宽调到 100 Gbps,那万兆算出来也是 10,没问题; 但百兆算出来是 1000,这个数会超过 OSPF 代价字段的 16 位上限吗? 65535 以内,不会。 所以调参考带宽的边界是「最小代价别小于 1,最大代价别超过 65535」。 顺带说一句:OSPF 的代价是「出接口」的代价,不是「入接口」。 所以一条路径的总代价是「沿途每一跳出接口代价之和」。 这也意味着「来回路径可能不对称」——因为去和回经过的接口不同,累加的代价也不同。
30 秒实验
- 算一下:参考带宽 100 Mbps 时,一个 2 Mbps 专线的代价是多少?
- 想一下:为什么 OSPF 不跑在 TCP 或 UDP 上?
- 想一下:参考带宽只改了一台设备,会出什么问题?
常见误区
- 以为「OSPF 的代价是延迟」。 是按带宽算的,和实际延迟没有直接关系。
- 以为「参考带宽随便改」。 必须全网一致,不然两台算出的路径对不上。
- 以为「OSPF 一定比 RIP 好」。 它吃内存、配置复杂,小网里 RIP 反而省事。
自测三问(点开对答案)
1. OSPF 的代价怎么算? —— **参考带宽除以接口带宽**,默认参考带宽 100 Mbps,最小取 1。 2. 为什么千兆和万兆的代价都是 1? —— **算出来是 0.1 和 0.01**,取整后都被最小值 1 顶住了。 3. OSPF 为什么不跑在 TCP 上? —— **它要在「还没有路由」时工作**,依赖 TCP 就死锁了;而且它要用多播。下一节看 OSPF 靠哪五种报文干活。
- ☐ (本节完,下一节 7.5.2 OSPF基础知识)