前面讲 VXLAN 的时候说过,它的思路是"用三层网络承载二层流量"。其实在 VXLAN 之前,MPLS 已经用类似的思路把"标签转发"这件事做了十几年——只是它承载的是三层 VPN。
理解 MPLS VPN 只需要抓住两件事:① 转发靠标签,不靠 IP 查表;② 隔离靠 VRF(RD + RT),不靠加密。剩下的都是这两件事的展开。
MPLS 解决什么问题
传统 IP 转发每跳都要做一次"最长匹配查表",在核心节点上这是很大的负担。而且 IP 转发只认目的地,没法表达"走哪条路"。
MPLS 的做法是:在进入 MPLS 域时给包打一个短标签,域内只看标签转发。标签是定长的、只在本地的标签表里查——查表快,还能天然支持流量工程和 VPN。
| 角色 | 全称 | 干什么 |
|---|---|---|
| LER | Label Edge Router,标签边缘路由器 | MPLS 域的出入口。入口压标签(Push),出口弹标签(Pop) |
| LSR | Label Switching Router,标签交换路由器 | 域内转发,只换标签(Swap) |
| LSP | Label Switched Path,标签交换路径 | 一条标签走过的路径,相当于"隧道" |
| FEC | Forwarding Equivalence Class,转发等价类 | 被同一个标签标识的一组报文(通常是一个路由前缀) |
标签长什么样
MPLS 标签是 4 字节(32 位),夹在二层帧头和 IP 头之间:
┌──────────────────────┬──────┬───┬────────┐
│ Label(20 bit) │ EXP │ S │ TTL │
│ 标签值 │ 3bit │1bit│ 8 bit │
└──────────────────────┴──────┴───┴────────┘
│ │ │ └── 每跳减 1,到 0 丢弃
│ │ └───────── 栈底标志:1 = 最后一层
│ └──────────────── 优先级(类似 802.1p,QoS 用)
└────────────────────────────────────── 标签值:0~15 是保留值
关键保留标签:
0 IPv4 显式空标签(PHP 用,告诉上游"弹出标签再转发")
3 Implicit Null(隐式空标签,直接不压标签)
7 Router Alert(给路由器自己看的)
14 OAM Alert
三种标签动作
| 动作 | 在哪做 | 干什么 |
|---|---|---|
| Push | Ingress LER | 压入一层(或多层)标签 |
| Swap | 中间 LSR | 把入标签换成出标签,标签值只在本地有意义 |
| Pop | Egress LER | 弹出标签,恢复成普通 IP 包 |
PHP:次末跳弹出
正常情况下,出口 LER 要先把标签 Pop 掉,再去查 IP 路由表——多一次查表。MPLS 用 PHP(Penultimate Hop Popping,次末跳弹出)优化掉这一步:
- 出口 LER 向上游通告隐式空标签(3);
- 上游 LSR(次末跳)收到标签 3,就知道"我该把标签弹掉再发出去";
- 结果:出口 LER 收到的直接是纯 IP 包,只需查一次路由表。
标签是怎么分发的
标签不是手工配的(虽然可以),主流是协议分发:
| 协议 | 特点 | 场景 |
|---|---|---|
| LDP | Label Distribution Protocol。跟着 IGP 的最优路径走,只能建"最短路径"的 LSP | 普通 MPLS VPN,最常用 |
| RSVP-TE | 可以显式指定路径,支持带宽预留 | 流量工程(MPLS TE) |
| SR(Segment Routing) | 用 IGP 扩展直接分发标签(SR-MPLS),不再需要 LDP/RSVP | 新一代骨干网 |
| MP-BGP | 给 VPN 私网路由分发标签 | MPLS VPN 必用 |
LDP 的标签分发有两种模式,华为默认是 DU(Downstream Unsolicited,下游自主) + 有序方式(Ordered):
- DU:下游主动把标签通告给上游,不用上游要;
- DoD(Downstream on Demand):上游请求了才给;
- 有序:只有自己有了下游的标签(或自己是出口),才给上游发标签;
- 独立:不管下游,自己就能发标签。
MPLS VPN:隔离靠什么
运营商要在一张物理网上跑几十个客户的 VPN,最大的麻烦是客户地址会重叠——A 客户和 B 客户都用 192.168.1.0/24,怎么办?
解法是三层隔离:
① VPN 实例(VRF):先把路由表分开
每个 PE 上为每个 VPN 建一个 VPN 实例(VRF),它有自己独立的路由表、FIB、接口。不同 VRF 的路由天然互不可见。
② RD:让相同前缀能共存
光有 VRF 还不够——BGP 在 PE 之间传递时,两条 192.168.1.0/24 会冲突。于是给每条路由前面加一个 RD(Route Distinguisher,路由标识符):
A 客户:192.168.1.0/24 → RD 100:1 + 192.168.1.0/24 = 100:1:192.168.1.0/24
B 客户:192.168.1.0/24 → RD 100:2 + 192.168.1.0/24 = 100:2:192.168.1.0/24
★ 两条路由现在【不一样了】,可以共存于 MP-BGP 表里
★ RD 是 8 字节,两种写法:
ASN:nn (如 100:1,AS 号 2 字节 + 编号 4 字节)
IP:nn (如 1.1.1.1:1,IP 4 字节 + 编号 2 字节)
★ RD 只负责【让前缀唯一】,不控制谁能收——那是 RT 的事
③ RT:控制谁能收到
RT(Route Target,路由目标)才是真正决定"这条路由发给谁"的属性。它是一个 BGP 扩展团体属性,分两个方向:
| 作用 | |
|---|---|
| Export RT | 从本 VRF 发出去的路由,打上这个 RT |
| Import RT | 收到的路由,如果带的 RT 匹配本 VRF 的 import 列表,就装进本 VRF |
场景:A、B 两个客户各自独立,但都需要访问同一个"公共服务 VRF"
VPN_A export RT 1:1 import RT 1:1
VPN_B export RT 1:2 import RT 1:2
VPN_SRV export RT 1:100 import RT 1:1, 1:2
效果:
· SRV 把路由打上 RT 1:100 发出去
· A 和 B 的 import 列表里【都没有 1:100】,所以收不到 SRV 的路由
· A 发的路由带 RT 1:1,SRV 的 import 里有 1:1 → SRV 能收到
· 想反过来也通,就要在 A/B 的 import 里加上 1:100
★ Hub-Spoke 组网就是靠 RT 单向性实现的:
Hub 的 import 包含所有 Spoke 的 RT,export 只有一个 RT;
Spoke 的 import 只包含 Hub 的 RT → Spoke 之间不能直接互通,必须过 Hub
转发过程:双层标签栈
MPLS VPN 的报文上压两层标签,这是最核心的一张图:
CE-A ── PE-1 ── P1 ── P2 ── PE-2 ── CE-B
① CE-A 发普通 IP 包 → PE-1
② PE-1(Ingress LER):
· 在 VRF-A 里查到目的地址,下一跳是 PE-2
· 压【内层私网标签】(MP-BGP 分配的,标识这个 VRF)
· 再压【外层公网标签】(LDP 分配的,指向 PE-2 的 LSP)
→ 变成「公网标签 | 私网标签 | IP 包」
③ P1、P2(LSR):
· 只看【外层标签】,做 Swap
· 完全不看私网标签,也不知道有 VPN 存在
→ 这就是 MPLS VPN 的"透明承载"
④ PE-2(Egress LER):
· 弹出外层标签(PHP 可能让 P2 就弹了)
· 看到私网标签 → 知道属于哪个 VRF
· 弹掉私网标签,在对应 VRF 里查表 → 转发给 CE-B
★ 关键:P 设备不需要任何 VPN 配置,只跑 IGP + LDP 就行
跨域 MPLS VPN:三种 Option
一个客户的站点分布在两个 AS 里,怎么打通?三种方案,复杂度递增、扩展性也递增:
| Option A | Option B | Option C | |
|---|---|---|---|
| 做法 | ASBR 之间背靠背 VRF,每个 VPN 建一个子接口 + EBGP | ASBR 之间跑 MP-EBGP 交换 VPNv4 路由,ASBR 不存 VPN 实例路由 | 两端 PE 之间直接建多跳 MP-EBGP,ASBR 只传带标签的公网路由 |
| ASBR 压力 | 大(要存所有 VPN 的路由) | 中(存 VPNv4 路由,不存 VPN 实例) | 小(只存公网路由) |
| 扩展性 | 差(VPN 数量一多,子接口爆炸) | 中 | 最好 |
| 配置复杂度 | 简单 | 中 | 最复杂 |
| 用在哪 | 小型跨域、VPN 数量少 | 主流方案 | 大型运营商骨干 |
Hub-Spoke 组网
Hub-Spoke 是最常见的 MPLS VPN 拓扑之一,用 RT 的导入导出不对称就能实现:
- Spoke 之间不允许直接互通(分支不能互相访问,只能访问总部);
- Spoke 的 export RT 只有 Hub 能 import;Spoke 的 import RT 只包含 Hub 的;
- Hub 的 import RT 包含所有 Spoke 的,export RT 只有一个。
注意:Spoke 访问 Spoke 时流量会绕到 Hub 再回来,Hub 侧要留意带宽和转发性能。
配置:一个完整的 MPLS VPN
mpls lsr-id 1.1.1.1
mpls
mpls ldp
#
interface GigabitEthernet0/0/1
mpls
mpls ldp
# 用 LDP 给 IGP 路由分配标签,形成 LSP
ip vpn-instance VPN_A
ipv4-family
route-distinguisher 100:1 # RD
vpn-target 1:1 export-extcommunity # Export RT
vpn-target 1:1 import-extcommunity # Import RT
interface GigabitEthernet0/0/2
ip binding vpn-instance VPN_A
ip address 192.168.1.1 255.255.255.0
bgp 100
peer 2.2.2.2 as-number 100
peer 2.2.2.2 connect-interface LoopBack0
ipv4-family vpnv4 # ★ 关键:VPNv4 地址族
peer 2.2.2.2 enable
peer 2.2.2.2 advertise-community # 要带 RT,必须开
ipv4-family vpn-instance VPN_A
import-route direct
import-route static
★ 顺序不能错:先建 VPN 实例、再配 MP-BGP,
否则 vpn-instance 地址族下会找不到实例
验证与排错
# 公网侧
display mpls lsp # ★ 所有 LSP
display mpls ldp session # LDP 会话状态(Oper 才算正常)
display mpls ldp peer
display mpls lsp verbose # 看某条 LSP 的入/出标签和下一跳
# VPN 侧
display ip vpn-instance # VPN 实例列表
display ip vpn-instance VPN_A # ★ RD、RT、绑定接口
display ip routing-table vpn-instance VPN_A # ★ VRF 里的路由
display bgp vpnv4 all peer # MP-BGP 邻居
display bgp vpnv4 vpn-instance VPN_A routing-table # VRF 的 BGP 路由
display bgp vpnv4 all routing-table # ★ 所有 VPNv4 路由(含 RD)
# 端到端
ping -vpn-instance VPN_A 192.168.2.2 # 在指定 VRF 里 ping
四个高频问题:
- 公网能通、VPN 不通 → 先看
display bgp vpnv4 all peer是不是 Established; - MP-BGP 邻居起来了但没路由 → 九成是 RT 没匹配上。用
display bgp vpnv4 all routing-table看对端发来的路由带了什么 RT,再对比本地的 import RT; - VPN 路由有但数据不通 → 查私网标签有没有分配。PE 之间要能互相看到对方的 VPNv4 路由并带标签,否则出不了包;
- P 设备要不要配 VPN? → 不用。P 只跑 IGP + LDP。如果 P 上要配 VPN 实例,说明你的拓扑设计有问题。
一句话总结:MPLS 用标签替代逐跳查表,MPLS VPN 用"VRF 隔离路由表 + RD 让前缀唯一 + RT 控制收发 + 双层标签转发"四件事,在运营商的一张物理网上跑出成千上万个互不可见的客户 VPN。P 设备对 VPN 完全无感——这是它最漂亮的地方。
📌 本篇整理自 2024–2025 的「数通」学习笔记(HCIE-Datacom 方向)
合并了原始笔记中「MPLS-VPN / MPLS-hty / mpls 跨域 / mpls-vpn--hub-spoke / VPN技术 / 隧道技术及GRE」几页。
原笔记里夹着大量 MPLS 实验截图(含 display mpls lsp 输出与标签栈抓包),本文把标签结构和转发过程重新画成了图。
配置命令保留华为 VRP 原样。