在传统CS(电路交换)语音里,主叫拿起电话拨号,网络通过一套七号信令(ISUP IAM/ACM/ANM)就能完成接续,整个过程对主叫而言几乎是"透明的"——你拨完号,等着振铃就行。但在IMS/VoLTE架构下,一次主叫会话建立(Mobile Originated Call)却要在Gm、Mw、Mg、Mi等多条参考点上交互多达十余条SIP信令,其中还穿插着专用承载建立、SDP媒体协商、Precondition资源预留确认等动作。
这套看似"啰嗦"的流程,根本动机在于:IMS承载在IP之上,IP网络的"尽力而为"特性与语音这种实时、时延敏感业务之间存在天然矛盾。如果在被叫真正振铃之前,端到端的QoS资源(无线专用承载、传输带宽)尚未就绪,就会出现"接通了却听不到声音"或"前几秒话音断裂"的糟糕体验。为彻底根治这一问题,3GPP在TS 23.228的会话建立流程中引入了基于RFC 3312的Precondition(前置条件)机制,把"资源预留"这一动作强制嵌入SIP信令序列,确保振铃(180 Ringing)发生时双向媒体路径必然可用。
本文聚焦TS 23.228第5.4节"Originating call procedures"与TS 24.229(SIP/SDP Stage 3)的具体信令机制,逐条拆解一次完整IMS主叫会话建立的18步信令,并深入剖析Precondition框架如何在SIP事务状态机中驱动资源预留的时序。
在拆解信令之前,先锁定INVITE从主叫UE出发后所经过的IMS核心网实体及参考点:
| 参考点 | 连接实体 | 在主叫路径中的职责 |
|---|---|---|
| Gm | UE ↔ P-CSCF | UE所有SIP信令的第一跳/最后一跳,P-CSCF在此压缩/安全保护信令 |
| Mw | P-CSCF ↔ S-CSCF(主叫侧) | 主叫侧CSCF间路由 |
| Mg | I-CSCF ↔ S-CSCF(被叫侧) | 入局到被叫归属网络的入口 |
| Mi | S-CSCF ↔ BGCF | 当被叫为CS/PSTN号码时,路由到BGCF选择MGCF |
| Mj | BGCF ↔ MGCF | 选中 breakout 点后的最后一段 |
| ISC | S-CSCF ↔ AS | 基于iFC(初始过滤准则)触发业务逻辑(如号码变换、彩铃) |
| Rx | P-CSCF ↔ PCRF | 会话级QoS授权,驱动专用承载建立(VoLTE关键接口) |
主叫侧路径典型为:UE-A → P-CSCF → S-CSCF(A) → [I-CSCF] → S-CSCF(B) → P-CSCF → UE-B。其中S-CSCF在转发INVITE前会评估iFC,决定是否串接AS;P-CSCF在收到带SDP的响应后,会通过Rx接口向PCRF发起鉴权与授权请求(AAR命令),触发EPC/5GC建立QCI=1(5QI=1)的GBR专用承载。
下面是一次标准VoLTE主叫会话建立(带Precondition、双向资源预留)的完整时序。为清晰起见,省略了部分可选的100 Trying与AS交互细节,聚焦核心18步:
sequenceDiagram
autonumber
participant UEa as UE-A (主叫)
participant Pa as P-CSCF-A
participant Sa as S-CSCF-A
participant PCRF as PCRF/PCF
participant Sb as S-CSCF-B
participant Pb as P-CSCF-B
participant UEb as UE-B (被叫)
UEa->>Pa: 1. INVITE (SDP offer, curr=none, des=sendrecv)
Pa->>Sa: 2. INVITE (插入Route/Record-Route, P-Asserted-Identity)
Sa->>Sb: 3. INVITE (经iFC评估, AS可选触发)
Sb->>Pb: 4. INVITE
Pb->>UEb: 5. INVITE
UEb-->>Pb: 6. 183 Session Progress (SDP answer, curr=none, des=sendrecv)
Pb-->>Sb: 7. 183
Sb-->>Sa: 8. 183
Sa-->>Pa: 9. 183
Pa-->>UEa: 10. 183 (要求可靠传输, Require:100rel)
Note over Pa,PCRF: P-CSCF通过Rx(AAR)向PCRF请求QoS授权,触发双向专用承载
UEa->>Pa: 11. PRACK (确认183)
Pa->>UEa: 12. 200 OK (PRACK)
Note over UEa,UEb: 双向专用承载(QCI=1)建立完成,资源预留就绪
UEa->>Pa: 13. UPDATE (curr=sendrecv, 本地资源已满足)
Pa->>UEb: 14. UPDATE (逐跳转发)
UEb-->>UEa: 15. 200 OK (UPDATE, curr=sendrecv, 双向满足)
UEb-->>UEa: 16. 180 Ringing (开始振铃, 媒体路径已就绪)
UEb-->>UEa: 17. 200 OK (INVITE) (被叫摘机)
UEa->>UEb: 18. ACK (会话正式建立, 双向媒体流启动)
这张图的核心"骨架"是:INVITE/183完成SDP能力协商,PRACK锁定协商结果,UPDATE确认资源就绪,最后才允许180/200 OK让会话进入振铃与通话态。这种"协商→确认→资源→振铃"的串行化,正是Precondition机制的精髓。
UE-A发起的INVITE是最复杂的一条消息。其SIP头域与SDP体必须同时满足路由、鉴权标识、媒体能力声明三重目的。关键字段如下:
graph LR
A[INVITE消息] --> B[SIP头域]
A --> C[SDP Body Offer]
B --> B1[Request-URI: 被叫号码tel/sip]
B --> B2[P-Preferred-Identity: 主叫IMPU]
B --> B3[Route: 来自注册的Service-Route]
B --> B4[Require: precondition, 100rel]
B --> B5[Supported: 100rel, precondition]
C --> C1[m=audio 端口 RTP/AVP]
C --> C2[a=rtpmap: AMR-WB/EVS payload]
C --> C3[a=curr:qos local none]
C --> C4[a=curr:qos remote none]
C --> C5[a=des:qos mandatory local sendrecv]
C --> C6[a=des:qos mandatory remote sendrecv]
B1 -.触发iFC业务.- D[AS: 号码补全/彩铃]
B4 -.驱动后续时序.- E[PRACK与UPDATE强制]
几个IE的设计意图值得专门说明:
Require: precondition, 100rel:这是整条流程的"总开关"。100rel(RFC 3262)要求对方对1xx临时响应进行可靠传输(即必须用PRACK确认);precondition则要求对方必须理解并参与precondition协商。若被叫不支持,应返回420 Bad Extension,主叫据此决定是否降级。GSMA IR.92 VoLTE profile强制要求终端实现这两个扩展。
a=curr:qos local none / a=curr:qos remote none:声明当前本地和远端的QoS资源状态均为"none"(未预留)。这是precondition协商的"起点状态"。
a=des:qos mandatory local sendrecv / remote sendrecv:声明期望的QoS是mandatory(强制)的,方向为sendrecv(双向收发)。mandatory意味着:在该precondition满足之前,会话不得进入"振铃→通话"阶段。这就是把振铃动作"卡住"直到资源就绪的法理依据。
a=rtpmap中的编解码:VoLTE默认AMR-WB 8.85/12.65kbps或EVS(5G VoNR场景),这是后续专用承载码率授权的依据。
INVITE经P-CSCF→S-CSCF-A时,P-CSCF会做几件关键操作:①保存Record-Route以建立后续事务路径;②从P-Preferred-Identity提取并验证主叫身份,转换为P-Asserted-Identity;③插入P-Charging-Vector(含ICID、IOI)用于计费关联。S-CSCF收到后,先评估iFC:解析INVITE中的方法、SDP、被叫URI等触发点(Trigger Point),匹配到对应AS则通过ISC接口前转给AS执行业务(如把tel:13800138000补全为+8613800138000),AS返回后再继续向被叫侧路由。
被叫侧S-CSCF-B通过DNS ENUM查询或本地配置定位被叫P-CSCF,最终INVITE送达UE-B。每一跳都可能在消息中追加自己的Record-Route,为后续的in-dialog请求(如UPDATE、ACK、BYE)建立反向路由表。
UE-B收到INVITE后,不立即振铃,而是先回应183 Session Progress,其中携带SDP Answer。这是SDP Offer/Answer模型(RFC 3264)的应答阶段:被叫从主叫提供的编解码列表中选出自己支持的那一组(如选定AMR-WB 12.65),并在183的SDP中回填选定的payload type。同时,被叫在183中也声明a=curr:qos ... none和a=des:qos mandatory sendrecv,与主叫"对齐"precondition期望。
由于INVITE中带了Require: 100rel,这条183是可靠传输的临时响应,必须由主叫用PRACK确认,否则P-CSCF会周期性重传183。这一点至关重要——它保证了"能力协商结果不会因UDP丢包而丢失"。
UE-A收到183后立即回送PRACK(Provisional Response ACK),其中携带183响应的RSeq值作为RAck。这完成了对183的可靠确认。被叫侧回200 OK (PRACK)。此后,双方的编解码、端口、precondition期望值已正式锁定,后续基于in-dialog的UPDATE可以修改这些状态。
这是Precondition机制最关键的三步。在PRACK之后到振铃之前的窗口期内,网络侧(通过P-CSCF的Rx接口向PCRF发起AAR)正在为主叫和被叫分别建立QCI=1的GBR专用承载。当主叫侧专用承载建立完成,意味着主叫本地QoS资源已满足,于是UE-A发送UPDATE消息:
UPDATE sip:... SIP/2.0
Content-Type: application/sdp
...
a=curr:qos local sendrecv ; 本地资源已满足(从none升级为sendrecv)
a=curr:qos remote none ; 远端尚未确认
a=des:qos mandatory local sendrecv
a=des:qos mandatory remote sendrecv
UPDATE逐跳转发到UE-B。当被叫侧专用承载也建立完成,UE-B确认双向资源均已就绪后,回送200 OK (UPDATE),其中a=curr:qos remote sendrecv也升级为sendrecv。至此,主叫收到的200 OK(UPDATE)中,本地和远端的curr都变成sendrecv,所有mandatory precondition全部满足——这正是触发"可以振铃了"的信号。
设计UPDATE而非复用INVITE的精妙之处在于:UPDATE是一个in-dialog的target-refresh请求(RFC 3311),它在不重新发起整个会话邀请的前提下,独立完成precondition状态的增量更新,既保持了会话上下文,又避免了重协商整套SDP的冗余。
Precondition满足后,UE-B才发送180 Ringing开始物理振铃。注意:此刻媒体路径(专用承载)已完全就绪,只是还没有RTP媒体流——因为用户尚未摘机。当被叫用户摘机接听,UE-B发送200 OK (INVITE)作为对最初INVITE事务的最终响应,主叫UE-A回送ACK完成三次握手。ACK之后,双向RTP/RTCP媒体流正式启动,通话正式开始。
从协议状态机角度,整条流程可抽象为三个状态跃迁阶段,precondition的"满足/未满足"是跃迁的守卫条件:
stateDiagram-v2
[*] --> OfferSent: 发送INVITE(SDP offer, curr=none)
OfferSent --> Negotiated: 收到183+PRACK完成<br/>(能力锁定, 资源未就绪)
Negotiated --> ResourcesReserved: 收到200OK(UPDATE)<br/>(local+remote curr=sendrecv)
note right of ResourcesReserved
所有mandatory precondition满足
此前禁止进入振铃态
end note
ResourcesReserved --> Alerting: 180 Ringing (振铃)
Alerting --> Confirmed: 200OK(INVITE)+ACK
Confirmed --> [*]: 通话中 (RTP双向媒体)
这个状态机揭示了一个强约束:从Negotiated到ResourcesReserved的跃迁必须完成,才能进入Alerting。如果资源预留失败(如无线资源紧张、PCRF拒绝授权),会话会回退(主叫收到480/503等错误响应并释放),从而避免"假振铃"。
为更直观理解precondition相关SDP属性如何组织,下面是offer阶段的SDP属性逻辑结构:
graph TD
SDP[SDP媒体描述 m=audio] --> CURR[a=curr: 当前状态]
SDP --> DES[a=des: 期望状态]
SDP --> CONF[a=conf: 确认状态]
CURR --> C1[strength: none/e2e/local/remote]
CURR --> C2[direction: sendrecv/recvonly]
DES --> D1[strength: mandatory/optional]
DES --> D2[direction: sendrecv等]
DES --> D3[status-type: qos]
CONF --> CF1[向对端确认其des已满足]
style D1 fill:#ffd,stroke:#a00
其中:
- strength字段:mandatory是强制门槛(未满足不得振铃),optional是尽力满足。VoLTE默认两端都用mandatory。
- direction字段:单向资源预留时(如仅主叫侧先就绪),可用sendonly/recvonly精细表达。
- a=conf属性:用于向对端"确认"对端的des已被本端满足,是UPDATE协商中的握手信号。
| 维度 | 启用Precondition(VoLTE默认) | 不启用Precondition |
|---|---|---|
| 振铃时序 | 资源就绪后才振铃 | 收到INVITE即可振铃 |
| 接通时延 | 较长(多一轮UPDATE往返) | 较短 |
| 媒体连续性 | 摘机即可通话,无前断续 | 可能出现前1~2秒话音丢失 |
| 信令复杂度 | 高(含PRACK+UPDATE) | 低(仅INVITE/183/200/ACK) |
| 依赖扩展 | RFC 3312 + RFC 3262 + RFC 3311 | 仅基础SIP |
| 适用场景 | 运营商级VoLTE/VoNR语音 | 紧急呼叫降级、部分视频彩铃 |
| 失败处理 | 资源不足直接释放会话 | 振铃后媒体失败用户感知差 |
正因为这张表的取舍,GSMA IR.92与3GPP TS 23.228均强烈建议VoLTE终端默认启用precondition;仅在与不支持precondition的legacy终端互通、或IMS紧急呼叫等特殊场景下才降级关闭。
在Wireshark中识别一次IMS主叫会话建立,可按以下步骤:
sip 协议过滤,或更精确 sip.Method == "INVITE" || sip.Method == "PRACK" || sip.Method == "UPDATE"。sip.Call-ID 字段把同一通电话的所有SIP消息归并到一个call group(Wireshark的Telephony→SIP Flows可自动聚合)。INVITE → 183 → PRACK → 200(PRACK) → UPDATE → 200(UPDATE) → 180 → 200(INVITE) → ACK 这条消息链。如果发现"180 Ringing直接跟在INVITE后面、中间没有UPDATE",则说明本次通话未启用precondition或被叫是CS终端(经MGCF)。a=curr:qos 的 strength 是否从 none 跃迁到 sendrecv——这是判定资源预留是否成功的金标准。Create Bearer Request(QCI=1)及UE的 Activate Dedicated EPS Bearer Context Accept,证明无线侧专用承载确实建立。| 故障现象 | 可能根因 | 排错思路 |
|---|---|---|
| INVITE发出后无任何响应 | P-CSCF路由错误、iFC配置异常、S-CSCF未注册 | 查P-CSCF日志是否转发、S-CSCF是否有用户注册记录 |
| 卡在183、PRACK之后无UPDATE | 专用承载建立失败、PCRF Rx授权被拒、无线资源拥塞 | 查PCRF是否下发AAR响应、查eNB是否拒绝GBR承载、检查ARP/PLR参数 |
| 收到UPDATE但200(UPDATE)迟迟不来 | 被叫侧专用承载未建立、被叫终端precondition实现缺陷 | 抓被叫Gm口信令、查被叫P-CSCF的Rx流程 |
| 振铃后摘机无声音 | SDP端口协商错配、NAT导致RTP不通、编解码不匹配 | 比对INVITE/183的SDP端口与码流、检查RTP流是否双向 |
| 偶发"未振铃即失败" | mandatory precondition超时、资源预留定时器到点 | 查S-CSCF/P-CSCF的会话定时器配置,考虑降级为optional |
| ## 常见问题 |
Q1:Precondition机制和SIP的100rel(可靠临时响应)是同一个东西吗?
A:不是。100rel(RFC 3262)解决的是"临时响应(如183)可靠传输"的问题,即用PRACK确认183;而precondition(RFC 3312)解决的是"资源预留时序"的问题,用UPDATE同步QoS状态。但precondition依赖100rel——因为带precondition的183必须可靠传输才能保证协商不丢。两者协同才能撑起VoLTE的会话建立。
Q2:为什么用UPDATE而不是直接复用INVITE来更新precondition状态? A:因为INVITE已经处于"待响应"事务状态中,在一个事务未结束前不能再用INVITE刷新同一dialog。UPDATE(RFC 3311)是专门为"in-dialog目标刷新与SDP增量更新"设计的方法,它独立于INVITE事务,能干净地完成precondition状态的协商而不打乱原有事务状态机。
Q3:如果主被叫一方支持precondition另一方不支持,会怎样?
A:若被叫在INVITE的Require: precondition下返回420 Bad Extension或421 Extension Required,主叫可降级为不带precondition重发(前提是业务允许)。但实际VoLTE网络中,运营商通过终端入网认证确保IR.92一致性,互通问题更多发生在与CS/PSTN经MGCF的边界,此时MGCF会剥离precondition属性。
Q4:Precondition对呼叫建立时延有多大影响? A:相比无precondition流程,多了一轮PRACK往返和一轮UPDATE往返,典型增加150~400ms(取决于网络RTT与专用承载建立速度)。运营商通过优化P-CSCF-PCRF的Rx时延、预授权码率模板等方式压缩这部分时延,IR.92要求端到端建立时延控制在合理范围内。
Q5:IMS紧急呼叫也走Precondition吗? A:通常不走或降级。紧急呼叫(E-CSCF路由)优先保障接通率,TS 23.167规定紧急会话可不强制资源预留,被叫(PSAP)侧也可能不支持precondition,故主叫终端会以optional或不带precondition的方式发起,避免因协商失败而无法接通紧急呼叫。
本文由「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 等场景全覆盖。
