注销流程可以两种发起:
- UE 通知网络它不再访问 5GS
- 网络通知 UE 它不再有权访问 5GS
1. UE 发起 NAS Deregistration Request (UE Originating)
Gmm 消息类型设置为 MsgTypeDeregistrationRequestUEOriginatingDeregistration,NGAP UplinkNasTransport 消息 Present 设置为 NGAPPDUPresentInitiatingMessage,ProcedureCode 设置为 ProcedureCodeUplinkNASTransport
2. AMF 处理 uplinkNASTransport 消息
HandleUplinkNasTransport
--> HandleNAS
--> Dispatch
--> SendEvent GmmMessageEvent
--> Registered
Registered 中函数根据 nas 的 gmm MsgTypeDeregistrationRequestUEOriginatingDeregistration 类型 直接进行状态转移
State | Event | From | To |
Registered | GmmMessageEvent | Registered | Registered |
Registered -> DeregistrationInitiated | InitDeregistrationEvent | Registered | Registered |
func Registered(state *fsm.State, event fsm.EventType, args fsm.ArgsType) {
logger.GmmLog.Debugln("UE in GMM State[Registered]")
switch event {
case GmmMessageEvent:
amfUe := args[ArgAmfUe].(*context.AmfUe)
procedureCode := args[ArgProcedureCode].(int64)
gmmMessage := args[ArgNASMessage].(*nas.GmmMessage)
accessType := args[ArgAccessType].(models.AccessType)
switch gmmMessage.GetMessageType() {
case nas.MsgTypeDeregistrationRequestUEOriginatingDeregistration:
if err := GmmFSM.SendEvent(state, InitDeregistrationEvent, fsm.ArgsType{
ArgAmfUe: amfUe,
ArgAccessType: accessType,
ArgNASMessage: gmmMessage,
}); err != nil {
logger.GmmLog.Errorln(err)
}
2.1 DeregisteredInitiated 函数
处理函数为 HandleDeregistrationRequest
func DeregisteredInitiated(state *fsm.State, event fsm.EventType, args fsm.ArgsType) {
logger.GmmLog.Debugln("UE in GMM State[DeregisteredInitiated]")
switch event {
case fsm.EntryEvent:
amfUe := args[ArgAmfUe].(*context.AmfUe)
gmmMessage := args[ArgNASMessage].(*nas.GmmMessage)
accessType := args[ArgAccessType].(models.AccessType)
if err := HandleDeregistrationRequest(amfUe, accessType,
gmmMessage.DeregistrationRequestUEOriginatingDeregistration); err != nil {
logger.GmmLog.Errorln(err)
}
3. HandleDeregistrationRequest 函数
如果存在 UE 的 SM 上下文,则发起释放 SM 上下文的请求,
// TS 23.502 4.2.2.3
func HandleDeregistrationRequest(ue *context.AmfUe, anType models.AccessType,
deregistrationRequest *nasMessage.DeregistrationRequestUEOriginatingDeregistration) error {
logger.GmmLog.Info("[AMF] Handle Deregistration Request(UE Originating)")
targetDeregistrationAccessType := deregistrationRequest.GetAccessType()
for pduSessionId, smContext := range ue.SmContextList {
if smContext.PduSessionContext.AccessType != anType &&
targetDeregistrationAccessType != nasMessage.AccessTypeBoth {
continue
}
releaseData := consumer.BuildReleaseSmContextRequest(ue, nil, "", nil)
problemDetail, err := consumer.SendReleaseSmContextRequest(ue, pduSessionId, releaseData)
if problemDetail != nil {
logger.GmmLog.Errorf("Release SmContext Failed Problem[%+v]", problemDetail)
} else if err != nil {
logger.GmmLog.Errorf("Release SmContext Error[%v]", err.Error())
}
}
3.1 SendDeregistrationAccept 函数
发送 DownlinkNASTransport 请求,Deregistration accept 消息
func SendDeregistrationAccept(ue *context.RanUe) {
logger.GmmLog.Info("[NAS] Send Deregistration Accept")
nasMsg, err := BuildDeregistrationAccept()
if err != nil {
logger.GmmLog.Error(err.Error())
return
}
ngap_message.SendDownlinkNasTransport(ue, nasMsg, nil)
}
3.2 SendUEContextReleaseCommand 函数
状态转移
State | Event | From | To |
Registered | GmmMessageEvent | Registered | Registered |
Registered -> DeregistrationInitiated | InitDeregistrationEvent | Registered | Registered |
DeregistrationInitiated | Deregistration Accept | DeregistrationInitiated | Deregistered |
// TS 23.502 4.2.6, 4.12.3
switch targetDeregistrationAccessType {
case nasMessage.AccessType3GPP:
if ue.RanUe[models.AccessType__3_GPP_ACCESS] != nil {
ngap_message.SendUEContextReleaseCommand(ue.RanUe[models.AccessType__3_GPP_ACCESS],
context.UeContextReleaseUeContext, ngapType.CausePresentNas, ngapType.CauseNasPresentDeregister)
}
return GmmFSM.SendEvent(ue.State[models.AccessType__3_GPP_ACCESS], DeregistrationAcceptEvent, fsm.ArgsType{
ArgAmfUe: ue,
ArgAccessType: anType,
})
4. 发送 NGAP UE Context Release Complete
4.1 AMF 处理 NGAP UE Context Release Complete
func HandleUEContextReleaseComplete(ran *context.AmfRan, message *ngapType.NGAPPDU) {
var aMFUENGAPID *ngapType.AMFUENGAPID
var rANUENGAPID *ngapType.RANUENGAPID
var userLocationInformation *ngapType.UserLocationInformation
var infoOnRecommendedCellsAndRANNodesForPaging *ngapType.InfoOnRecommendedCellsAndRANNodesForPaging
var pDUSessionResourceList *ngapType.PDUSessionResourceListCxtRelCpl
var criticalityDiagnostics *ngapType.CriticalityDiagnostics
释放 RAN 等缓存信息