diff --git a/internal/context/amf_ran.go b/internal/context/amf_ran.go index 97b32641..a94c9c6c 100644 --- a/internal/context/amf_ran.go +++ b/internal/context/amf_ran.go @@ -63,7 +63,7 @@ func (ran *AmfRan) NewRanUe(ranUeNgapID int64) (*RanUe, error) { ranUe.RanUeNgapId = ranUeNgapID ranUe.Ran = ran ranUe.Log = ran.Log - ranUe.FindAmfUe = nil + ranUe.HoldingAmfUe = nil ranUe.UpdateLogFields() if ranUeNgapID != RanUeNgapIdUnspecified { diff --git a/internal/context/ran_ue.go b/internal/context/ran_ue.go index 60b28eb0..e80ef47d 100644 --- a/internal/context/ran_ue.go +++ b/internal/context/ran_ue.go @@ -47,9 +47,9 @@ type RanUe struct { LastActTime *time.Time /* Related Context*/ - AmfUe *AmfUe - Ran *AmfRan - FindAmfUe *AmfUe + AmfUe *AmfUe + Ran *AmfRan + HoldingAmfUe *AmfUe // The AmfUe that is already exist (CM-Idle, Re-Registration) /* Routing ID */ RoutingID string diff --git a/internal/gmm/common/user_profile.go b/internal/gmm/common/user_profile.go index 82013405..00b08a21 100644 --- a/internal/gmm/common/user_profile.go +++ b/internal/gmm/common/user_profile.go @@ -54,19 +54,19 @@ func PurgeAmfUeSubscriberData(ue *context.AmfUe) { } } -func AttachRanUeToAmfUeAndReleaseOldIfAny(ue *context.AmfUe, ranUe *context.RanUe) { - if oldRanUe := ue.RanUe[ranUe.Ran.AnType]; oldRanUe != nil { +func AttachRanUeToAmfUeAndReleaseOldIfAny(amfUe *context.AmfUe, ranUe *context.RanUe) { + if oldRanUe := amfUe.RanUe[ranUe.Ran.AnType]; oldRanUe != nil { oldRanUe.Log.Infof("Implicit Deregistration - RanUeNgapID[%d]", oldRanUe.RanUeNgapId) oldRanUe.DetachAmfUe() - if ue.T3550 != nil { - ue.State[ranUe.Ran.AnType].Set(context.Registered) + if amfUe.T3550 != nil { + amfUe.State[ranUe.Ran.AnType].Set(context.Registered) } - StopAll5GSMMTimers(ue) + StopAll5GSMMTimers(amfUe) causeGroup := ngapType.CausePresentRadioNetwork causeValue := ngapType.CauseRadioNetworkPresentReleaseDueToNgranGeneratedReason ngap_message.SendUEContextReleaseCommand(oldRanUe, context.UeContextReleaseUeContext, causeGroup, causeValue) } - ue.AttachRanUe(ranUe) + amfUe.AttachRanUe(ranUe) } func ClearHoldingRanUe(ranUe *context.RanUe) { diff --git a/internal/nas/handler.go b/internal/nas/handler.go index 5584074f..4cd477be 100644 --- a/internal/nas/handler.go +++ b/internal/nas/handler.go @@ -10,39 +10,49 @@ import ( "github.com/free5gc/nas" ) -func HandleNAS(ue *amf_context.RanUe, procedureCode int64, nasPdu []byte, initialMessage bool) { +func HandleNAS(ranUe *amf_context.RanUe, procedureCode int64, nasPdu []byte, initialMessage bool) { amfSelf := amf_context.GetSelf() - if ue == nil { + if ranUe == nil { logger.NasLog.Error("RanUe is nil") return } if nasPdu == nil { - ue.Log.Error("nasPdu is nil") + ranUe.Log.Error("nasPdu is nil") return } - if ue.AmfUe == nil { - ue.AmfUe = amfSelf.NewAmfUe("") - gmm_common.AttachRanUeToAmfUeAndReleaseOldIfAny(ue.AmfUe, ue) + if ranUe.AmfUe == nil { + // Only the New created RanUE will have no AmfUe in it + + if ranUe.HoldingAmfUe != nil && !ranUe.HoldingAmfUe.CmConnect(ranUe.Ran.AnType) { + // If the UE is CM-IDLE, there is no RanUE in AmfUe, so here we attach new RanUe to AmfUe. + gmm_common.AttachRanUeToAmfUeAndReleaseOldIfAny(ranUe.HoldingAmfUe, ranUe) + ranUe.HoldingAmfUe = nil + } else { + // Assume we have an existing UE context in CM-CONNECTED state. (RanUe <-> AmfUe) + // We will release it if the new UE context has a valid security context(Authenticated) in line 50. + ranUe.AmfUe = amfSelf.NewAmfUe("") + gmm_common.AttachRanUeToAmfUeAndReleaseOldIfAny(ranUe.AmfUe, ranUe) + } } - msg, integrityProtected, err := nas_security.Decode(ue.AmfUe, ue.Ran.AnType, nasPdu, initialMessage) + msg, integrityProtected, err := nas_security.Decode(ranUe.AmfUe, ranUe.Ran.AnType, nasPdu, initialMessage) if err != nil { - ue.AmfUe.NASLog.Errorln(err) + ranUe.AmfUe.NASLog.Errorln(err) return } - ue.AmfUe.NasPduValue = nasPdu - ue.AmfUe.MacFailed = !integrityProtected + ranUe.AmfUe.NasPduValue = nasPdu + ranUe.AmfUe.MacFailed = !integrityProtected - if ue.AmfUe.SecurityContextIsValid() && ue.FindAmfUe != nil { - gmm_common.ClearHoldingRanUe(ue.FindAmfUe.RanUe[ue.Ran.AnType]) - ue.FindAmfUe = nil + if ranUe.AmfUe.SecurityContextIsValid() && ranUe.HoldingAmfUe != nil { + gmm_common.ClearHoldingRanUe(ranUe.HoldingAmfUe.RanUe[ranUe.Ran.AnType]) + ranUe.HoldingAmfUe = nil } - if errDispatch := Dispatch(ue.AmfUe, ue.Ran.AnType, procedureCode, msg); errDispatch != nil { - ue.AmfUe.NASLog.Errorf("Handle NAS Error: %v", errDispatch) + if errDispatch := Dispatch(ranUe.AmfUe, ranUe.Ran.AnType, procedureCode, msg); errDispatch != nil { + ranUe.AmfUe.NASLog.Errorf("Handle NAS Error: %v", errDispatch) } } diff --git a/internal/ngap/handler.go b/internal/ngap/handler.go index 677b3231..d10116db 100644 --- a/internal/ngap/handler.go +++ b/internal/ngap/handler.go @@ -498,7 +498,7 @@ func handleInitialUEMessageMain(ran *context.AmfRan, // Described in TS 23.502 4.2.2.2.2 step 4 (without UDSF deployment) ranUe.Log.Infof("find AmfUe [%q:%q]", idType, id) ranUe.Log.Debugf("AmfUe Attach RanUe [RanUeNgapID: %d]", ranUe.RanUeNgapId) - ranUe.FindAmfUe = amfUe + ranUe.HoldingAmfUe = amfUe } else if regReqType != nasMessage.RegistrationType5GSInitialRegistration { if regReqType == nasMessage.RegistrationType5GSPeriodicRegistrationUpdating || regReqType == nasMessage.RegistrationType5GSMobilityRegistrationUpdating {