第157篇:PHP(次末跳弹出)机制
关键词
PHP、Penultimate Hop Popping、次末跳弹出、Implicit NULL、Explicit NULL、标签栈优化
一、为什么需要 PHP?
1.1 Egress LSR 的负担
回顾标准的 MPLS 转发过程:
Ingress Transit Egress
| LSR ──▶ | Push R2 | LSR ───────▶ | Swap R3 | LSR ──────▶ | Pop R4 | ──────────▶ IP 转发 |
|---|---|---|---|---|---|---|
| └───────┘ L=200 └───────┘ L=100 └───────┘ L=100 | ||||||
| │ | ||||||
| │ 还要查 LFIB | ||||||
| ▼ | ||||||
| IP 路由表 |
问题:Egress LSR 做了两件事: 1. 收到标签 → 查找 LFIB → Pop 2. 去掉标签后 → 查找 IP 路由表 → 转发给 CE
但如果 Egress LSR 的 CPU/转发引擎比较紧张,查两次表会降低转发性能。
1.2 PHP 的解决思路
PHP 的核心思想:在 LSP 的倒数第二跳(Penultimate Hop)就把标签弹出,这样 Egress LSR 收到的是普通的 IP 包,直接进行 IP 转发即可,不必再做标签查找。
PHP 之后:
Ingress Transit(PHP) Egress
| LSR ───▶ | Push R2 | LSR ───────▶ | Pop R3 | LSR ──────────▶ | 直接 IP 转发 R4 | ──────────▶ |
|---|---|---|---|---|---|---|
| └───────┘ L=200 └───────┘ 裸 IP 包 └───────┘ 只看 IP 路由 |
二、Implicit NULL(隐式空标签)
2.1 什么是 Implicit NULL
Implicit NULL(隐式空标签) 是一个特殊标签值 3。
当 Egress LSR 为某个 FEC 分配标签时,它可以分配标签值 3(Implicit NULL),而不是一个普通标签。
含义:告诉上游 LSR——"你不需要给我发标签,直接把标签弹出,把裸 IP 包扔给我就行。"
2.2 分配过程
LDP 标签分配
| R2 ◀────── | Label Map FEC= 10.0 Label =300 | R3 ◀────── | Label Map FEC= 10.0 Label =200 | R4 |
|---|---|---|---|---|
| │ | ||||
| R4 分配标签:Implicit NULL(3) | ||||
| 告诉 R3:不要送标签给我,Pop 掉 |
R3 收到 Implicit NULL 后: - 不再为这一 FEC 分配出标签 - 在 LFIB 中,操作设为 Pop(PHP)
2.3 转发表对比
没有 PHP 的情况:
R3 的 LFIB:
In-Label Out-Label Out-IF Operation
──────── ──────── ────── ─────────
200 100 GE0/0/1 Swap
R4 的 LFIB:
In-Label Out-Label Out-IF Operation
──────── ──────── ────── ─────────
100 - - Pop → IP lookup
开启 PHP(Implicit NULL)后:
R3 的 LFIB:
In-Label Out-Label Out-IF Operation
──────── ──────── ────── ─────────
200 - GE0/0/1 Pop(PHP)
R4 的 LFIB:
In-Label Out-Label Out-IF Operation
──────── ──────── ────── ─────────
- - - -(不需要入标签了)
三、Explicit NULL(显式空标签)
3.1 为什么需要 Explicit NULL
Implicit NULL 有一个副作用:标签弹出后,原本标签中的 EXP 位信息也丢失了。
Exp(3 位)用于携带 QoS 信息。如果在次末跳就把标签弹掉了,Egress LSR 就无法根据 Exp 位做 QoS 处理。
Explicit NULL(显式空标签,标签值 0)解决了这个问题:
- Egress LSR 分配标签 0(Explicit NULL)
- 上游 LSR 收到后,照常 Push 标签 0 到 Egress
- Egress LSR 收到标签 0 后,先读取 Exp 位(QoS 信息),再 Pop 标签
- 标签 0 的头部长度仍然是 4 字节,Exp 位得以保留
3.2 Implicit NULL vs Explicit NULL
| 对比项 | Implicit NULL(3) | Explicit NULL(0) |
|---|---|---|
| PHP 行为 | 次末跳弹出,不送标签 | 次末跳照常送标签 0 |
| Egress 收到 | 裸 IP 包 | 标签 0 + IP 包 |
| Egress 操作 | 直接 IP 转发 | 读 Exp → Pop → IP 转发 |
| Exp 保留 | 丢失 | 保留 |
| 适用场景 | 不需要 QoS 的纯转发 | 需要 QoS 保留的场景 |
3.3 Explicit NULL 的配置
# 华为设备强制使用 Explicit NULL
mpls ldp
explicit-null # 全局配置 Explicit NULL
!
# 或针对特定 FEC
ip prefix-list FORCE_EXPLICIT_NULL permit 10.0.0.0/24
mpls ldp
explicit-null for prefix-list FORCE_EXPLICIT_NULL
四、PHP 的完整转发对比
4.1 无 PHP
R1 发送 IP 包
│
R2(Ingress):Push Label 200
│ MPLS(200)
R3(Transit):Swap → Label 100
│ MPLS(100)
R4(Egress):Pop → IP → IP 路由转发
│ IP
CE
R4 的工作量:LFIB 查找(Pop)+ IP 路由表查找 = 两次查找
4.2 有 PHP(Implicit NULL)
R1 发送 IP 包
│
R2(Ingress):Push Label 200
│ MPLS(200)
R3(PHP):Pop → 裸 IP 包
│ IP
R4(Egress):仅 IP 路由转发
│ IP
CE
R4 的工作量:IP 路由表查找 = 一次查找
4.3 有 Explicit NULL
R1 发送 IP 包
│
R2(Ingress):Push Label 200
│ MPLS(200)
R3(Transit):Swap → Label 0(Explicit NULL)
│ MPLS(0, Exp=5)
R4(Egress):读 Exp → Pop → IP 路由转发
│ IP(标记优先级)
CE
五、华为设备上的 PHP 行为
5.1 默认行为
华为设备默认启用 PHP,即 Egress LSR 会分发 Implicit NULL 标签给上游邻居。
<HUAWEI> display mpls lsp
LSP Information: LDP LSP
FEC In-Label Out-Label Interface Out-Interface LSID
10.0.0.0/24 - 200 - GE0/0/0 3
^^^^^^^^
操作类型为 3(Pop),即 PHP
5.2 验证 PHP
# 查看 LDP 标签绑定
<HUAWEI> display mpls ldp label
Label[Out]: 3 Label[In]: 200 FEC: 10.0.0.0/24
↑
标签值为 3 表示 Implicit NULL
5.3 配置 Explicit NULL
mpls ldp
explicit-null # 全局启用 Explicit NULL
# 验证
<HUAWEI> display mpls ldp label
Label[Out]: 0 Label[In]: 200 FEC: 10.0.0.0/24
↑
标签值为 0 表示 Explicit NULL
六、PHP 的适用场景
| 场景 | 推荐模式 | 原因 |
|---|---|---|
| 普通 LDP LSP | Implicit NULL | 减少 Egress 负担,默认即可 |
| MPLS VPN | Implicit NULL | Egress PE 需要查 VPN 标签,不再需要外层标签 |
| 需要 QoS 保留 | Explicit NULL | Exp 位需要在 Egress 被读取 |
| 管道模型(Pipe Model) | Explicit NULL | QoS 必须在 Egress 被传递到 CE |
| 短标签场景 | Implicit NULL | 标签资源紧张时优先使用 |
七、常见问题
7.1 PHP 后的 IP TTL
问:PHP 弹出标签后,IP TTL 是否受影响?
答:不影响。标签的 TTL 与 IP TTL 是独立维护的: - MPLS TTL 只在标签操作时递减 - IP TTL 保持原值 - PHP 只是去掉标签,不影响 IP 层
7.2 多层标签的 PHP
在 MPLS VPN(双层标签)场景中: - 外层标签(LDP 标签)在倒数第二跳被 PHP 弹出 - 内层标签(VPN 标签)保留到 Egress PE 查看
PE1 P1 P2 PE2
| Push LDP+ VPN | ────▶ | Swap LDP (外层) | ───▶ | PHP (Pop 外层) | ───▶ | 仅 VPN 标签 查 VRF | ───▶ CE |
|---|---|---|---|---|---|---|---|
| 双层标签 双层标签 只剩VPN 标签恢复 | |||||||
| 标签 IP |
八、总结
| 知识点 | 核心要点 |
|---|---|
| PHP | 次末跳弹出,Egress 不再做标签查找 |
| Implicit NULL(3) | 次末跳直接 Pop,Egress 收到裸 IP 包 |
| Explicit NULL(0) | 次末跳照常送标签 0,保留 Exp 位 |
| 默认行为 | 华为/Cisco/Juniper 均默认启用 Implicit NULL |
| 适用场景 | 普通转发用 Implicit NULL;需要 QoS 保留用 Explicit NULL |
九、思考
- PHP 解决了什么问题?
- Implicit NULL 和 Explicit NULL 的核心区别是什么?
- 为什么有些场景需要使用 Explicit NULL?
- 在 MPLS VPN 中,PHP 只弹出哪一层标签?为什么?
- 如何验证设备当前使用的是 Implicit NULL 还是 Explicit NULL?
下篇预告:第158篇《MPLS 流量工程基础:RSVP-TE》——MPLS TE 如何显式控制流量路径,RSVP-TE 如何通过信令建立 TE 隧道。