结构体 HandoverRequiredIEsValue
type HandoverRequiredIEsValue struct {
Present int
AMFUENGAPID *AMFUENGAPID `aper:"referenceFieldValue:10"`
RANUENGAPID *RANUENGAPID `aper:"referenceFieldValue:85"`
HandoverType *HandoverType `aper:"referenceFieldValue:29"`
Cause *Cause `aper:"referenceFieldValue:15,valueLB:0,valueUB:5"`
TargetID *TargetID `aper:"referenceFieldValue:105,valueLB:0,valueUB:2"`
DirectForwardingPathAvailability *DirectForwardingPathAvailability `aper:"referenceFieldValue:22"`
PDUSessionResourceListHORqd *PDUSessionResourceListHORqd `aper:"referenceFieldValue:61"`
SourceToTargetTransparentContainer *SourceToTargetTransparentContainer `aper:"referenceFieldValue:101"`
}
结构体定义根据 TS 38413 9.2.3.1 定义
IE/Group Name |
Presence |
Range |
IE type and reference |
Semantics description |
Criticality |
Assigned Criticality |
Message Type |
M |
9.3.1.1 |
YES |
reject |
||
AMF UE NGAP ID |
M |
9.3.3.1 |
YES |
reject |
||
RAN UE NGAP ID |
M |
9.3.3.2 |
YES |
reject |
||
Handover Type |
M |
9.3.1.22 |
YES |
reject |
||
Cause |
M |
9.3.1.2 |
YES |
ignore |
||
Target ID |
M |
9.3.1.25 |
YES |
reject |
||
Direct Forwarding Path Availability |
O |
9.3.1.64 |
YES |
ignore |
||
PDU Session Resource List |
1 |
YES |
reject |
|||
>PDU Session Resource Item |
1..<maxnoofPDUSessions> |
- |
||||
>>PDU Session ID |
M |
9.3.1.50 |
- |
|||
>>Handover Required Transfer |
M |
OCTET STRING |
Containing the Handover Required Transfer IE specified in subclause 9.3.4.14. |
- |
||
Source to Target Transparent Container |
M |
9.3.1.20 |
YES |
reject |
1. Handover Required (S-RAN -> S-AMF)
BuildHandoverRequired 创建 NGAP 消息,类型为 NGAPPDUPresentInitiatingMessage,ProcedureCode 设置为 ProcedureCodeHandoverPreparation,InitiatingMessagePresentHandoverRequired,包括的 IE 如下:
- AMF UE NGAP ID
- RAN UE NGAP ID
- Handover Type (TS 38413 9.3.1.22) Intra5GS, 5GStoEPS, EPSto5GS
- Cause (TS 38413 9.3.1.2)
- Target ID(TS 38413 9.3.1.25)
- Direct Forwarding Path Availability [optional]
- PDU Session Resource List
- Source to Target Transparent Container
1.1 AMF 处理 Handover Required 请求
根据目标 RAN 如果未缓存则需要(未实现),缺少 T-AMF 选择
var aMFSelf = context.AMF_Self()
targetRanNodeId := ngapConvert.RanIdToModels(targetID.TargetRANNodeID.GlobalRANNodeID)
targetRan := aMFSelf.AmfRanFindByRanId(targetRanNodeId)
if targetRan == nil {
// handover between different AMF
logger.NgapLog.Warnf("Handover required : cannot find target Ran Node Id[%+v] in this AMF", targetRanNodeId)
logger.NgapLog.Error("Handover between different AMF has not been implemented yet")
return
// TODO: Send to T-AMF
// Described in (23.502 4.9.1.3.2) step 3.Namf_Communication_CreateUEContext Request
}
1.2 在同一个 AMF 切换
如果存在 PDU 会话则更新 SMF 会话上下文,BuildUpdateSmContextRequsetHandover 实例化 SmContextUpdateData,向 SMF 发送 Nsmf_PDUSession_UpdateSMContext 请求 (/sm-contexts/{smContextRef}/modify),结构体为 SmContextUpdateData
// Handover in same AMF
sourceUe.HandOverType.Value = handoverType.Value
tai := ngapConvert.TaiToModels(targetID.TargetRANNodeID.SelectedTAI)
targetId := models.NgRanTargetId{
RanNodeId: &targetRanNodeId,
Tai: &tai,
}
var pduSessionReqList ngapType.PDUSessionResourceSetupListHOReq
for _, pDUSessionResourceHoItem := range pDUSessionResourceListHORqd.List {
pduSessionId := int32(pDUSessionResourceHoItem.PDUSessionID.Value)
if smContext, exist := amfUe.SmContextList[pduSessionId]; exist {
response, _, _, _ := consumer.SendUpdateSmContextN2HandoverPreparing(amfUe, pduSessionId, models.N2SmInfoType_HANDOVER_REQUIRED, pDUSessionResourceHoItem.HandoverRequiredTransfer, "", &targetId)
if response == nil {
logger.NgapLog.Errorf("SendUpdateSmContextN2HandoverPreparing Error for PduSessionId[%d]", pduSessionId)
continue
} else if response.BinaryDataN2SmInformation != nil {
ngap_message.AppendPDUSessionResourceSetupListHOReq(&pduSessionReqList, pduSessionId, *smContext.PduSessionContext.SNssai, response.BinaryDataN2SmInformation)
}
}
}
1.3. SMF 处理上下文更新操作
UpdateSmContext 函数设置消息类型为 PDUSessionSMContextUpdate,丢进队列进行处理,定位到函数 HandlePDUSessionSMContextUpdate,根据 AMF 只设置 N2 信息,
{
"hoState":"PREPARING",
"n2SmInfo":{
"contentId":"N2SmInfo"
},
"n2SmInfoType":"HANDOVER_REQUIRED",
"targetId":{
"ranNodeId":{
"plmnId":{
"mcc":"208",
"mnc":"93"
},
"gNbId":{
"bitLength":24,
"gNBValue":"000102"
}
},
"tai":{
"plmnId":{
"mcc":"208",
"mnc":"93"
},
"tac":"303399"
}
}
}
根据 hoState 为 HoState_PREPARING,设置 N2SmInfoType 为 N2SmInfoType_PDU_RES_SETUP_REQ
switch smContextUpdateData.HoState {
case models.HoState_PREPARING:
smContext.HoState = models.HoState_PREPARING
err = smf_context.HandleHandoverRequiredTransfer(body.BinaryDataN2SmInformation, smContext)
response.JsonData.N2SmInfoType = models.N2SmInfoType_PDU_RES_SETUP_REQ
n2Buf, err := smf_context.BuildPDUSessionResourceSetupRequestTransfer(smContext)
if err != nil {
logger.PduSessLog.Errorf("Build PDUSession Resource Setup Request Transfer Error(%s)", err.Error())
}
response.BinaryDataN2SmInformation = n2Buf
response.JsonData.N2SmInfoType = models.N2SmInfoType_PDU_RES_SETUP_REQ
response.JsonData.N2SmInfo = &models.RefToBinaryData{
ContentId: "PDU_RES_SETUP_REQ",
}
response.JsonData.HoState = models.HoState_PREPARING
1.3.1 SendPfcpSessionModificationRequest
BuildPfcpSessionModificationRequest 实例化 PFCPSessionModificationRequest,包括 Update PDR, Update FAR,Update BAR,CP F-SEID,消息头类型设置为 PFCP_SESSION_MODIFICATION_REQUEST
向 UPF 发送 N4 Session Modification Request
seqNum = getSeqNumber()
nodeIDtoIP := upNodeID.ResolveNodeIdToIp().String()
remoteSEID := ctx.PFCPContext[nodeIDtoIP].RemoteSEID
message := pfcp.Message{
Header: pfcp.Header{
Version: pfcp.PfcpVersion,
MP: 1,
S: pfcp.SEID_PRESENT,
MessageType: pfcp.PFCP_SESSION_MODIFICATION_REQUEST,
SEID: remoteSEID,
SequenceNumber: seqNum,
MessagePriority: 12,
},
Body: pfcpMsg,
}
1.3.2 UPF 处理 N4 Session Modification Request
Status UpfN4HandleSessionModificationRequest(UpfSession *session, PfcpXact *xact,
PFCPSessionModificationRequest *request) {
UTLT_Assert(session, return STATUS_ERROR, "Session error");
UTLT_Assert(xact, return STATUS_ERROR, "xact error");
Status status;
PfcpHeader header;
Bufblk *bufBlk;
UpfN4HandleCreateFar
UpfN4HandleCreatePdr
响应消息 N4 Session Modification Response,设置头类型为 PFCP_SESSION_MODIFICATION_RESPONSE
调用 UpfN4BuildSessionModificationResponse 向 SMF 回复请求,设置 cause 为 PFCP_CAUSE_REQUEST_ACCEPTED
1.3.3 SMF 接收处理 N4 Session Modification Response
func HandlePfcpSessionModificationResponse(msg *pfcpUdp.Message) {
pfcpRsp := msg.PfcpMessage.Body.(pfcp.PFCPSessionModificationResponse)
SEID := msg.PfcpMessage.Header.SEID
seqNum := msg.PfcpMessage.Header.SequenceNumber
smContext := smf_context.GetSMContextBySEID(SEID)
2.3.1如果 SMF 支持 ULCL 功能
AddPDUSessionAnchorAndULCL (待分析)
if smf_context.SMF_Self().ULCLSupport && smContext.BPManager != nil {
if smContext.BPManager.BPStatus == smf_context.AddingPSA {
logger.PfcpLog.Infoln("Keep Adding PSAAndULCL")
upfNodeID := smContext.GetNodeIDByLocalSEID(SEID)
producer.AddPDUSessionAnchorAndULCL(smContext, upfNodeID)
}
}
2. SendHandoverRequest (AMF 向 RAN 发送)
/*The PGW-C+SMF (V-SMF in the case of home-routed roaming scenario only) sends
a Nsmf_PDUSession_CreateSMContext Response(N2 SM Information (PDU Session ID, cause code)) to the AMF.*/
// Cause is from SMF
// pduSessionResourceSetupList provided by AMF, and the transfer data is from SMF
// sourceToTargetTransparentContainer is received from S-RAN
// nsci: new security context indicator, if amfUe has updated security context, set nsci to true, otherwise set to false
// N2 handover in same AMF
func SendHandoverRequest(sourceUe *context.RanUe, targetRan *context.AmfRan, cause ngapType.Cause, pduSessionResourceSetupListHOReq ngapType.PDUSessionResourceSetupListHOReq,
sourceToTargetTransparentContainer ngapType.SourceToTargetTransparentContainer, nsci bool) {
ngaplog.Info("[AMF] Send Handover Request")
AMF -> RAN 包括的信息:
- Source to Target transparent container
- N2 MM Information [ security information and Mobility Restriction List ]
- N2 SM Information list
- [ Tracing Requirements ]
2.1 BuildHandoverRequest 实例化 NGAP 消息
类型为 NGAPPDUPresentInitiatingMessage,ProcedureCode 设置为 ProcedureCodeHandoverResourceAllocation,InitiatingMessagePresentHandoverRequest
3. T-RAN 发送 Handover Request 确认消息
创建 NGAP 消息类型为 NGAPPDUPresentSuccessfulOutcome,ProcedureCode 设置为 ProcedureCodeHandoverResourceAllocation,SuccessfulOutcomePresentHandoverRequestAcknowledge,包括 IE
- AMF UE NGAP ID
- RAN UE NGAP ID
- PDU Session Resource Admitted List
- PDU SessionResource Admittedy Item
- PDU Session Resource Failed to setup Item
- Target To Source TransparentContainer
- Criticality Diagnostics (optional)
4. AMF 处理 Handover Request 确认消息
func HandleHandoverRequestAcknowledge(ran *context.AmfRan, message *ngapType.NGAPPDU) {
var aMFUENGAPID *ngapType.AMFUENGAPID
var rANUENGAPID *ngapType.RANUENGAPID
var pDUSessionResourceAdmittedList *ngapType.PDUSessionResourceAdmittedList
var pDUSessionResourceFailedToSetupListHOAck *ngapType.PDUSessionResourceFailedToSetupListHOAck
var targetToSourceTransparentContainer *ngapType.TargetToSourceTransparentContainer
var criticalityDiagnostics *ngapType.CriticalityDiagnostics
4.1 对于 pDUSessionResourceAdmittedList 不为空时
SendUpdateSmContextN2HandoverPrepared 由 T-AMF 到 SMF (Nsmf_PDUSession_UpdateSMContext Request)
BuildUpdateSmContextRequsetHandover 函数
case UpdateSmContextPresentN2HandoverPreparing:
updateData.HoState = models.HoState_PREPARING
updateData.TargetId = param.targetId
// amf changed in same plmn
if param.amfid != "" {
updateData.TargetServingNfId = param.amfid
}
向 SMF 发送 Nsmf_PDUSession_UpdateSMContext (/sm-contexts/{smContextRef}/modify)
又走 N4 接口 N4 Session Modification Request/Response 等(分析待定)
5. SendHandoverCommand 函数
AMF 向 RAN 发送 Handover Command 请求,NGAP 消息类型为 NGAPPDUPresentSuccessfulOutcome,ProcedureCode 为 ProcedureCodeHandoverPreparation,包括的 IE
- AMF UE NGAP ID
- RAN UE NGAP ID
- Handover Type
- NAS Security Parameters from NG-RAN [C-iftoEPS]
- PDU Session Resource Handover List
- PDU Session Resource to Release List
- Target to Source Transparent Container
6. RAN 发起 Handover Notification 到 AMF
由 T-NG-RAN 发送的消息来通知 AMF UE 已经在目标小区标识,切换已经完成。NGAP 消息类型为 NGAPPDUPresentInitiatingMessage,ProcedureCode 设置为 ProcedureCodeHandoverNotification, InitiatingMessagePresentHandoverNotify,包括的 IE:
- AMF UE NGAP ID
- RAN UE NGAP ID
- User Location Information
7. AMF 处理 Handover Notification 消息
7.1 如果 AMF 不存在 UE 情况
未实现步骤 6a.Namf_Communication_N2InfoNotify
amfUe := targetUe.AmfUe
if amfUe == nil {
Ngaplog.Error("AmfUe is nil")
return
}
sourceUe := targetUe.SourceUe
if sourceUe == nil {
// TODO: Send to S-AMF
// Desciibed in (23.502 4.9.1.3.3) [conditional] 6a.Namf_Communication_N2InfoNotify.
Ngaplog.Error("N2 Handover between AMF has not been implemented yet")
}
7.2 Handover notification 完成
对所有成功的 PDU 会话执行 SendUpdateSmContextN2HandoverComplete,BuildUpdateSmContextRequsetHandover 实例化 SmContextUpdateData,设置 HoState_COMPLETED
case UpdateSmContextPresentN2HandoverComplete:
updateData.HoState = models.HoState_COMPLETED
if param.amfid != "" {
updateData.ServingNfId = param.amfid
updateData.ServingNetwork = param.guami.PlmnId
updateData.Guami = param.guami
}
if ladn, ok := context.LadnPool[smContext.PduSessionContext.Dnn]; ok {
if amf_context.InTaiList(ue.Tai, ladn.TaiLists) {
updateData.PresenceInLadn = models.PresenceState_IN_AREA
} else {
updateData.PresenceInLadn = models.PresenceState_OUT_OF_AREA
}
}
SendUpdateSmContextRequest 向 SMF 发送 Nsmf_PDUSession_UpdateSMContext (/sm-contexts/{smContextRef}/modify) 向每一个 PDU 会话对应的 SMF 发送 Handover Complete 来指示 N2 切换成功
对应 Handover 执行阶段步骤 7(T-AMF->SMF)