本文聚焦 3GPP TS 23.228(IMS Stage 2) 的移动台主叫(MOC, Mobile Originated Call)会话发起流程,结合 TS 24.229(基于SIP/SDP的IMS呼叫控制) 的预条件(Precondition)处理、RFC 3312/4032 的资源管理集成框架,以及 TS 23.503/TS 23.501 中 P-CSCF 通过 Rx/N5 向 PCF 申请 QoS 授权的 PCC 机制,逐条消息拆解 VoNR 主叫从 INVITE 到 ACK 的完整信令链,重点解析为什么 VoNR 必须使用"预条件"机制、SDP offer/answer 中
curr/des/conf三个属性的状态机含义,以及 SIP 层资源协商与 5G QoS Flow 建立的精确耦合点。
很多协议工程师第一次接触 IMS 呼叫时都会产生一个疑问:SIP 本身就是会话协商协议,为什么 3GPP 还要叠床架屋地引入一套"预条件"机制? 这个问题的答案,恰恰揭示了移动通信语音业务与固定互联网语音的根本差异。
在固定互联网中,SIP 终端在 INVITE 中协商出编解码(codec)后,媒体就可以直接在已建立 IP 连通性的链路上发送——因为 IP 承载是"尽力而为"的,不存在"预留失败"的问题。但在移动网络中,语音媒体必须承载在专用 GBR QoS Flow(5G 中标准化 5QI=1,会话类语音,PDB=100ms,PER=10⁻²)上,而专用 QoS Flow 的建立是一个独立的、可能失败的过程:它需要 SMF 通过 N2 接口向 gNB 申请无线资源、需要 gNB 执行准入控制(Admission Control)、需要 UE 激活对应的专用 DRB。
如果把这两个过程解耦——先让被叫振铃、被叫接听,再去建立专用承载——就会出现一个致命问题:用户已经"接通",但专用承载建立失败,导致语音根本无法传递,用户体验是"接通即掉话、接通即静音"。这在电信级语音服务中是不可接受的。
预条件机制(RFC 3312,由 RFC 4032 更新)的核心设计思想,就是把"双向专用承载资源都已就绪"作为一个强制性前置条件(mandatory precondition),挂在 SDP 协商中。只有当主叫、被叫双方的本地资源都预留完成,会话才允许进入振铃(180 Ringing)和接通(200 OK)阶段。换句话说,预条件机制用 SIP 的会话状态机,把承载资源预留的原子性强制保证在了用户感知层面之前。
GSMA NG.114(VoNR IMS Profile)和早期的 IR.92(VoLTE IMS Profile)都把"预条件支持"列为必选能力。这也是为什么任何符合标准的 VoNR 终端,其 IMS 注册时都会在 SIP Supported 头域中声明 precondition,并在发起呼叫时默认采用 mandatory 预条件。
下图是一条带双向 mandatory 预条件的 VoNR 主叫完整信令流。主叫 UE-A(发起方)与被叫 UE-B(终止方)各自经过"资源预留→UPDATE确认→振铃→接通"的标准节拍。
sequenceDiagram
autonumber
participant UE_A as 主叫 UE-A
participant PCSCF_A as P-CSCF-A
participant SCSCF as S-CSCF / I-CSCF
participant PCSCF_B as P-CSCF-B
participant UE_B as 被叫 UE-B
Note over UE_A,UE_B: 阶段1:初始 INVITE 携带 SDP Offer(预条件未满足)
UE_A->>PCSCF_A: INVITE (SDP Offer)<br/>curr:qos none / des:qos mandatory sendrecv
PCSCF_A->>SCSCF: INVITE (前转, 并向 PCF 发 AAR 申请 QoS 授权)
SCSCF->>PCSCF_B: INVITE
PCSCF_B->>UE_B: INVITE
Note over UE_A,UE_B: 阶段2:被叫回 183 Session Progress 携带 SDP Answer
UE_B-->>PCSCF_B: 183 Session Progress (SDP Answer)<br/>des mandatory + conf:qos remote sendrecv
PCSCF_B-->>SCSCF: 183
SCSCF-->>PCSCF_A: 183 (PCSCF_A 向 PCF 发 AAR, 触发 UE-A 侧专用 QoS Flow 建立)
PCSCF_A-->>UE_A: 183 Session Progress
Note over UE_A,UE_B: 阶段3:可靠传送 183(100rel)+ 本地资源预留
UE_A->>PCSCF_A: PRACK (确认 183)
PCSCF_A->>SCSCF: PRACK
SCSCF->>PCSCF_B: PRACK
PCSCF_B->>UE_B: PRACK
UE_B-->>UE_A: 200 OK (PRACK) 逐跳回传
Note over UE_A,UE_B: 阶段4:UE-A 本地专用承载建立完成,发 UPDATE
UE_A->>PCSCF_A: UPDATE (curr:qos local sendrecv)
PCSCF_A->>SCSCF: UPDATE
SCSCF->>PCSCF_B: UPDATE
PCSCF_B->>UE_B: UPDATE
Note over UE_A,UE_B: 阶段5:UE-B 本地承载建立完成,回 200(UPDATE),双向预条件全部满足
UE_B-->>PCSCF_B: 200 OK (UPDATE) (curr:qos local+remote sendrecv)
PCSCF_B-->>SCSCF: 200 OK (UPDATE)
SCSCF-->>PCSCF_A: 200 OK (UPDATE)
PCSCF_A-->>UE_A: 200 OK (UPDATE)
Note over UE_A,UE_B: 阶段6:预条件已满足,被叫安全振铃
UE_B-->>UE_A: 180 Ringing (逐跳前转)
Note over UE_B: 用户摘机应答
UE_B-->>UE_A: 200 OK (INVITE)
UE_A->>UE_B: ACK (双向媒体通路开启)
需要特别强调的三个关键节点:
a=curr:qos 全部为 none,a=des:qos 为 mandatory。这表示"我要求资源预留是强制性的,但现在双方资源都还没就绪",因此媒体通路方向此时是被挂起的。a=curr:qos local 翻成 sendrecv,向被叫宣告"我这边资源好了"。a=curr:qos remote 也翻成 sendrecv。此时四个预条件维度(local/remote × send/recv)全部满足,被叫才允许进入第 6 步的振铃。预条件机制的全部精髓,都浓缩在 SDP 的三个属性行里。下面是一条真实的 VoNR 主叫 INVITE 中 SDP Offer 的核心片段(节选自 TS 24.229 5.1.2.2 与 RFC 3312 第 5 节):
v=0
o=- 4568 4568 IN IP4 10.20.30.40
s=-
c=IN IP4 10.20.30.40
t=0 0
m=audio 49170 RTP/AVP 97 96
b=AS:41
b=RS:600
b=RR:2000
a=rtpmap:97 EVS/16000
a=fmtp:97 br=5.9-24.4; bw=nb-wb; max-red=220
a=rtpmap:96 AMR-WB/16000
a=fmtp:96 mode-change-capability=2; max-red=0
a=ptime:20
a=maxptime:240
a=sendrecv
a=curr:qos local none
a=curr:qos remote none
a=des:qos mandatory local sendrecv
a=des:qos mandatory remote sendrecv
RFC 3312 定义了三类预条件属性,每个属性都有 类型(type)+ 强度(strength)+ 方向(direction) 三元组结构:
| SDP 属性行 | 语义 | 典型取值 | 作用阶段 |
|---|---|---|---|
a=curr:qos <dir> <status> |
当前状态:本端当前观察到的资源预留进度 | curr:qos local none → curr:qos local sendrecv |
每次 SDP 交换都更新 |
a=des:qos <strength> <dir> <status> |
期望状态:要求达到的目标,决定是否阻塞会话 | des:qos mandatory local sendrecv |
Offer/Answer 中声明 |
a=conf:qos <dir> <status> |
确认请求:要求对端在满足时主动通知我 | conf:qos remote sendrecv |
触发对端发 UPDATE |
strength(强度)的三档决定了会话是否被阻塞:
- mandatory:必须满足,否则媒体方向被挂起(VoNR 默认采用此档)。
- optional:尽力满足,不阻塞媒体方向。
- none:不要求(用于取消预条件)。
direction(方向标签)是一个状态标记,不要和媒体方向 sendrecv 混淆。curr:qos local sendrecv 的正确读法是:"我本地(local)这一侧的资源,在发送(send)和接收(recv)两个方向上都已经预留完成(sendrecv 状态)"。
预条件属性总是从产生该 SDP 的一方视角来表述的:
- UE-A 说的 local = UE-A 自己接入侧的资源;UE-A 说的 remote = UE-B 接入侧的资源。
- UE-B 说的 local = UE-B 自己接入侧的资源;UE-B 说的 remote = UE-A 接入侧的资源。
这就产生了一个镜像关系:UE-A 的 local == UE-B 的 remote。所以当 UE-A 发 UPDATE 把自己 curr:qos local 置为 sendrecv 时,UE-B 收到后会把自己视角下的 remote 视为已满足。这种相对视角的交叉确认,正是双向预条件得以收敛的核心机制。
下面用状态图刻画四个维度(local/remote × send/recv)从 none 收敛到 sendrecv 的全过程:
stateDiagram-v2
[*] --> 两侧均为none: INVITE Offer<br/>curr local none<br/>curr remote none
两侧均为none --> A_local满足: UE-A 专用承载建立<br/>发 UPDATE (curr local sendrecv)
A_local满足 --> A_local_B_remote同时满足: UE-B 收 UPDATE<br/>B 的 remote 自动满足
A_local满足 --> B_local满足: UE-B 本地承载建立
A_local_B_remote同时满足 --> 全部满足: UE-B 回 200(UPDATE)<br/>curr local+remote sendrecv
B_local满足 --> 全部满足: UE-A 的 remote 满足
全部满足 --> 振铃: 180 Ringing 被允许前转
振铃 --> [*]: 200 OK (INVITE) + ACK<br/>双向媒体开启
理解了 SDP 层的状态机,下一个关键问题是:UE 怎么知道"本地资源预留完成"? 在 5G VoNR 架构下,这个"完成"信号来自 SMF 通过 N1 接口给 UE 下发的 PDU Session Modification Command(TS 23.502 Section 4.3.3.3),其中激活了承载语音媒体的专用 QoS Flow(5QI=1)。而触发这条修改流程的源头,正是 P-CSCF 通过 Rx/N5 接口向 PCF 申请的 QoS 授权。
下图刻画了从 SIP 信令到 5G 无线资源建立的完整数据面/控制面耦合链路:
flowchart TD
subgraph SIP["IMS 信令域 (SIP/SDP)"]
UE1["UE-A"]
PCSCF["P-CSCF\n(SDP 解析)"]
end
subgraph PCC["策略与计费控制 (PCC)"]
PCF["PCF\n(Rx/N5 + N7)"]
SMF["SMF\n(会话管理)"]
end
subgraph DPR["5G 数据面与无线"]
UPF["UPF\n(N3/N9)"]
gNB["gNB\n(DRB)"]
UE2["UE-A 专用承载"]
end
UE1 -->|"INVITE/183\n携带 SDP"| PCSCF
PCSCF -->|"AAR (Rx) / Npcf_PolicyAuthorization (N5)\n提取 media component"| PCF
PCF -->|"N7 SM Policy Association\n下发 PCC rule (5QI=1, GBR)"| SMF
SMF -->|"N4\n建立/修改 N3/N9 隧道"| UPF
SMF -->|"N2 PDU Session Resource Setup\n(Ngap PDU Session Resource Setup Item)"| gNB
SMF -->|"N1 QoS rule 激活\n(5QI=1)"| UE2
gNB --> UE2
UE2 -.->|"检测到本地专用承载激活\n触发 SIP UPDATE"| UE1
P-CSCF 在收到 INVITE/183 携带的 SDP 后,并不只是简单前转,它要执行一项关键的策略触发动作:
m= 行和 c= 行提取媒体类型(audio/video)、IP 五元组(源/目的 IP、端口)、编解码、带宽(b=AS/RS/RR)。Media-Component-Description AVP,把媒体组件、Flow-Status、请求的 QoS(5QI=1、ARP、GBR/MBR)提交给 PCF。PDU Session Modification Command 中相关 QoS rule 状态变更为 active),UE-A 判定本地资源预留完成,于是主动构造并发送 SIP UPDATE,把 curr:qos local 翻成 sendrecv。这条耦合链路解释了一个极其重要的工程事实:SIP UPDATE 的发送时机,完全由 5G 无线专用承载的建立速度决定。在无线条件差、gNB 准入失败或 PCF 授权延迟的场景下,UPDATE 会被显著推迟,甚至触发预条件超时导致呼叫失败。
| 参数 | 取值 | 说明 |
|---|---|---|
| 标准化 5QI | 1 | 会话类语音(Conversational Voice) |
| 资源类型 | GBR | 保证比特率,需准入控制 |
| 优先级(Priority Level) | 20 | 较高优先级 |
| PDB(包延迟预算) | 100 ms | 端到端时延预算 |
| PER(包错误率) | 10⁻² | 语音可容忍 1% 丢包 |
| 默认平均窗口 | 2000 ms | GBR 测量窗口 |
| 典型 GBR | 约 5.9 kbps (AMR-WB) / 9.6~24.4 kbps (EVS) | 取决于协商的 EVS 模式 |
在抓包分析 VoNR 呼叫时,可以用如下显示过滤器快速定位关键消息:
sip.Method == "INVITE" — 定位主叫发起sip.Status-Code == 183 — 定位带 SDP Answer 的 Session Progresssip.Method == "UPDATE" — 定位预条件完成的标志消息sip.Status-Code == 180 — 定位振铃sdp.media.type == "audio" 且 sdp.attribute == "curr" — 查看 curr/des/conf 行一个健康的 VoNR 主叫,在 INVITE 与 180 Ringing 之间必然存在一次 UPDATE 与 200(UPDATE) 交互。如果抓包中 INVITE 之后直接出现 180 Ringing 而没有任何 UPDATE,基本可以判定预条件机制未启用(这在标准 VoNR 终端上属于异常)。
| 故障现象 | 可能根因 | 排错切入点 |
|---|---|---|
| UPDATE 迟迟不发,呼叫卡在 183 | UE-A 专用承载未建立(PCF/SMF/N2 失败) | 查 Rx AAR 是否成功、N7 PCC Rule 是否下发、N2 是否失败(如 gNB 准入拒绝) |
| 183 后被叫直接 180,无 UPDATE | 预条件 capability 协商失败,UE 未启用 mandatory | 检查 Supported/Require 头域是否含 precondition;检查 IMS 注册时的协商参数 |
| 被叫 180 Ringing 未前转给主叫 | 早期媒体(Early Media)与 P-Early-Media 策略阻断 | 检查 P-CSCF 的 P-Early-Media 处理、180 是否被 PRACK 之外的策略拦截 |
| 双方 UPDATE 都发了但呼叫失败 | 预条件状态机未收敛(curr 与 des 方向不匹配) | 逐条比对双方 SDP 的 curr/des 方向标签,常见为 send/recv 方向写反 |
| 媒体单向通 | 仅一方向 des mandatory,另一方向 optional | 检查 offer/answer 中双方 des 方向是否对称为 sendrecv |
Q1:预条件机制(precondition)和 100rel(可靠临时响应)是一回事吗?
A:不是。precondition(RFC 3312)解决的是"资源预留与媒体通路的同步"问题;100rel(RFC 3262,可靠传送 1xx 临时响应)解决的是"183 Session Progress 必须被可靠确认"的问题。两者在 VoNR 中必须同时启用:预条件机制依赖 183 携带 SDP Answer,而 183 的可靠传送又依赖 100rel(通过 PRACK 确认)。两者的交集体现在 Supported/Require 头域中同时出现 precondition 与 100rel。
Q2:主叫和被叫都必须支持预条件吗?有一方不支持怎么办?
A:是的,标准 VoNR 主被叫都应支持预条件(NG.114 强制要求)。在 offer/answer 协商时,若一方在 INVITE 中 Require: precondition 而另一方不支持,会直接返回 420 Bad Extension 拒绝。若双方都未声明 mandatory,则降级为"无预条件"呼叫——这在 5G VoNR 中属异常配置,应避免。
Q3:UPDATE 消息在 RFC 3311 和预条件中扮演什么角色?
A:UPDATE(RFC 3311)用于在 INVITE 尚未最终确认(200 OK/ACK 之前)阶段更新会话参数。在预条件机制中,UPDATE 的唯一职责是携带更新后的 SDP,通告 curr:qos 的状态翻转。它和 PRACK 不同:PRACK 确认 183,UPDATE 通告资源状态,两者在流程中先后出现、各司其职。
Q4:为什么是 UE 主动发 UPDATE,而不是网络发?
A:因为"本地资源预留完成"这个事件,只有 UE 自己能最准确地感知——5G 中 UE 通过 NAS PDU Session Modification Command 确认 5QI=1 QoS Flow 激活,网络侧(P-CSCF/SMF)并不直接驱动 SIP 层。这种设计保证了 SIP 层状态机与 UE 承载状态的一致性,也符合端到端协商原则。
Q5:VoNR 的预条件和 VoLTE 有本质区别吗?
A:机制层面完全一致,都基于 RFC 3312/4032。差异仅在承载层:VoLTE 触发的是 EPC 的专用 EPS Bearer(QCI=1)建立(通过 P-CSCF→PCRF 的 Gx/Rx);VoNR 触发的是 5GS 的专用 QoS Flow(5QI=1)建立(通过 P-CSCF→PCF 的 N5 + N7)。SDP 层的 curr/des/conf 状态机、UPDATE 收敛逻辑完全相同,这是 3GPP 有意保持的 IMS 控制面与承载面解耦的延续。
本文由「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 等场景全覆盖。
