MPLS 在 IP 头前面插一个 32 位的标签,路由器只看标签转发。 入口打上、中间换、出口剥掉,这条路径叫 LSP。
7.6 讲完了「怎么算出路由」,这一节换一个维度:转发时看什么。 MPLS 不改路由协议,它改的是「拿到路由之后,怎么把包发出去」。
一、标签只有 32 位,四个字段
MPLS 的「标签」是一块 4 字节的头部,插在二层头和 IP 头之间。它的四个字段分工很明确:
| 字段 | 位数 | 作用 |
|---|---|---|
| 标签值 | 20 | 决定下一跳怎么转发 |
| EXP | 3 | 优先级,后来改名叫 TC |
| S | 1 | 栈底标记,1 表示最后一层 |
| TTL | 8 | 和 IP 的 TTL 一个用途,防环 |
标签值占 20 位,所以标签空间是 2 的 20 次方,约 104 万个。 这个数字是「每台设备本地有效」的,不是全球唯一—— 同一台设备的同一个标签,只能对应一条转发规则。 S 位只有 1 位,但它是「栈」这个设计的枢纽。 它告诉设备「下面还有没有标签」,所以设备可以「只看最外层」而不必关心里面有几层。 这就是 MPLS 能把「运营商」和「客户」分开的技术基础。
二、三种动作:push、swap、pop
一个包穿过 MPLS 网络,标签会被改好几次,但动作只有三种:
| 动作 | 在哪儿做 | 干什么 |
|---|---|---|
| push | 入口 LER | 打上一个标签 |
| swap | 中间 LSR | 换成本机的出标签 |
| pop | 出口 LER | 剥掉标签,恢复纯 IP 包 |
入口和出口叫 LER(标签边缘路由器),中间叫 LSR(标签交换路由器)。 整条路径叫 LSP(标签交换路径)。 这三个缩写要记住,因为排错时说的就是它们。 为什么中间要「换」而不是「一直用同一个号」: 因为标签是「本地有效」的—— 每台设备自己分配自己的号,只保证「进来的包用这个号,从那个口出去」。 所以同一条路径上,每一跳的号都可以不一样。 这个设计让标签分配变成了「各管各的」,不需要全局协调。
三、为什么要有标签栈
一层标签就够转发了,为什么还要「栈」: 因为一层标签只能表达「去哪儿」,表达不了「这是谁的流量」。 两层标签正好把这两件事分开:外层决定「送到哪个站点」,内层决定「送到站点里的哪个网段」。 这个分工带来了 MPLS VPN 的核心能力:中间的运营商路由器只换外层,内层原封不动地传过去。 所以运营商不需要知道客户的内部结构——它只知道「这个包属于客户 A,要送到站点 B」。 客户的地址空间可以重叠(两家客户都用 10.0.0.0/8),因为外层标签把它们区分开了。 注意「只换外层」这件事的实现方式:外层 swap、内层不动,所以栈的深度不变。 只有到了出口,两个标签才一起 pop。 这也解释了 S 位的作用——没有 S 位,设备就不知道「剥掉这一层之后,下面那层是不是还要用」。
四、标签是怎么发下来的
标签不是人配的,是协议分的。 有两种常见的分发方式:一种是跟着路由协议走(LDP),一种是用 BGP 扩展(BGP 加标签)。 LDP 的思路很直白:「我有一条路由,我就给它分一个标签,然后告诉邻居」。 所以 LSP 是跟着路由表自动长出来的——路由变了,标签也跟着变。 这也意味着「MPLS 域内的转发路径和 IP 路由是同一棵树」, 所以单靠 LDP 做不到「让某条流量走另一条路」。 要「指定路径」就得用 RSVP-TE 或 SR:它们能显式指定一条 LSP 经过哪些节点, 这才是 MPLS 做流量工程的入口。 所以「MPLS 能管流量」这句话,严格说应该是「MPLS 加流量工程信令才能管流量」。
五、动手 Demo:MPLS 的标签是怎么换的
看一个包从 R1 到 R4 的过程中,标签栈怎么变。 重点在「每台的号都不一样」这一点。
hops = [
('R1 入口 LER', None, 100, 'push'),
('R2 核心 LSR', 100, 200, 'swap'),
('R3 核心 LSR', 200, 300, 'swap'),
('R4 出口 LER', 300, None, 'pop'),
]
for name, inl, outl, act in hops:
print('%-14s %-6s -> %-6s %s'
% (name, inl or '—', outl or '—', act))
print('标签空间 2**20 =', 2 ** 20)
实跑输出:
--------------------------------------------------------------------
MPLS 的标签是怎么换的
--------------------------------------------------------------------
**MPLS 在 IP 头前面插一个 32 位的「标签」**,**路由器只看标签转发,不看 IP 地址。**
**一个包穿过网络时,标签会被换好几次。**
**标签本身占 20 位,所以标签空间是 2 的 20 次方,等于 1,048,576 个。**
字段 位数 作用
------------------------------------------------------------
标签值 20 位 决定下一跳怎么转发
EXP 3 位 优先级(后来改叫 TC,给 QoS 用)
S 1 位 栈底标记,1 表示这是最后一个标签
TTL 8 位 和 IP 的 TTL 一个用途,防环
**合计** **32 位** **正好 4 字节**
**下面跟着一个包走一遍**:**路径是 R1 → R2 → R3 → R4,R4 后面是目标网段。**
节点 标签栈变化 动作
-----------------------------------------------------------------
R1(入口 LER) `— → 100` **push**:打上标签 100
R2(核心 LSR) `100 → 200` **swap**:换成 200
R3(核心 LSR) `200 → 300` **swap**:换成 300
R4(出口 LER) `300 → —` **pop**:剥掉,恢复成纯 IP 包
**入口和出口叫 LER**(标签边缘路由器),**中间叫 LSR**(标签交换路由器)。
**入口负责「打上」,中间负责「换」,出口负责「剥掉」。**
**整条路径叫 LSP**(标签交换路径)。
**标签栈可以有多层**,这就是「栈」这个名字的来源:
层 示例值 谁看它
-----------------------------------------------------
外层标签 `5000` **决定「这个包去哪个用户」**
内层标签 `120` **决定「在用户网里怎么走」**
**两层标签正是 MPLS VPN 的实现方式**:**外层管「送到哪个站点」,内层管「送到站点里的哪个网段」。**
**中间的运营商路由器只换外层,内层原封不动地传过去**——**所以运营商不需要知道客户的内部结构。**
**这个「外层可见、内层不可见」的分工,是 MPLS 最值钱的地方。**
入口和出口叫 LER(标签边缘路由器),中间叫 LSR(标签交换路由器)。 入口负责「打上」,中间负责「换」,出口负责「剥掉」。 整条路径叫 LSP(标签交换路径)。 注意「100 到 200 到 300」不是约定,是各自分配的结果—— R2 用的是「本机分给这条 LSP 的号」,R3 也用自己的一套。 所以抓包看到的标签值,只有「同一台设备的入和出」这一对是有意义的。 拿两台设备的标签号去比大小,是没有意义的。 pop 有两种做法: 一种是「倒数第二跳弹出」(PHP)——出口的前一跳就把标签剥掉,出口只做纯 IP 转发。 另一种是出口自己剥。 PHP 更常用,因为它让出口设备「不需要维护标签表」,代价是「出口看不到标签,只能看 IP 头」。
30 秒实验
- 算一下:20 位标签空间有多大?
- 想一下:为什么每台设备的标签号可以不一样?
- 想一下:两层标签分别解决什么问题?
常见误区
- 以为「标签是全局唯一的」。 只在本机有效,每一跳都可以换号。
- 以为「MPLS 改了路由协议」。 它不改路由,改的是「拿到路由之后怎么转发」。
- 以为「配了 LDP 就能做流量工程」。 LDP 跟着路由走,要指定路径得用 RSVP-TE 或 SR。
自测三问(点开对答案)
1. 标签的四个字段是什么? —— **20 位标签值、3 位 EXP、1 位 S、8 位 TTL。** 2. 三种动作分别在哪做? —— **push 在入口 LER、swap 在中间 LSR、pop 在出口 LER。** 3. 为什么需要标签栈? —— **一层只能表达「去哪儿」**,两层才能同时表达「哪个客户」和「哪个网段」。下一节看 MPLS 到底解决了什么问题。
- ☐ (本节完,下一节 7.7.2 MPLS的优点)