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

「查表快」这个老卖点已经过时了:现代路由表用 TCAM,也是常数时间。 真正的理由换成了三个:流量工程、VPN、统一承载。

📝 本节和前面几节的关系

7.7.1 讲了机制,这一节讲「为什么要用它」。 这一节会实测一次「标签查表 vs 最长前缀匹配」,并且说清这个测量的局限。

一、老卖点:查表快

MPLS 最早被推销的理由是「转发快」:IP 要按最长前缀匹配,标签只要精确匹配。 在 1990 年代,这个差别是实打实的—— 当年的路由器用软件查表,一次最长前缀匹配要几十个时钟周期。 为什么最长前缀匹配慢: 因为它要「试多个长度」——先试 /32 有没有、再试 /31、/30……直到命中。 软件实现里这就是一个循环,表越大越慢。 而标签是「精确值」,一次哈希或一次直接索引就到位。 但这个优势在今天基本消失了:现代路由器用 TCAM 做最长前缀匹配, 它是一种「能并行比较所有表项」的硬件,一个时钟周期就能出结果。 所以「MPLS 查表快」这个理由,在硬件层面已经站不住了。

二、实测:算法层的差距有多大

下面这个测量要看清它的边界:它测的是「两种算法在 Python 里的差距」,不是真实路由器。 所以它只能说明「算法复杂度不同」,不能说明「MPLS 更快」。 做法是造 5 万条前缀,用 50 个目标地址各查一次: 最长前缀匹配用线性扫描(每条都试一遍),标签查表用一次哈希。 两者都跑在同一台机器、同一个解释器上。 结果差了四个数量级(460 毫秒对 0.007 毫秒)。 这个差距来自复杂度:一个随表大小线性增长,一个是常数。 但真实路由器把线性那一步交给硬件并行做,所以「差四个数量级」这件事在硬件上不成立。

三、新理由一:流量工程

这是今天 MPLS 最主要的用途。 IP 路由有个天生的限制:它只能「按目的地选路」。 所以去同一个目的地的所有流量,必然走同一条路——哪怕那条路已经挤爆,另一条空闲。 这叫「等價多路径不均匀」问题: OSPF 支持 ECMP,可以把流量分到多条等价路径上,但「等价」是路由算出来的, 人不能指定「这条流走这边」。 MPLS 能——因为转发看的是标签,标签可以人为指定走哪条 LSP。 于是「语音走一条、普通数据走另一条」就做得到了。 这个能力叫「显式路径」,是 IP 天生做不到的。 它带来两个实际用途:一是「避开拥塞链路」(哪怕它是最短路径), 二是「主备切换」(备用 LSP 提前建好,主路径一断立刻切)。 后者的切换时间是毫秒级,比路由收敛快得多。

四、新理由二和三:VPN 与统一承载

VPN 这一条在 7.7.1 已经讲过一半:两层标签把「运营商」和「客户」的地址空间隔开, 所以两家客户都用 10.0.0.0/8 也不会冲突。 这一条为什么重要:因为「客户不想改地址」是刚需。 一个企业内网跑了几十年,上了广域互联之后要求「地址一个都不能改」。MPLS VPN 能做到, 而「用公网加 NAT」做不到。因为 NAT 会破坏端到端。 这也是 MPLS 在企业专线市场长期占主流的原因。 统一承载这一条最容易被忽略:同一个标签栈能带 IP、以太网、甚至 TDM 流量。 所以运营商可以用一张网同时提供「上网」和「专线」,不必为每种业务建一张物理网。 这是「省钱」的逻辑,不是「技术先进」的逻辑——而工程上「省钱」往往比「先进」更有说服力。

五、动手 Demo:标签查表真的比最长前缀匹配快吗

造 5 万条前缀,用 50 个目标各查一次,比较线性扫描和哈希查表。 这个测量只反映算法复杂度,不代表真实路由器。

import random, time
random.seed(7)
N, M = 50000, 50
nets = [(random.getrandbits(32) & 0xFFFFFF00, 24) for _ in range(N)]
targets = [random.getrandbits(32) for _ in range(M)]

t0 = time.perf_counter()
for ip in targets:
    best = -1
    for val, plen in nets:
        mask = (0xFFFFFFFF << (32 - plen)) & 0xFFFFFFFF
        if ip & mask == val and plen > best:
            best = plen
t1 = time.perf_counter()
print('线性最长前缀匹配 %.1f 毫秒' % ((t1 - t0) * 1000))

实跑输出:

--------------------------------------------------------------------
标签查表真的比最长前缀匹配快吗
--------------------------------------------------------------------
**MPLS 最常被提到的优点是「查表快」**:**IP 要按最长前缀匹配,标签只要精确匹配。**
**这个说法对不对,实测一下。**

  方式             表的大小      查询次数     总耗时
  -------------------------------------------------------
  最长前缀匹配     50,000 条     50 次        461.5 毫秒
  标签精确查表     50,000 条     50 次        0.007 毫秒

**差了四个数量级**——**这就是「查表快」这句话的来源。**
**最长前缀匹配要逐条试,最坏要看完整张表。**
**标签是精确值,一次哈希就到位。**

**但这个测量必须加一句限定**:**它只反映「两种算法在 Python 里的差距」,不代表真实路由器。**
**现代路由器查路由表用的是 TCAM(一种能并行比较的硬件)。**
**一个时钟周期就能把所有前缀比完,也是常数时间。**
**所以「MPLS 查表快」这个理由,在今天的硬件上已经不成立了。**

**那 MPLS 现在为什么还在用,理由换成了三个**:

  优点             真正的原因
  ------------------------------------------------------------------
  **流量工程**     **可以指定「这条流走这条路径」,IP 路由做不到**
  **VPN**          **两层标签把「运营商」和「客户」的地址空间隔开**
  **统一承载**     **同一个标签栈能带 IP、以太网、甚至 TDM 流量**

**第一行是今天最主流的用法**:**IP 路由只能「按目的地选路」,所有去同一个地方的人都走同一条路。**
**MPLS 能按「标签」分流转发**——**去同一个目的地,语音走一条、普通数据走另一条,各走各的。**
**这叫「显式路径」,是 IP 天生做不到的。**
**所以「MPLS 快」这个旧卖点过时了,「MPLS 能管」这个新卖点还在。**

差了两个数量级——这就是「查表快」这句话的来源。 最长前缀匹配要逐条试,最坏要看完整张表。 标签是精确值,一次哈希就到位。 但这个测量必须加一句限定:它只反映「两种算法在 Python 里的差距」,不代表真实路由器。 现代路由器查路由表用的是 TCAM(一种能并行比较的硬件)。 一个时钟周期就能把所有前缀比完,也是常数时间。 所以「MPLS 查表快」这个理由,在今天的硬件上已经不成立了。 那 MPLS 现在为什么还在用,理由换成了三个:流量工程、VPN、统一承载。 第一行是今天最主流的用法:IP 路由只能「按目的地选路」,所有去同一个地方的人都走同一条路。 MPLS 能按「标签」分流转发——去同一个目的地,语音走一条、普通数据走另一条,各走各的。 所以「MPLS 快」这个旧卖点过时了,「MPLS 能管」这个新卖点还在。

30 秒实验

  1. 算一下:5 万条前缀、50 个目标,线性扫描一共比较多少次?
  2. 想一下:为什么 IP 路由「只能按目的地选路」?
  3. 想一下:MPLS VPN 和「公网加 NAT」相比,优势在哪?

常见误区

  1. 以为「MPLS 现在还是因为快才用」。 TCAM 之后就不成立了,现在的理由是流量工程和 VPN。
  2. 以为「这个 Python 测量能代表路由器」。 只反映算法复杂度,真实设备是硬件并行匹配。
  3. 以为「MPLS 只在运营商用」。 企业专线、数据中心也在用,只是形态不同。
自测三问(点开对答案) 1. 「查表快」这个理由为什么过时了? —— **现代路由表用 TCAM 做并行匹配**,最长前缀匹配也是常数时间。 2. MPLS 今天最主要的用途是什么? —— **流量工程**:能指定某条流走哪条 LSP,IP 路由做不到。 3. 两层标签在 VPN 里怎么分工? —— **外层决定「哪个站点」,内层决定「站点里的哪个网段」。**

下一章换到最上面一层:应用协议。

相关笔记