diff --git a/lte/gateway/c/oai/include/mme_app_ue_context.h b/lte/gateway/c/oai/include/mme_app_ue_context.h index e56964d829b7..93cc8633de0e 100644 --- a/lte/gateway/c/oai/include/mme_app_ue_context.h +++ b/lte/gateway/c/oai/include/mme_app_ue_context.h @@ -414,6 +414,7 @@ typedef struct ue_mm_context_s { * Stop when UE moves to connected state */ struct mme_app_timer_t implicit_detach_timer; + time_t time_implicit_detach_timer_started; /* Initial Context Setup Procedure Guard timer */ struct mme_app_timer_t initial_context_setup_rsp_timer; /* UE Context Modification Procedure Guard timer */ diff --git a/lte/gateway/c/oai/tasks/mme_app/mme_app_bearer.c b/lte/gateway/c/oai/tasks/mme_app/mme_app_bearer.c index 6ef7697d7a38..0e96d8359202 100644 --- a/lte/gateway/c/oai/tasks/mme_app/mme_app_bearer.c +++ b/lte/gateway/c/oai/tasks/mme_app/mme_app_bearer.c @@ -1590,6 +1590,7 @@ void mme_app_handle_mobile_reachability_timer_expiry(void* args) { ue_context_p->mme_ue_s1ap_id); ue_context_p->implicit_detach_timer.id = MME_APP_TIMER_INACTIVE_ID; } else { + ue_context_p->time_implicit_detach_timer_started = time(NULL); OAILOG_DEBUG_UE( LOG_MME_APP, ue_context_p->emm_context._imsi64, "Started Implicit Detach timer for UE id: " MME_UE_S1AP_ID_FMT "\n", @@ -1616,6 +1617,7 @@ void mme_app_handle_implicit_detach_timer_expiry(void* args) { OAILOG_FUNC_OUT(LOG_MME_APP); } ue_context_p->implicit_detach_timer.id = MME_APP_TIMER_INACTIVE_ID; + ue_context_p->time_implicit_detach_timer_started = 0; // Initiate Implicit Detach for the UE nas_proc_implicit_detach_ue_ind(mme_ue_s1ap_id); OAILOG_FUNC_OUT(LOG_MME_APP); diff --git a/lte/gateway/c/oai/tasks/mme_app/mme_app_context.c b/lte/gateway/c/oai/tasks/mme_app/mme_app_context.c index eb873dd1607d..b41653115ab3 100644 --- a/lte/gateway/c/oai/tasks/mme_app/mme_app_context.c +++ b/lte/gateway/c/oai/tasks/mme_app/mme_app_context.c @@ -102,6 +102,9 @@ static bool mme_app_recover_timers_for_ue( static void mme_app_resume_mobile_reachability_timer( struct ue_mm_context_s* const ue_mm_context_pP); +static void mme_app_resume_implicit_detach_timer( + struct ue_mm_context_s* const ue_mm_context_pP); + static void _directoryd_report_location(uint64_t imsi, uint8_t imsi_len) { char imsi_str[IMSI_BCD_DIGITS_MAX + 1]; IMSI64_TO_STRING(imsi, imsi_str, imsi_len); @@ -1529,6 +1532,7 @@ void mme_ue_context_update_ue_sig_connection_state( free_wrapper((void**) &timer_argP); } ue_context_p->implicit_detach_timer.id = MME_APP_TIMER_INACTIVE_ID; + ue_context_p->time_implicit_detach_timer_started = 0; } // Update Stats update_mme_app_stats_connected_ue_add(); @@ -2289,27 +2293,37 @@ static bool mme_app_recover_timers_for_ue( ue_mm_context_pP->time_mobile_reachability_timer_started) { mme_app_resume_mobile_reachability_timer(ue_mm_context_pP); } + if (ue_mm_context_pP && + ue_mm_context_pP->time_implicit_detach_timer_started) { + mme_app_resume_implicit_detach_timer(ue_mm_context_pP); + } OAILOG_FUNC_RETURN(LOG_MME_APP, false); } +// Resumes mobile reachability timer on MME restart static void mme_app_resume_mobile_reachability_timer( struct ue_mm_context_s* const ue_mm_context_pP) { OAILOG_FUNC_IN(LOG_MME_APP); time_t current_time = time(NULL); time_t lapsed_time = current_time - ue_mm_context_pP->time_mobile_reachability_timer_started; - ue_mm_context_pP->mobile_reachability_timer.sec = - (((mme_config.nas_config.t3412_min) + - MME_APP_DELTA_T3412_REACHABILITY_TIMER) * - 60) - - lapsed_time; + /* Below condition validates whether timer has expired before MME recovers + * from restart, so MME shall handle as timer expiry + */ + if (ue_mm_context_pP->mobile_reachability_timer.sec <= lapsed_time) { + mme_app_handle_mobile_reachability_timer_expiry( + (void*) &(ue_mm_context_pP->mme_ue_s1ap_id)); + OAILOG_FUNC_OUT(LOG_MME_APP); + } + uint32_t remaining_time_in_seconds = + ue_mm_context_pP->mobile_reachability_timer.sec - lapsed_time; OAILOG_DEBUG( LOG_MME_APP, - "Current_time :%ld time mobile reachability timer " - "started:%ld lapsed time:%ld remaining time:%ld\n", + "Current_time :%ld mobile reachability timer start time :%ld " + "lapsed time:%ld remaining time:%d \n", current_time, ue_mm_context_pP->time_mobile_reachability_timer_started, - lapsed_time, ue_mm_context_pP->mobile_reachability_timer.sec); + lapsed_time, remaining_time_in_seconds); // Start Mobile reachability timer only for remaining duration nas_itti_timer_arg_t timer_callback_arg = {0}; @@ -2318,9 +2332,8 @@ static void mme_app_resume_mobile_reachability_timer( timer_callback_arg.nas_timer_callback_arg = (void*) &(ue_mm_context_pP->mme_ue_s1ap_id); if (timer_setup( - ue_mm_context_pP->mobile_reachability_timer.sec, 0, TASK_MME_APP, - INSTANCE_DEFAULT, TIMER_ONE_SHOT, &timer_callback_arg, - sizeof(timer_callback_arg), + remaining_time_in_seconds, 0, TASK_MME_APP, INSTANCE_DEFAULT, + TIMER_ONE_SHOT, &timer_callback_arg, sizeof(timer_callback_arg), &(ue_mm_context_pP->mobile_reachability_timer.id)) < 0) { OAILOG_ERROR_UE( LOG_MME_APP, ue_mm_context_pP->emm_context._imsi64, @@ -2336,3 +2349,53 @@ static void mme_app_resume_mobile_reachability_timer( } OAILOG_FUNC_OUT(LOG_MME_APP); } + +// Resumes implicit detach timer on MME restart +static void mme_app_resume_implicit_detach_timer( + struct ue_mm_context_s* const ue_mm_context_pP) { + OAILOG_FUNC_IN(LOG_MME_APP); + time_t current_time = time(NULL); + time_t lapsed_time = + current_time - ue_mm_context_pP->time_implicit_detach_timer_started; + + /* Below condition validates whether timer has expired before MME recovers + * from restart, so MME shall handle as timer expiry + */ + if (ue_mm_context_pP->implicit_detach_timer.sec <= lapsed_time) { + mme_app_handle_implicit_detach_timer_expiry( + (void*) &(ue_mm_context_pP->mme_ue_s1ap_id)); + OAILOG_FUNC_OUT(LOG_MME_APP); + } + uint32_t remaining_time_in_seconds = + ue_mm_context_pP->implicit_detach_timer.sec - lapsed_time; + OAILOG_DEBUG( + LOG_MME_APP, + "Current_time :%ld imiplcit detach timer start time:%ld " + "lapsed time:%ld remaining time:%d \n", + current_time, ue_mm_context_pP->time_implicit_detach_timer_started, + lapsed_time, remaining_time_in_seconds); + + // Start Implicit detach timer only for remaining duration + nas_itti_timer_arg_t timer_callback_arg = {0}; + timer_callback_arg.nas_timer_callback = + mme_app_handle_implicit_detach_timer_expiry; + timer_callback_arg.nas_timer_callback_arg = + (void*) &(ue_mm_context_pP->mme_ue_s1ap_id); + if (timer_setup( + remaining_time_in_seconds, 0, TASK_MME_APP, INSTANCE_DEFAULT, + TIMER_ONE_SHOT, &timer_callback_arg, sizeof(timer_callback_arg), + &(ue_mm_context_pP->implicit_detach_timer.id)) < 0) { + OAILOG_ERROR_UE( + LOG_MME_APP, ue_mm_context_pP->emm_context._imsi64, + "Failed to start Implicit Detach timer for UE id " + " " MME_UE_S1AP_ID_FMT "\n", + ue_mm_context_pP->mme_ue_s1ap_id); + ue_mm_context_pP->implicit_detach_timer.id = MME_APP_TIMER_INACTIVE_ID; + } else { + OAILOG_DEBUG_UE( + LOG_MME_APP, ue_mm_context_pP->emm_context._imsi64, + "Started Implicit Detach timer for UE id " MME_UE_S1AP_ID_FMT "\n", + ue_mm_context_pP->mme_ue_s1ap_id); + } + OAILOG_FUNC_OUT(LOG_MME_APP); +} diff --git a/lte/gateway/c/oai/tasks/mme_app/mme_app_state_converter.cpp b/lte/gateway/c/oai/tasks/mme_app/mme_app_state_converter.cpp index a777b5b0a5cf..ed7b2b9e4dbf 100644 --- a/lte/gateway/c/oai/tasks/mme_app/mme_app_state_converter.cpp +++ b/lte/gateway/c/oai/tasks/mme_app/mme_app_state_converter.cpp @@ -504,6 +504,7 @@ void MmeNasStateConverter::proto_to_pdn_context_list( void MmeNasStateConverter::ue_context_to_proto( const ue_mm_context_t* state_ue_context, oai::UeContext* ue_context_proto) { + OAILOG_FUNC_IN(LOG_MME_APP); ue_context_proto->Clear(); char* msisdn_buffer = bstr2cstr(state_ue_context->msisdn, (char) '?'); @@ -602,11 +603,15 @@ void MmeNasStateConverter::ue_context_to_proto( ue_context_proto->mutable_ulr_response_timer()); ue_context_proto->mutable_time_mobile_reachability_timer_started() ->set_seconds(state_ue_context->time_mobile_reachability_timer_started); + ue_context_proto->mutable_time_implicit_detach_timer_started()->set_seconds( + state_ue_context->time_implicit_detach_timer_started); + OAILOG_FUNC_OUT(LOG_MME_APP); } void MmeNasStateConverter::proto_to_ue_mm_context( const oai::UeContext& ue_context_proto, ue_mm_context_t* state_ue_mm_context) { + OAILOG_FUNC_IN(LOG_MME_APP); state_ue_mm_context->msisdn = bfromcstr(ue_context_proto.msisdn().c_str()); state_ue_mm_context->ue_context_rel_cause = static_cast(ue_context_proto.rel_cause()); @@ -690,6 +695,9 @@ void MmeNasStateConverter::proto_to_ue_mm_context( &state_ue_mm_context->paging_response_timer); state_ue_mm_context->time_mobile_reachability_timer_started = ue_context_proto.time_mobile_reachability_timer_started().seconds(); + state_ue_mm_context->time_implicit_detach_timer_started = + ue_context_proto.time_implicit_detach_timer_started().seconds(); + OAILOG_FUNC_OUT(LOG_MME_APP); } /********************************************************* diff --git a/lte/gateway/c/oai/tasks/mme_app/mme_app_state_manager.cpp b/lte/gateway/c/oai/tasks/mme_app/mme_app_state_manager.cpp index 3fb9e7564e6d..b056aa89d806 100644 --- a/lte/gateway/c/oai/tasks/mme_app/mme_app_state_manager.cpp +++ b/lte/gateway/c/oai/tasks/mme_app/mme_app_state_manager.cpp @@ -136,6 +136,9 @@ void MmeNasStateManager::mme_nas_state_init_local_state() { mme_statistic_timer_); state_cache_p->statistic_timer_id = 0; } + if (is_initialized) { + mme_app_recover_timers_for_all_ues(); + } } // Create the hashtables for MME NAS state diff --git a/lte/protos/oai/mme_nas_state.proto b/lte/protos/oai/mme_nas_state.proto index 7df7ae267418..38ba757fa21f 100644 --- a/lte/protos/oai/mme_nas_state.proto +++ b/lte/protos/oai/mme_nas_state.proto @@ -133,6 +133,7 @@ message UeContext { uint32 rau_tau_timer = 205; Timer ulr_response_timer = 206; google.protobuf.Timestamp time_mobile_reachability_timer_started = 207; + google.protobuf.Timestamp time_implicit_detach_timer_started = 208; } // mme_ue_context_t