首页 › deep-tech › 5G PDCP层:加密压缩重排序的设计哲学

5G PDCP层:加密、压缩、重排序的设计哲学

你有没有想过:你在手机上刷的视频,在空中飞的时候,是谁负责把它"加密锁好"、把"臃肿的头部瘦身"、再把"乱序的包裹排好"?答案就是PDCP——5G协议栈中最容易被忽视、却最不可或缺的"安全管家兼物流调度员"。

一、从一个快递包裹说起

想象你是一家电商仓库的打包员。你的工作流程是这样的:

  1. 验货贴标:确认商品完好,贴上防伪标签(完整性保护)
  2. 锁进密码箱:用只有收件人知道的密码锁上(加密)
  3. 精简包装:把过度包装的快递盒换成薄袋子(头压缩)
  4. 编好序号:给每个包裹标上顺序号,方便收件人按顺序拆(重排序)
  5. 防丢兜底:如果某个包裹在运输中丢失,准备一份备用(PDCP复制)

这五步,恰好对应了5G PDCP层的五大核心功能。PDCP全称 Packet Data Convergence Protocol(分组数据汇聚协议),位于RLC层之上、SDAP/RRC层之下,是Layer 2的"天花板"。

二、PDCP在协议栈中的位置

先看全貌,再逐个深入:

graph TB
    subgraph 用户面["用户面(User Plane)"]
        APP["应用层<br/>(视频/网页/游戏)"]
        SDAP["SDAP层<br/>QoS流映射"]
        PDCP_U["🔐 PDCP层<br/>加密 · 头压缩 · 重排序"]
        RLC_U["RLC层<br/>分段/ARQ"]
        MAC_U["MAC层<br/>调度/复用"]
        PHY_U["PHY层<br/>调制/编码"]
    end

    subgraph 控制面["控制面(Control Plane)"]
        NAS["NAS层<br/>核心网信令"]
        RRC["RRC层<br/>无线资源控制"]
        PDCP_C["🔐 PDCP层<br/>加密 · 完整性保护 · 重排序"]
        RLC_C["RLC层"]
        MAC_C["MAC层"]
        PHY_C["PHY层"]
    end

    APP --> SDAP --> PDCP_U --> RLC_U --> MAC_U --> PHY_U
    NAS --> RRC --> PDCP_C --> RLC_C --> MAC_C --> PHY_C

    style PDCP_U fill:#ff6b6b,color:#fff,stroke:#c0392b
    style PDCP_C fill:#ff6b6b,color:#fff,stroke:#c0392b

注意一个关键区别:用户面和控制面都经过PDCP,但职责不同:

功能 用户面(DRB) 控制面(SRB)
加密/解密 ✅ ✅
完整性保护 ❌(可选) ✅(必须)
头压缩(ROHC) ✅ ❌
重排序 ✅ ✅
重复检测 ✅ ✅
PDCP复制 ✅ ✅

为什么控制面不做头压缩? 因为RRC信令本身已经是精简的二进制编码(ASN.1 PER),没有臃肿的IP/UDP/RTP头部需要压缩。头压缩专为VoLTE/VoNR等小包业务设计,一个语音包有效载荷才几十字节,IP头部却占了40字节——不压缩太浪费空口资源了。

三、加密与完整性保护:空口安全的第一道锁

3.1 加密的原理

PDCP加密的本质是流密码异或(XOR):用密钥和一组参数生成一串伪随机 keystream,再与明文逐比特异或。

$$Ciphertext = Plaintext \oplus Keystream(KEY, COUNT, BEARER, DIRECTION)$$

其中: - KEY:从5G-AKA认证流程派生的密钥($K_{UPenc}$ 用于用户面,$K_{RRCP}$ 用于控制面加密) - COUNT:32位计数器 = HFN(超帧号)+ PDCP SN(序列号) - BEARER:无线承载标识(5位) - DIRECTION:方向位(上行=0,下行=1)

5G支持四种加密算法:

算法标识 名称 基础算法 说明
NEA0 空加密 无 调试用,不提供安全保护
NEA1 128-NEA1 SNOW 3G 继承自4G的流密码算法
NEA2 128-NEA2 AES-128 CTR AES计数器模式
NEA3 128-NEA3 ZUC 中国国密算法

关键设计细节:COUNT值的滚动

COUNT是一个32位的"永不回头"计数器。低12位(或18位)是PDCP SN,高位是HFN。SN溢出回绕时,HFN自动加1。这意味着每个PDCP包都对应唯一的COUNT值,同一个密钥绝不会对相同的keystream加密两次(否则就破解了——"两时间垫"攻击)。

graph LR
    subgraph COUNT值结构["COUNT值(32位)"]
        HFN["HFN(超帧号)<br/>20位 或 14位"]
        SN["PDCP SN<br/>12位 或 18位"]
    end

    SN --"溢出回绕"--> HFN

    subgraph 加密输入["加密算法输入"]
        KEY["密钥 KEY<br/>128位"]
        COUNT_IN["COUNT<br/>32位"]
        BEARER["承载ID<br/>5位"]
        DIR["方向<br/>1位"]
    end

    KEY --> CRYPTO["加密算法<br/>NEA1/2/3"]
    COUNT_IN --> CRYPTO
    BEARER --> CRYPTO
    DIR --> CRYPTO
    CRYPTO --> KS["Keystream<br/>伪随机序列"]
    KS --> XOR["⊕ 明文"]
    XOR --> CIPHER["密文"]

    style CRYPTO fill:#e74c3c,color:#fff
    style XOR fill:#f39c12,color:#fff

3.2 完整性保护

完整性保护与加密不同——它不是为了保密,而是为了防篡改。控制面信令(RRC消息)必须做完整性保护,防止中间人篡改切换命令、测量配置等关键信令。

完整性保护算法(NIA系列)在PDCP PDU末尾附加一个32位的 MAC-I(消息认证码):

$$MAC\text{-}I = NIA(KEY, COUNT, BEARER, DIRECTION, PDU_{header} + PDU_{payload})$$

接收端用同样的密钥和参数计算出X-MAC,与收到的MAC-I比对。如果不一致——对不起,这个包被篡改过,丢弃。

一个容易忽略的调试陷阱:如果基站和手机的COUNT值不同步(比如切换时SN续传出错),即使密钥正确,加密/完整性校验也会失败。这类问题在路测中表现为"加密失败"或"完整性校验失败",但根因往往是PDCP SN同步问题,而非密钥错误。

四、头压缩ROHC:把40字节头部压缩到1字节

4.1 为什么需要头压缩?

看一组数据:

业务类型 有效载荷 IPv4/UDP/RTP头部 头部占比
VoLTE语音 32字节 40字节 55.6%
VoLTE语音 16字节 40字节 71.4%
视频流 1500字节 40字节 2.6%

对于语音业务,超过一半的空口资源被"地址信息"吃掉了——这就像寄快递时,快递盒上的地址标签比里面的商品还大。ROHC就是来解决这个问题的。

4.2 ROHC的核心思想:上下文复用

IP/UDP/RTP头部里,大量字段是不变或可预测的:

字段类别 例子 变化规律
完全不变 源/目的IP、源/目的端口 整个会话期间不变
可预测增量 RTP序号、RTP时间戳 每个包固定增量
随机变化 IP ID(某些实现) 需要每次传输

ROHC的哲学:既然你和我已经知道大部分信息,就不用每次都重复了。就像老朋友打电话,第一次说"我是北京市海淀区的张三",以后只需说"我"——双方都知道上下文。

4.3 ROHC三状态压缩机

stateDiagram-v2
    [*] --> IR : 建立承载
    IR --> FO : 收到确认<br/>建立部分上下文
    FO --> SO : 收到确认<br/>完整上下文建立
    SO --> FO : 检测到<br/>上下文变化
    FO --> IR : 多次未确认<br/>上下文丢失
    SO --> IR : 多次未确认<br/>上下文丢失

    note right of IR
        IR状态(初始化与刷新)
        发送完整头部
        压缩后约20-40字节
    end note

    note right of FO
        FO状态(一阶压缩)
        只发送变化字段
        压缩后约5-10字节
    end note

    note right of SO
        SO状态(二阶压缩)
        只发送增量/序号
        压缩后仅1-3字节!
    end note

压缩率的演进:

状态 压缩后头部大小 压缩率(40字节原始头部)
IR状态 ~20-40字节 0%-50%
FO状态 ~5-10字节 75%-87.5%
SO状态 1-3字节 92.5%-97.5%

ROHC中的"R"代表Robust(健壮的)。与早期的IP头压缩(RFC 2507)不同,ROHC能容忍一定的丢包而不会丢失上下文。它通过W-LSB编码(窗口最低有效位)技术,即使丢了几个包,接收端也能通过滑动窗口推断出正确的字段值。

4.4 ROHC Profile(配置文件)

不同业务用不同的压缩策略:

Profile ID 压缩对象 典型应用
0x0000 无压缩 调试/回退
0x0001 RTP/UDP/IP VoLTE/VoNR语音
0x0002 UDP/IP 视频流、游戏
0x0003 ESP/IP VPN隧道
0x0004 IP 纯IP数据
0x0006 TCP/IP 网页浏览

实战连接:在VoLTE优化中,如果发现语音MOS分异常低但无线质量良好,检查一下ROHC是否正确协商。如果ROHC Profile没有匹配上(比如应该用0x0001但协商成了0x0000),头部没有压缩,语音包在空口传输效率骤降,可能导致延迟和抖动增加。

五、重排序:让乱序的包裹排好队

5.1 为什么会乱序?

数据包到达PDCP层时可能乱序,原因包括:

  1. RLC AM重传:后面的包先到,前面丢失的包重传后到
  2. 切换数据转发:切换时,源基站和目标基站同时转发数据,到达顺序不确定
  3. PDCP复制:同一包走两条路径,到达时间不同
  4. CA(载波聚合):不同载波的调度延迟不同

5.2 重排序窗口机制

PDCP接收端维护一个重排序窗口,核心参数:

参数 含义
RX_NEXT 期望接收的下一个PDCP SN
RX_DELIV 第一个未交付给上层的PDCP SN
t-Reordering 重排序定时器
reordering_Window 窗口大小(SN长度的一半)

重排序的工作逻辑:

flowchart TD
    RECV["收到PDCP PDU<br/>SN = X"] --> CHECK1{"X 在窗口内?"}
    CHECK1 -- 否 --> DROP["丢弃"]
    CHECK1 -- 是 --> CHECK2{"X == RX_DELIV?<br/>正好是期望的序号"}
    CHECK2 -- 是 --> DELIVER["立即交付给上层<br/>更新 RX_DELIV"]
    CHECK2 -- 否 --> BUFFER["缓存该PDU"]
    BUFFER --> CHECK3{"重排序定时器<br/>正在运行?"}
    CHECK3 -- 否 --> CHECK4{"X > RX_DELIV?<br/>(发现了缺口)"}
    CHECK4 -- 是 --> START["启动 t-Reordering<br/>等待缺失的包"]
    CHECK3 -- 是 --> WAIT["继续等待"]
    CHECK4 -- 否 --> WAIT2["不启动定时器<br/>(填入已有缺口后面的包)"]

    TIMER["t-Reordering超时"] --> FORWARD["将 RX_DELIV 到<br/>第一个缓存包之前的<br/>所有PDU交付上层"]

    style DELIVER fill:#27ae60,color:#fff
    style START fill:#e67e22,color:#fff
    style TIMER fill:#e74c3c,color:#fff
    style FORWARD fill:#8e44ad,color:#fff

通俗理解:想象你在收编号1-100的快递。你已经收到1-5号,第6号没来但7、8号来了。你把7、8号先放着(缓存),等第6号(启动定时器)。如果定时器到了第6号还没来——算了,7、8号先上交,第6号当丢了。

5.3 PDCP SN(序列号)长度

承载类型 SN长度 范围
SRB(信令承载) 5位 0-31
DRB(数据承载) 12位 0-4095
DRB(数据承载) 18位 0-262143

为什么有12位和18位两种选择? 12位的SN在高速业务下很快回绕(一个100Mbps的TCP连接,约0.4秒就会绕一圈),可能导致COUNT值快速增长。18位SN提供了更大的"缓冲",适合高速率场景。但SN越长,PDCP头部开销越大(12位SN头部1字节,18位SN头部3字节)。

六、PDCP复制:一份保险,两条路径

这是5G NR新增的重要功能,专为URLLC(超可靠低延迟) 场景设计。

6.1 原理

同一个PDCP PDU被复制两份,分别通过两个独立的RLC实体发送。这两条路径可以是: - 同一MAC实体下的不同载波(CA场景) - 不同MAC实体(DC场景,即双连接)

graph TD
    SDU["PDCP SDU<br/>(原始数据包)"]
    SDU --> ADD_SN["添加PDCP SN<br/>编号"]
    ADD_SN --> ENCRYPT["加密"]
    ENCRYPT --> COPY{"PDCP复制<br/>激活?"}

    COPY -- 是 --> PATH1["路径1<br/>RLC实体1 → MAC1 → 载波1"]
    COPY -- 是 --> PATH2["路径2<br/>RLC实体2 → MAC2 → 载波2"]
    COPY -- 否 --> PATH_ONLY["单一RLC实体<br/>正常传输"]

    PATH1 --> RECV["接收端 PDCP"]
    PATH2 --> RECV
    PATH_ONLY --> RECV
    RECV --> DEDUP["重复检测<br/>丢弃副本"]
    DEDUP --> UPPER["交付上层"]

    style COPY fill:#e74c3c,color:#fff
    style DEDUP fill:#27ae60,color:#fff

6.2 设计权衡

方面 有利 有代价
可靠性 两条路径独立,一条断了另一条还在 空口资源消耗翻倍
延迟 不用等重传,哪个先到用哪个 额外的PDCP头部和MAC CE开销
适用场景 工业控制、远程手术、车联网 不适合大流量业务(太浪费资源)

激活方式:PDCP复制可以动态开关——通过MAC CE(Control Element)快速激活/去激活。当信道质量好时关闭复制节省资源,信道变差时瞬间打开复制保证可靠性。

七、PDCP在切换中的关键角色

切换是PDCP最繁忙的时刻之一。它要做这些事:

7.1 切换数据转发

sequenceDiagram
    participant UE as 手机(UE)
    participant Source as 源gNB
    participant Target as 目标gNB

    Source->>UE: RRC Reconfiguration(切换命令)
    Note over UE: 暂停上行发送<br/>保存PDCP状态

    Source->>Target: 转发未确认的<br/>下行PDCP SDU
    Source->>Target: 转发缓存的<br/>上行PDCP SDU
    Note over Target: 按SN排序<br/>填补缺口

    UE->>Target: RRC Reconfiguration Complete
    Note over UE,Target: 密钥更新<br/>SN续传/重置
    Target->>UE: 继续数据传输

7.2 密钥更新

切换时必须更新加密密钥,防止源基站继续解密用户在新基站的数据(前向安全)。5G通过密钥衍生函数,用源密钥和目标PCI/频率生成新密钥:

$$K_{NG-RAN^{*}} = KDF(K_{NG-RAN}, PCI \parallel ARFCN)$$

7.3 SN处理模式

切换时PDCP SN有两种处理模式:

模式 说明 适用场景
SN续传 目标基站从源基站的SN继续编号 AM模式DRB,保证数据连续性
SN重置 目标基站从0开始重新编号 UM模式DRB或SRB

调试经验:切换后的第一个PDCP包最容易出问题。如果看到切换完成后立即出现"加密失败"或"头压缩上下文丢失",通常是因为: 1. COUNT值没有正确同步 2. ROHC上下文没有正确转移 3. 密钥更新时序出错

八、Discard Timer:过期就扔的保鲜机制

PDCP层还有一个容易被忽略的定时器:Discard Timer(丢弃定时器)。

每个PDCP SDU从上层到达时启动一个Discard Timer。如果这个包在定时器到期前还没被下层(RLC/MAC/PHY)成功发出去——直接丢弃,不发了。

为什么这样设计?

在实时业务(如语音、视频通话)中,迟到的数据包没有意义。如果一个语音包已经延迟了100ms才发出去,对方收到时已经过了播放时间,只会造成回声或卡顿。不如直接扔掉,让上层重传或跳过。

场景 建议Discard Timer值
VoLTE/VoNR语音 20-40ms
视频流 100-200ms
TCP数据(eMBB) 不配置或很大
URLLC工业控制 5-10ms

九、PDCP PDU格式一览

PDCP有两种PDU:数据PDU和控制PDU。

9.1 PDCP Data PDU

┌──────────────────────────────────────────────────┐
│ PDCP Header                                       │
│ ┌─────────┬────────────┬──────────┐               │
│ │ D/C │ R │ PDCP SN    │          │               │
│ │(1b) │   │(12b/18b)   │          │               │
│ └─────────┴────────────┴──────────┘               │
├──────────────────────────────────────────────────┤
│ Payload(加密后的数据/头压缩后的数据)                │
├──────────────────────────────────────────────────┤
│ MAC-I(仅控制面,32位)                             │
└──────────────────────────────────────────────────┘

9.2 PDCP Control PDU

控制PDU类型 功能
ROHC反馈 解压器告诉压缩机上下文状态
PDCP Status Report 切换时告知对方哪些SN已收到/未收到
Ethernet头压缩反馈 5G新增加的以太网头压缩

Status Report在切换时尤其重要——目标基站通过它告诉手机"我已经收到了SN 1-100,请从101开始发"。这避免了切换后的数据重复和丢失。

十、实战调试场景

场景1:VoLTE语音质量差

现象:无线指标正常(RSRP>-90dBm,SINR>15dB),但语音MOS分低于3.0。

排查路径: 1. 检查PDCP层ROHC是否激活(Profile是否正确协商为0x0001) 2. 检查PDCP层丢包率(PDCP SDU discard rate) 3. 检查Discard Timer配置是否过小(可能误杀正常的语音包) 4. 检查12位SN是否够用(高速率场景应考虑18位SN)

场景2:切换后数据中断

现象:切换完成后,下行数据中断200-500ms。

排查路径: 1. 检查数据转发是否正常(源gNB是否转发了未确认的PDCP SDU) 2. 检查目标gNB的PDCP重排序窗口是否正确设置 3. 检查t-Reordering定时器是否过大(导致等待时间过长) 4. 检查密钥更新是否成功(COUNT值是否同步)

场景3:URLLC业务可靠性不足

现象:工业控制指令偶尔丢失,端到端可靠性达不到99.999%。

排查路径: 1. 检查PDCP复制是否激活 2. 检查两条路径是否真正独立(不同载波/不同MAC实体) 3. 检查MAC CE动态激活/去激活时延 4. 检查重复检测逻辑是否正确(避免把重复包误当新包)

十一、PDCP vs 4G PDCP:进化了什么?

特性 4G LTE PDCP 5G NR PDCP
头压缩 ROHC仅用于用户面 ROHC + 以太网头压缩
完整性保护 仅控制面 控制面必须,用户面可选
SN长度 5/7/12位 5/12/18位
PDCP复制 不支持 支持(CA/DC)
乱序交付 不支持 支持(outOfOrderDelivery)
路由到多个RLC 不支持 支持辅助RLC实体
加密算法 EEA0/1/2/3 NEA0/1/2/3(密钥体系不同)

最大变化:5G PDCP新增了PDCP复制功能,这是4G完全没有的能力,直接服务于URLLC场景。同时18位SN的引入,使PDCP能适应更高的数据速率。

常见问题

Q: PDCP加密和NAS加密有什么区别?谁保护的范围更大? A: NAS加密保护的是手机和核心网(AMF)之间的信令,只保护NAS消息。PDCP加密保护的是空口段(手机和基站之间),覆盖所有用户数据和RRC信令。两者是独立的加密层,5G采用"双重加密"理念——NAS信令经过NAS加密后,再经过PDCP加密,实现端到端+空口的双重保护。

Q: 为什么VoLTE的头压缩效果这么明显,但刷网页时几乎没有感觉? A: 头压缩的收益取决于"头部占总包的比例"。语音包很小(约32字节),40字节的IP/UDP/RTP头部占比超过50%,压缩到1-3字节后效率翻倍。而网页浏览的TCP包通常是1500字节,头部只占2.6%,压缩收益微乎其微。所以ROHC对VoLTE/VoNR是刚需,对大数据业务是锦上添花。

Q: PDCP重排序和RLC AM的按序交付有什么区别?不会重复吗? A: RLC AM确实保证按序交付给PDCP,但有几个场景RLC无法覆盖:(1) 切换时源基站和目标基站的数据合并;(2) PDCP复制场景下两条路径的数据合并;(3) RLC UM模式不保证顺序。PDCP的重排序是"最后一道关卡",覆盖所有乱序场景。

Q: t-Reordering定时器设置多大合适? A: 典型值为10-50ms。设置太小,正常延迟的包会被误判为丢失;设置太大,上层需要等待更久才能拿到数据。建议根据业务类型调整:语音业务用小值(10-20ms),数据业务可适当放大(30-50ms)。实际上,这个参数是网络侧通过RRC信令配置给手机的。

Q: PDCP复制会浪费一半的空口资源吗?什么时候该用? A: 从空口资源角度确实如此——每个包发两份。但URLLC业务(工业控制、远程手术)的数据量通常很小(一个指令可能只有几十字节),而可靠性的收益巨大。所以PDCP复制适合"小包、高可靠"场景,不适合视频流等大流量场景。5G的动态激活机制也允许按需开关——信道好时关闭,信道差时打开。

参考来源

  1. 5G NR PDCP Layer: Functions, Architecture, and Procedures — RF Wireless World提供的PDCP层架构和功能详解
  2. 5G PDCP Complete Guide — Functions, Headers, Timers, Reordering — Mohamed Eladawi的PDCP完整指南
  3. PDCP Duplication in 5G: Carrier Aggregation & Dual Connectivity — TelecomTrainer的PDCP复制技术解析
  4. NR PDCP ROHC Header Compression — 3GLTEInfo的ROHC头压缩技术说明
  5. 安立技术文库:5G技术解读之PDCP层数据收发 — 安立公司知乎专栏的PDCP层中文技术解读

本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入