📚 第七章 路由协议
📄 一句话概括

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 秒实验

  1. 算一下:参考带宽 100 Mbps 时,一个 2 Mbps 专线的代价是多少?
  2. 想一下:为什么 OSPF 不跑在 TCP 或 UDP 上?
  3. 想一下:参考带宽只改了一台设备,会出什么问题?

常见误区

  1. 以为「OSPF 的代价是延迟」。 是按带宽算的,和实际延迟没有直接关系。
  2. 以为「参考带宽随便改」。 必须全网一致,不然两台算出的路径对不上。
  3. 以为「OSPF 一定比 RIP 好」。 它吃内存、配置复杂,小网里 RIP 反而省事。
自测三问(点开对答案) 1. OSPF 的代价怎么算? —— **参考带宽除以接口带宽**,默认参考带宽 100 Mbps,最小取 1。 2. 为什么千兆和万兆的代价都是 1? —— **算出来是 0.1 和 0.01**,取整后都被最小值 1 顶住了。 3. OSPF 为什么不跑在 TCP 上? —— **它要在「还没有路由」时工作**,依赖 TCP 就死锁了;而且它要用多播。

下一节看 OSPF 靠哪五种报文干活。

相关笔记