在普通互联网SIP通话(如基于WebRTC或软交换的VoIP)中,主叫UE发出INVITE、被叫返回200 OK、双方ACK之后,媒体RTP流就可以立即在RTP端口上双向流动。这套逻辑在"尽力而为"的IP网络里是成立的——因为底层不保证带宽,丢了重传即可。
但IMS语音(VoLTE/VoNR)完全不是这个玩法。3GPP对运营商IMS语音的硬性要求是:在媒体流真正发送之前,端到端的承载资源(无线RB + 传输 + 核心网GTP-U/N3隧道)必须已经完成预留/激活,并且QoS参数满足会话需求。否则会出现两类灾难性故障:
为了让SIP信令层与底层承载建链过程严格协调、互相同步,3GPP/IETF引入了Precondition(前提条件)框架,核心定义在 RFC 3312 "Integration of Resource Management and Session Initiation Protocol (SIP)",并由 RFC 4032 修订、RFC 5027 补充。3GPP在 TS 24.229(IMS呼叫控制协议)和 TS 23.228(IMS Stage 2)中将其纳入IMS规范,强制VoLTE/VoNR的会话建立必须遵循该机制。
理解Precondition,是理解整个VoNR/VoLTE呼叫建立的"灵魂"——它解释了为什么一个语音呼叫的SIP信令多达十几条消息、为什么必须用183而不是直接180、为什么必须有PRACK和UPDATE、为什么P-CSCF要同时盯着信令和承载。本文聚焦该机制,逐步拆解每一个IE和每一条信令的来龙去脉。
Precondition的本质,是在SDP offer/answer模型中额外携带一类"状态属性",把QoS资源的当前状态和目标状态显式表达出来,让通信双方通过多次SDP交换,逐步把"资源未就绪"推进到"资源已就绪",并在最后一刻才触发振铃。
它的设计哲学可以用一句话概括:信令层的会话状态机与承载层的资源状态机通过SDP属性"握手同步"。这与5G控制面其它地方"信令先走、承载后建"的松耦合完全相反——在IMS语音里,二者是强耦合的。
RFC 3312定义了三个媒体级(media-level)SDP属性,它们都挂在 m= 行下面:
a=curr:<precondition-type>:<status-type> <direction-tag>
a=des:<precondition-type> <strength-tag> <status-type> <direction-tag>
a=conf:<precondition-type>:<status-type> <direction-tag>
下面这张表把三个属性的含义拆开:
| 属性 | 全称 | 作用 | 典型取值 |
|---|---|---|---|
a=curr |
Current Status | 报告当前该方向资源是否已就绪 | a=curr:qos local none(本地未就绪)、a=curr:qos remote sendrecv(对端双向就绪) |
a=des |
Desired/Confirm Status | 声明期望达到的目标状态,并标注强度 | a=des:qos mandatory local sendrecv(本地双向,强制) |
a=conf |
Confirmation | 请求对端在满足某方向precondition后主动回送确认 | a=conf:qos remote sendrecv |
其中两个关键标签:
none / optional / mandatory。mandatory是VoNR/VoLTE的默认配置——表示在precondition被满足之前,接收方绝不能开始发送或接收该方向的媒体,并且绝不能向用户振铃。这正是阻止幽灵振铃的"闸门"。none / send / recv / sendrecv,分别表示发送方向、接收方向、双向。status-type进一步区分local(本端接入网资源)和remote(远端接入网资源),从而把"我的无线资源"和"对方的无线资源"分别跟踪——因为两端建承载的速度不同,必须独立追踪。
3GPP在TS 23.228 Clause 5.6.x中规定,对于支持本地资源预留的IMS终端,语音会话必须使用mandatory preconditions。原因有二:
第一,只有mandatory才能强制双方在媒体面真正互通前完成资源确认,避免"信令通了但承载没通"。
第二,mandatory语义为后续的UPDATE消息提供了"再次协商"的合法理由——RFC 3311(UPDATE方法)允许在早期对话内修改会话参数,但SIP限制早期对话内re-INVITE。Precondition机制正好用UPDATE把"资源就绪"这个状态变化注入到会话中。
下面是一通典型的VoNR MO(Mobile Originating)→ MT(Mobile Terminating)呼叫,完整呈现Precondition从offer到全部满足的全过程:
sequenceDiagram
autonumber
participant A as UE-A(主叫)
participant PA as P-CSCF-A
participant SA as S-CSCF-A
participant SB as S-CSCF-B
participant PB as P-CSCF-B
participant B as UE-B(被叫)
Note over A,B: ① 资源未就绪,发起呼叫
A->>PA: INVITE(SDP Offer, curr=none, des=mandatory, conf=remote)
PA->>SA: INVITE
SA->>SB: INVITE
SB->>PB: INVITE
PB->>B: INVITE
Note over A,B: ② 被叫应答SDP,触发双向资源预留
B->>PB: 183 Session Progress(SDP Answer, 选定EVS, curr=none)
PB->>SB: 183
SB->>SA: 183
SA->>PA: 183
PA->>A: 183(可靠传送,Require:100rel)
Note over A,B: ③ 确认183(RFC 3262可靠临时响应)
A->>PA: PRACK
PA->>B: PRACK(逐跳转发)
B->>A: 200 OK(PRACK)
Note over PA,PB: ④ P-CSCF通过Rx/N5向PCF授权承载
PA->>PA: Rx AAR授权(5QI=1,GBR)→触发专用QoS流
PB->>PB: Rx AAR授权→触发被叫专用QoS流
Note over A,B: ⑤ A端资源就绪,UPDATE更新curr状态
A->>PA: UPDATE(SDP Offer, curr local=sendrecv)
PA->>B: UPDATE
B->>A: 200 OK(UPDATE,SDP Answer,curr remote=sendrecv)
Note over A,B: ⑥ 所有mandatory precondition满足→振铃
B->>A: 180 Ringing(可靠)
A->>B: PRACK
B->>A: 200 OK(PRACK)
Note over A,B: ⑦ 被叫摘机
B->>A: 200 OK(INVITE)
A->>B: ACK
Note over A,B: ⑧ 双向RTP(承载已全部就绪)
这条时序里有几个看似"多余"的消息,每一个都直接服务于Precondition机制。下面逐步拆解关键IE。
主叫UE-A在INVITE里携带SDP Offer,关键是 m= 行下方的一组precondition属性。一个真实的VoNR INVITE SDP片段:
m=audio 50000 RTP/AVP 96 97 98
a=rtpmap:96 EVS/16000/1
a=fmtp:96 br=5.9-24.4; bw=nb-wb; dtx=yes
a=rtpmap:97 AMR-WB/16000/1
a=rtpmap:98 telephone-event/8000
a=curr:qos local none
a=curr:qos remote none
a=des:qos mandatory local sendrecv
a=des:qos mandatory remote sendrecv
a=conf:qos remote sendrecv
解读这组属性的语义:"我现在(curr)本地和对端的QoS都没就绪;我希望(des)本地和对端都达到双向强制(mandatory sendrecv)状态;同时请你(conf)在对端QoS就绪后告诉我。"
a=rtpmap:96 EVS/16000/1 表明优先选择EVS(Enhanced Voice Services,TS 26.441定义的VoNR主选编解码,带宽窄带到超宽带,码率可变)。fmtp参数里的 br=5.9-24.4 是EVS的自适应码率范围,这是VoNR相比VoLTE(固定AMR-WB 23.85kbps)的关键语音质量提升点。
被叫UE-B收到INVITE后,从Offer的codec列表中选定一个(通常也是EVS),返回带SDP Answer的183。此时UE-B的SDP同样标注 curr=none,因为它此刻也没建承载。
为什么是183而不是直接180 Ringing?因为180 Ringing的语义是"我正在向用户振铃",而Precondition机制要求振铃前所有mandatory precondition必须满足——此刻资源还没就绪,绝不能振铃。所以必须用一个非振铃的临时响应(183 Session Progress)先把SDP Answer送回去,把"应该建什么QoS的承载"这件事告诉主叫。
为什么183必须可靠传输(Require: 100rel,RFC 3262)?因为后续的UPDATE要依赖"主叫已经收到183的SDP Answer"这一事实来建立对话状态。临时响应默认不可靠(可能丢),必须用PRACK确认。RFC 3262正是为此引入了100rel扩展和PRACK机制。一个细节:PRACK里可以再次携带SDP offer(用于某些复杂场景),但VoNR标准流程中PRACK一般不带SDP。
当UE-A侧的专用QoS流(5QI=1承载)建立完成,UE-A需要通知UE-B"我的local资源好了"。但早期对话(early dialog)里不允许用re-INVITE。RFC 3311定义的UPDATE方法正是为此而生——它可以在对话建立前修改会话参数。UE-A发送UPDATE,携带新的SDP Offer,把 a=curr:qos local sendrecv 标注上:
a=curr:qos local sendrecv ← 本地已就绪
a=curr:qos remote none ← 对端还没就绪
a=des:qos mandatory local sendrecv
a=des:qos mandatory remote sendrecv
UE-B收到UPDATE后,发现远端的local(即B的remote)已经满足,自己这边资源也建好了,于是回200 OK(UPDATE)时把 a=curr:qos remote sendrecv 也标注上。当所有 a=des 中声明的mandatory方向都达到对应的 a=curr 状态时,Precondition全部满足——此刻UE-B才被允许向用户振铃,发出180 Ringing。
下面这张状态图刻画了Precondition从"未满足"到"全部满足"的推进过程:
stateDiagram-v2
[*] --> OfferSent: 发送INVITE(含des mandatory)
OfferSent --> AnswerRecv: 收到183 SDP Answer
AnswerRecv --> Reserving: PRACK确认,启动资源预留
Reserving --> LocalReady: 本端专用QoS流就绪
LocalReady --> UpdateSent: 发UPDATE(curr local=sendrecv)
UpdateSent --> RemoteReady: 收200OK(curr remote=sendrecv)
RemoteReady --> AllSatisfied: 本地+远端均满足
AllSatisfied --> Ringing: 允许180振铃
Ringing --> [*]: 200 OK+ACK,媒体激活
note right of Reserving
P-CSCF经Rx/N5向PCF授权
触发5QI=1专用承载
end note
note right of AllSatisfied
所有mandatory precondition达成
这是振铃的唯一触发点
end note
整个Precondition机制能够生效,离不开一个关键网元——P-CSCF。它在VoNR里同时扮演两个角色:
当P-CSCF在INVITE/183的SIP消息体里看到SDP,它会提取媒体信息(codec、码率、方向),翻译成PCC参数,经Rx的AAR(AA-Request)发给PCF:
| Rx AAR关键AVP | 来源 | 在VoNR语音中的取值 |
|---|---|---|
| Media-Component-Description | SDP的 m= 行 |
1个音频媒体组件 |
| Media-Type | SDP | AUDIO |
| Flow-Status | SDP方向 | ENABLED-UPLINK/DOWNLOAD(双向) |
| Flow-Usage | 固定 | RTCP / RTP |
| Max-Requested-Bandwidth-UL/DL | SDP b= 或codec码率 |
EVS约24.4kbps + IP/RTP/UDP头开销,约取值36-64kbps |
| AF-Application-Identifier | 预配置 | IMS语音业务标识 |
| Service-Info-Status | 呼叫阶段 | PRELIMINARY_SERVICE(早期)/FINAL(最终) |
PCF收到AAR后执行Rx Authorization(TS 29.513 Clause 4.2),把请求的QoS映射为5G的5QI值,对VoNR语音统一映射为 5QI=1(来自TS 23.501 Table 5.7.4-1标准化5QI表),再通过 Npcf_SMPolicyControl(N7接口)或 Npcf_PolicyAuthorization 服务通知SMF,触发一条专用QoS流(dedicated QoS Flow)建立在UE已存在的IMS PDN/PDU会话之上。
5QI=1 的标准化参数(TS 23.501):
| 参数 | 取值 | 含义 |
|---|---|---|
| 5QI | 1 | 标准化QoS标识,无需信令协商完整参数 |
| Resource Type | GBR | 保证比特率,专用资源 |
| Default Priority Level | 2 | 调度优先级 |
| Packet Delay Budget | 100 ms | 端到端时延预算 |
| Packet Error Rate | 10⁻² | 可接受丢包率 |
| Default Max Data Burst Volume | 1500 bytes |
P-CSCF在183阶段发的AAR会带 Service-Info-Status=PRELIMINARY_SERVICE,PCF据此先建立一条初步授权的承载(允许资源预留但不计费/或低优先级);在200 OK阶段发的AAR带 FINAL,PCF把承载转为最终状态并开始正常计费。这种两阶段授权与Precondition的"预留→确认"语义完美对应——又是一个信令与策略的协调点。
下图刻画了P-CSCF如何把SDP翻译成承载授权的完整链路:
flowchart TD
subgraph 信令面["SIP信令面"]
A1[INVITE/183 SDP] --> A2[P-CSCF 解析SDP]
end
subgraph 策略面["PCC策略面"]
A2 -->|Rx AAR<br/>Media-Component| PCF
PCF -->|5QI=1映射| PCF2[策略决策]
PCF2 -->|Npcf_SMPolicyControl<br/>N7| SMF
end
subgraph 用户面["用户面承载"]
SMF -->|N4 PFCP| UPF
SMF -->|N2 PDU Session<br/>Resource Setup| NG_RAN[(gNB)]
NG_RAN -->|RRC Reconfig<br/>建立DRB| UE[(UE)]
UPF <-->|N3 GTP-U| NG_RAN
end
UE -.->|承载就绪,反馈 curr=sendrecv| A1
style PCF fill:#e1f5ff,stroke:#0288d1
style SMF fill:#fff4e1,stroke:#f57c00
注意最后一个虚线箭头——UE感知到专用承载(DRB)建好,会在SIP层发起UPDATE,把 a=curr 状态推到sendrecv。这就是承载层状态反过来驱动信令层状态机的闭环,也是Precondition机制"双向同步"的精髓。
用Wireshark(或TShark,配合pcap-analyzer)打开VoNR呼叫抓包,过滤SIP消息后,按以下特征定位Precondition流程:
Content-Type: application/sdp,展开SDP,能在 m=audio 下找到 a=des:qos mandatory ——确认这是一条强制Precondition的语音会话。Require: 100rel——确认走的是可靠临时响应。Media-Type=AUDIO。a=curr 从 none 变成 sendrecv——这是Precondition满足的指纹。| 故障现象 | 可能根因 | 排错思路 |
|---|---|---|
| 被叫振铃后接听无声/单向 | UPDATE未发出或对端未收到,a=curr remote 一直为none,但用户已振铃(说明对端强制逻辑被旁路) |
抓包确认UPDATE/200OK是否完整;检查被叫UE是否真按mandatory行事 |
| 183后无PRACK,呼叫挂断 | RFC 3262可靠性协商失败,或中间CSCF不支持100rel透传 | 检查Require/Supported头部透传;核对P/S-CSCF配置 |
| 呼叫建立极慢(>3秒) | 专用QoS流建立慢,UPDATE迟迟不发;或P-CSCF AAR与PCF交互慢 | 看Rx/N5时延;确认5QI=1专用QoS流是否在200ms级建立 |
| 一直停在183,永远不到180 | 承载建立失败(NG-RAN拒绝、UE不支持该QoS、N4下发失败),Precondition无法满足 | 检查N2/N4日志;确认UE与gNB协商的5QI能力 |
| 主被叫Codec不一致导致 renegotiation失败 | SDP Answer未正确选定EVS,或fmtp参数互不支持 | 对比Offer/Answer的rtpmap和fmtp |
| ## 六、SDP Offer/Answer中Precondition属性组合速查 |
下表把VoNR呼叫中几个关键节点的 a=curr / a=des 组合列出来,便于抓包对照:
| 节点 | local curr | remote curr | local des | remote des | 含义 |
|---|---|---|---|---|---|
| INVITE Offer | none | none | mandatory sendrecv | mandatory sendrecv | 起点状态,期望双向强制 |
| 183 Answer | none | none | mandatory sendrecv | mandatory sendrecv | 双方确认目标,仍未就绪 |
| UPDATE(A发) | sendrecv | none | mandatory sendrecv | mandatory sendrecv | A本地就绪,等B |
| 200OK(UPDATE) | sendrecv | sendrecv | mandatory sendrecv | mandatory sendrecv | 双向全部就绪→可振铃 |
Q1: Precondition和PCC的Service-Info-Status(PRELIMINARY/FINAL)是什么关系?
A: 二者是同一资源预留过程在信令层和策略层的两套表达。Precondition用SDP的curr/des描述"资源是否就绪",是SIP信令层的语义;Service-Info-Status用AAR AVP告诉PCF"这是预授权还是最终授权",是PCC策略层的语义。它们围绕同一个事件——专用承载的预留→激活——分别驱动。PRELIMINARY对应"预留",FINAL对应Precondition全部满足后的"激活/确认"。
Q2: 为什么VoNR语音用5QI=1,不用默认QoS流承载RTP?
A: 默认QoS流(通常5QI=5或9)是非GBR的、尽力而为的,无法保证VoNR的100ms时延和低丢包。5QI=1是GBR类型,会预留专用无线资源(DRB)和传输资源,并赋予高调度优先级(Priority Level 2),这才是运营商级语音质量的保障。P-CSCF通过Rx/N5把SDP语音流精确映射到5QI=1,是Precondition能成立的前提。
Q3: 如果终端不支持Precondition(如某些VoWiFi),呼叫还能建立吗?
A: 可以,但需运营商允许降级。此时 a=des 用optional或none,双方收到200 OK就直接发媒体,承载在媒体激活时由网络按默认规则尽力建立。代价是可能出现前述的幽灵振铃和单向通话,且语音质量无保证,故运营商IMS语音规范(GSMA IR.92/IR.94)要求终端必须支持mandatory precondition。
Q4: UPDATE和re-INVITE在Precondition里都能用吗?
A: 标准流程用UPDATE(RFC 3311),因为它专门用于早期对话(early dialog)内的会话参数修改,正好在200 OK到来之前承载就绪。re-INVITE只能在已确认对话(200 OK之后)内使用,时间窗对不上。Precondition的"资源就绪通知"几乎总是落在early dialog阶段,所以UPDATE是唯一正确选择。
Q5: PRACK里为什么有时也带SDP?
A: 在RFC 3312的某些复杂场景(如多轮precondition协商或被叫需要在确认183时再调整codec),PRACK可携带SDP offer做补充协商。但VoNR标准MO/MT流程中,PRACK一般不带SDP,避免与UPDATE的offer冲突。若抓包看到PRACK带SDP,多见于互通网关或特殊终端,需结合上下文判断。
本文由「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 等场景全覆盖。
