(注:以下为今日 ims 子域文章,已避开前序主题)
在固网VoIP里,INVITE发出、对端摘机、200 OK回来,媒体通就通了——这是一个"乐观"模型。但在移动网络里,这套模型会直接杀死语音质量:如果直到对端摘机才开始申请无线承载(Radio Bearer)和核心网专用QoS流,那么主叫用户在接通瞬间会听到严重的前向截断(clipping),因为承载建立需要数十到上百毫秒,而此时被叫已经开始说话了。
为此,3GPP在IMS(TS 23.228)与MTSI(TS 26.114)中强制引入了一套资源预留前置条件机制(Precondition),其核心契约是:
被叫UE在确认主叫侧已经为本次会话预留好足够的双向QoS资源之前,不得向用户振铃;主叫UE在被叫侧资源就绪之前,不得认为会话已成功建立。
这把"建立承载"从"接通后的事后补救"前置成了"振铃前的前置条件"。VoNR(Voice over NR)与VoLTE在SIP/IMS层面共用同一套Precondition框架(RFC 3312 + RFC 4032 + RFC 3311 UPDATE + RFC 3262 100rel),差异只在于底层承载从EPC的专有承载变成了5GC的专用QoS Flow(5QI=1)。本文聚焦3GPP R18 TS 23.228 §5.3.2.2a(发起方)/§5.3.1.2a(终结方)所定义的、带Precondition的完整主叫会话建立流程,逐信令拆解。
RFC 3312定义了一套用SDP属性描述资源状态的语法,3GPP在TS 24.229 §6.1.3与TS 26.114里对其做了约束(限定为qos类型、mandatory强度、必须sendrecv)。三个关键属性构成契约的三要素:
| SDP属性 | 含义 | 典型取值 |
|---|---|---|
a=des:qos |
期望状态(Desired)——本方要求最终达到的资源水平 | local/remote × mandatory × send/recv/sendrecv |
a=cur:qos |
当前状态(Current)——此刻资源实际是否就绪 | none 或 sendrecv(已预留) |
a=conf:qos |
确认请求(Confirmation)——请求对端在其remote侧就绪时通知我 | remote sendrecv |
其中local指"我到我的接入网关这段",remote指"对方到对方接入网关这段"。一次完整的VoNR呼叫,a=des基本恒为local mandatory sendrecv + remote mandatory sendrecv;变化的只是a=cur——它从none一步步演进到sendrecv。会话能否振铃,取决于双方cur是否都已满足des。
这就引出了Precondition机制最精妙的设计——会话需要两次SDP Offer/Answer交换:第一次协商编解码与QoS能力(约定des),第二次确认资源真的预留成功(更新cur)。
sequenceDiagram
autonumber
participant UEa as 主叫UE
participant PCSCFa as P-CSCF(主叫)
participant SCSCF as S-CSCF
participant ICSCF as I-CSCF
participant PCSCFb as P-CSCF(被叫)
participant UEb as 被叫UE
participant PCF as PCF(Rx)
participant SMF as SMF(N4)
Note over UEa,SMF: 第一阶段:SDP能力协商(约定 des 契约)
UEa->>PCSCFa: INVITE (SDP Offer#1)<br/>a=des:qos local/remote mandatory sendrecv<br/>a=cur:qos local none
PCSCFa->>PCF: Rx:AAR/授权(QoS=5QI1, GBR)
PCF->>SMF: Npcf_SMPolicyControl_Update
SMF->>PCSCFa: (专载建立中,并行)
PCSCFa->>SCSCF: INVITE (转发)
SCSCF->>ICSCF: INVITE
ICSCF->>PCSCFb: INVITE
PCSCFb->>UEb: INVITE
Note over UEa,UEb: 第二阶段:被叫回送183(第一次Answer)
UEb->>PCSCFb: 183 Session Progress (SDP Answer#1)<br/>Require:100rel, RSeq<br/>a=des:qos local/remote mandatory sendrecv<br/>a=cur:qos local none
PCSCFb->>PCF: Rx:AAR(触发被叫专载)
Note over UEb: 被叫UE本地资源预留完成
PCSCFb->>UEb: (专载建立回调)
Note over UEa: 主叫UE本地资源预留完成
UEa->>PCSCFa: PRACK (确认183可靠传输)
Note over UEa,UEb: 第三阶段:资源预留确认(第二次O/A,用UPDATE)
UEa->>PCSCFa: UPDATE (SDP Offer#2)<br/>a=cur:qos local sendrecv<br/>a=conf:qos remote sendrecv
PCSCFa->>PCSCFb: UPDATE (转发)
PCSCFb->>UEb: UPDATE
UEb->>PCSCFb: 200 OK(UPDATE) (SDP Answer#2)<br/>a=cur:qos local/remote sendrecv
PCSCFb->>PCSCFa: 200 OK(UPDATE)
PCSCFa->>UEa: 200 OK(UPDATE)
Note over UEa,UEb: 第四阶段:振铃→应答→确认
UEb->>UEa: 180 Ringing (双方cur均满足,开始振铃)
UEb->>UEa: 200 OK (INVITE)
UEa->>UEb: ACK
Note over UEa,UEb: 双向RTP语音媒体开始
这张图把"两次SDP交换 + 两段Rx/N4专载建立 + UPDATE确认"全部串起来了。下面逐条拆解每条消息里的关键IE。
这是会话的起点,也是契约的"要约"。关键字段:
INVITE sip:[email protected] SIP/2.0
Require: precondition, 100rel
Supported: 100rel, precondition, timer, replaces
P-Preferred-Identity: <sip:[email protected]>
P-Access-Network-Info: 3GPP-5G; utran-cell-id-3gpp=46000...
Content-Type: application/sdp
v=0
o=- 2890844526 2890844526 IN IP6 2001:db8::1
m=audio 5004 RTP/AVP 109 108 96 ← EVS/AMR-WB/AMR-NB编解码列表
a=rtpmap:109 EVS/...
a=fmtp:109 br=13.2; bw=nb-wb;...
a=sendrecv
a=des:qos mandatory local sendrecv ← 期望:主叫本地必须保证双向
a=des:qos mandatory remote sendrecv ← 期望:被叫侧也必须保证
a=cur:qos local none ← 现状:主叫本地资源尚未预留
a=cur:qos remote none
关键IE解读:
- Require: precondition——强制要求对端支持Precondition,否则直接拒绝。这是把"先占资源"变成硬性约束的开关。
- m=audio ... RTP/AVP 109 108 96——Offer的编解码优先级列表。VoNR中通常把EVS(109)放在最前,AMR-WB(108)次之,AMR-NB(96)兜底,体现5G对EVS编解码的偏好(TS 26.441)。
- a=des:qos mandatory local/remote sendrecv——把契约写死:双方都必须为sendrecv方向预留mandatory强度的QoS。
- a=cur:qos local none——明确告诉对端:"我现在还没预留,你别急着振铃。"
设计意图:Offer里同时声明"我要什么(des)"和"我有什么(cur)",让被叫一次性知道目标态和起点态,避免后续误解。
被叫UE收到INVITE后,不会立即振铃,而是先回一个带SDP Answer的临时响应:
SIP/2.0 183 Session Progress
Require: 100rel
RSeq: 1001 ← 100rel可靠传输序列号
Content-Type: application/sdp
m=audio 5006 RTP/AVP 108 96 ← 选定AMR-WB(被叫不支持/未配EVS时的回退)
a=des:qos mandatory local sendrecv
a=des:qos mandatory remote sendrecv
a=cur:qos local none ← 被叫本地也尚未预留
Require: 100rel + RSeq——这条183要求可靠传输(RFC 3262)。原因很关键:183里携带了SDP Answer,这是会话能力协商的结果,绝不能丢。如果用普通不可靠临时响应,丢包会导致主叫拿不到Answer而无法继续资源预留。所以必须用PRACK确认。a=cur。a=cur:qos local none——被叫也声明自己还没预留好,于是双方进入并行资源预留阶段。为什么用183而不是200 OK:因为此时双方cur都还是none,Precondition未满足,会话还不算成功,只能给临时响应。
这是VoNR区别于纯固网SIP的最关键一段。P-CSCF收到带SDP的INVITE/183后,必须把QoS需求翻译成5GC能理解的PCC规则:
flowchart TD
A["P-CSCF解析SDP<br/>提取媒体带宽/G.711/EVS比特率"] --> B["Rx:AAR<br/>Npcf_PolicyAuthorization_Create<br/>(Media-Component, 5QI=1, GBR)"]
B --> C["PCF安装PCC规则<br/>授权GBR带宽"]
C --> D["Npcf_SMPolicyControl_UpdateNotify"]
D --> E["SMF发起N4 Session<br/>Modification Request(UPF)"]
E --> F["SMF→AMF: N1N2MessageTransfer<br/>N2 SM信息(5QI=1, GBR)"]
F --> G["AMF→gNB: PDU Session<br/>Resource Setup/Modify"]
G --> H["专用QoS Flow建立<br/>UE↔UPF"]
H -.回调.-> A
参数映射要点(TS 23.503 §5.2.2、§6.1.3.15):
- 媒体类型→5QI:会话语音媒体映射为 5QI=1(GBR,时延预算100ms,丢包率10⁻²);IMS信令本身走5QI=5。
- SDP带宽→GBR:EVS的b=AS:或a=fmtp中的比特率,加上RTP/UDP/IP头开销,换算为上行/下行GBR(典型语音约几十kbps)。
- P-CSCF的Rx授权是异步的:P-CSCF发出AAR后并不阻塞信令,专载建立与后续SIP消息并行进行。这也是为什么UPDATE要等到本地预留完成后才发——它在等专载回调。
主叫UE收到183后,开始本地资源预留(与5GC建立专用QoS Flow并行)。一旦本地预留完成,主叫发UPDATE通知被叫:
UPDATE sip:... SIP/2.0
Content-Type: application/sdp
m=audio 5004 RTP/AVP 109 ← m行不变,只动cur
a=cur:qos local sendrecv ← 本地主叫侧资源已就绪!
a=des:qos mandatory local sendrecv
a=des:qos mandatory remote sendrecv
a=conf:qos remote sendrecv ← 请求:你那边就绪后务必通知我
a=cur:qos local sendrecv——这是契约推进的信号:主叫本地资源已经从none变为sendrecv。a=conf:qos remote sendrecv——conf属性的作用是:当被叫发现它自己的remote侧(即主叫到P-CSCF这段,从被叫视角看是remote)满足时,要主动发回确认。这是RFC 3312中实现"双向独立预留"通知机制的核心。为什么是UPDATE而不是re-INVITE:会话此时还处于早期对话(early dialog)阶段——INVITE事务尚未完成(还没收到200 OK),RFC不允许在INVITE事务期间发起re-INVITE。RFC 3311定义的UPDATE正是为"早期对话中重协商SDP"而生,它不影响目标号码,只刷新媒体参数。
被叫收到UPDATE后,如果它本地资源也已预留好(专载已建立),回送:
a=cur:qos local sendrecv
a=cur:qos remote sendrecv ← 被叫也声明remote(主叫侧)就绪
此刻,双方的des(mandatory sendrecv)与cur在local+remote四个维度全部对齐,Precondition满足。注意:因为被叫在主叫UPDATE里看到了a=conf:qos remote sendrecv,所以即便被叫先于主叫完成预留,它也会通过200 OK(UPDATE)把a=cur remote sendrecv带回去,履行conf契约。
Precondition满足后,被叫才振铃(180),用户摘机后回200 OK,主叫回ACK,会话正式进入确认态,RTP双向媒体才开始流动。整个过程的时序保证了接通瞬间承载已就绪,没有前向截断。
从UE视角看,一次主叫会话的资源状态在四个状态间迁移:
stateDiagram-v2
[*] --> Idle
Idle --> OfferSent: 发送INVITE<br/>(des约定, cur=none)
OfferSent --> Negotiating: 收到183(Answer)<br/>触发本地预留+Rx专载
Negotiating --> LocalReady: 本地cur=sendrecv<br/>发送UPDATE
LocalReady --> BothReady: 收到200 OK(UPDATE)<br/>对端cur=sendrecv
BothReady --> Ringing: Precondition满足<br/>允许振铃
Ringing --> Confirmed: 200 OK/ACK
Confirmed --> [*]
Negotiating --> Failed: 专载建立失败/超时<br/>a=cur无法达sendrecv
Failed --> [*]: 拆除会话
| 维度 | 带Precondition(VoNR/VoLTE标准) | 不带Precondition(固网VoIP) | 不带Precondition+事后建承载 |
|---|---|---|---|
| 振铃时机 | 双向资源就绪后 | 收到INVITE即可 | 收到INVITE即可 |
| 接通时前向截断 | 无 | 无(但QoS无保证) | 严重(承载滞后) |
| 信令开销 | 大(两次O/A+UPDATE+PRACK) | 小 | 小 |
| 呼叫建立时延 | 略高(多了专载等待) | 低 | 低但质量差 |
| 适用场景 | 移动网(无线资源受限、需GBR保证) | 有QoS保证的固网 | 不推荐 |
用Wireshark/TShark(配合pcap-analyzer技能)抓IMS UE的SIP信令,按以下方式定位:
sip.Method == "INVITE" or sip.CSeq.method == "INVITE",展开SDP,确认是否存在a=des:qos与a=cur:qos。Require: 100rel和RSeq头;若缺失,说明对端不支持可靠临时响应,会导致SDP Answer丢失风险。sip.Method == "UPDATE",检查其SDP中a=cur:qos local是否从none变为sendrecv——这是资源预留成功的判据。PFCP Session Modification Request,其中Create QER/Create FAR携带5QI=1、GBR速率。若SIP信令走完了但N4无对应修改,专载未建,呼叫必失败。常见故障点与排错:
| 现象 | 根因 | 排查方向 |
|---|---|---|
| INVITE后无183,直接488/Not Acceptable | 编解码协商失败(如主叫只给EVS,被叫不支持且未回退) | 核对m行与a=rtpmap/fmtp;检查EVS能力集 |
| 183后无UPDATE,呼叫挂死 | 专载建立失败或本地资源预留超时 | 查Rx AAR是否被PCF拒;查N4/N2是否成功;UE是否上报QoS Flow失败 |
| UPDATE发出后无200 OK(UPDATE) | 被叫侧资源预留卡住 | 查被叫P-CSCF的Rx授权与被叫专载状态 |
| 183收到但主叫不回PRACK | 100rel未启用或RSeq异常 | 检查183的Require:100rel与RSeq合法性 |
| 摘机后语音单通/质差 | 5QI=1误配为非GBR,或GBR带宽不足 | 核对PCC规则中5QI与GBR值 |
| ## 常见问题 |
Q1:为什么VoNR需要两次SDP Offer/Answer交换,而普通SIP呼叫只需一次? A:因为Precondition把"资源是否就绪"作为会话成立的条件,而资源预留是INVITE之后才发生的。第一次O/A(INVITE/183)用于约定"期望什么(des)"和"选定编解码",第二次O/A(UPDATE/200 OK)用于确认"资源真的预留好了(cur=sendrecv)"。一次O/A无法同时表达"约定目标"和"确认达成"两个时点。
Q2:UPDATE和re-INVITE有什么区别?为什么这里只能用UPDATE? A:re-INVITE用于已建立(confirmed)对话的会话重协商;UPDATE(RFC 3311)专用于早期对话(early dialog),即INVITE已发但尚未收到200 OK期间。Precondition确认发生在摘机之前,会话还在早期对话态,此时发re-INVITE是非法的,只能用UPDATE。
Q3:如果专载建立失败,会话会怎样?
A:受影响UE的a=cur无法达到sendrecv,Precondition不满足。按TS 23.228,UE会在定时器超时后发送CANCEL或BYE释放会话,用户表现为"无法接通"。这是Precondition机制保护质量的体现——宁可不接通,也不建立质量无法保证的通话。
Q4:183为什么必须用PRACK可靠确认? A:183携带SDP Answer,是会话能力协商的结论,丢包会导致主叫无法继续资源预留。RFC 3262的100rel机制通过RSeq+PRACK保证这条临时响应可靠送达。
本文由「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 等场景全覆盖。
