[#220] Timer for UE Context Release
This commit is contained in:
parent
5ce04bcc6f
commit
ae3e59053d
|
@ -1844,6 +1844,9 @@ enb_ue_t *enb_ue_add(mme_enb_t *enb)
|
|||
|
||||
enb_ue->enb = enb;
|
||||
|
||||
enb_ue->t_ue_context_release.timer = ogs_timer_add(
|
||||
self.timer_mgr, mme_timer_ue_context_release, enb_ue);
|
||||
|
||||
ogs_hash_set(self.mme_ue_s1ap_id_hash, &enb_ue->mme_ue_s1ap_id,
|
||||
sizeof(enb_ue->mme_ue_s1ap_id), enb_ue);
|
||||
ogs_list_add(&enb->enb_ue_list, enb_ue);
|
||||
|
@ -1863,6 +1866,9 @@ void enb_ue_remove(enb_ue_t *enb_ue)
|
|||
ogs_assert(enb_ue);
|
||||
ogs_assert(enb_ue->enb);
|
||||
|
||||
CLEAR_ENB_UE_ALL_TIMERS(enb_ue);
|
||||
ogs_timer_delete(enb_ue->t_ue_context_release.timer);
|
||||
|
||||
/* De-associate S1 with NAS/EMM */
|
||||
enb_ue_deassociate(enb_ue);
|
||||
|
||||
|
@ -2547,6 +2553,7 @@ void mme_bearer_remove(mme_bearer_t *bearer)
|
|||
ogs_fsm_fini(&bearer->sm, &e);
|
||||
ogs_fsm_delete(&bearer->sm);
|
||||
|
||||
CLEAR_BEARER_ALL_TIMERS(bearer);
|
||||
ogs_timer_delete(bearer->t3489.timer);
|
||||
|
||||
ogs_list_remove(&bearer->sess->bearer_list, bearer);
|
||||
|
|
|
@ -265,6 +265,26 @@ struct enb_ue_s {
|
|||
#define S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL 4
|
||||
uint8_t ue_ctx_rel_action;
|
||||
|
||||
#define CLEAR_ENB_UE_ALL_TIMERS(__eNB) \
|
||||
do { \
|
||||
CLEAR_ENB_UE_TIMER((__eNB)->t_ue_context_release); \
|
||||
} while(0);
|
||||
#define CLEAR_ENB_UE_TIMER(__eNB_UE_TIMER) \
|
||||
do { \
|
||||
ogs_timer_stop((__eNB_UE_TIMER).timer); \
|
||||
if ((__eNB_UE_TIMER).pkbuf) \
|
||||
{ \
|
||||
ogs_pkbuf_free((__eNB_UE_TIMER).pkbuf); \
|
||||
(__eNB_UE_TIMER).pkbuf = NULL; \
|
||||
} \
|
||||
(__eNB_UE_TIMER).retry_count = 0; \
|
||||
} while(0);
|
||||
struct {
|
||||
ogs_pkbuf_t *pkbuf;
|
||||
ogs_timer_t *timer;
|
||||
uint32_t retry_count;;
|
||||
} t_ue_context_release;
|
||||
|
||||
/* Related Context */
|
||||
mme_enb_t *enb;
|
||||
mme_ue_t *mme_ue;
|
||||
|
|
|
@ -50,6 +50,7 @@ int mme_send_delete_session_or_ue_context_release(
|
|||
rv = mme_gtp_send_delete_all_sessions(mme_ue);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
} else {
|
||||
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
|
||||
rv = s1ap_send_ue_context_release_command(enb_ue,
|
||||
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
|
||||
S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
|
||||
|
@ -70,6 +71,7 @@ int mme_send_release_access_bearer_or_ue_context_release(
|
|||
rv = mme_gtp_send_release_access_bearers_request(mme_ue);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
} else {
|
||||
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
|
||||
rv = s1ap_send_ue_context_release_command(enb_ue,
|
||||
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
|
||||
S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0);
|
||||
|
|
|
@ -154,6 +154,7 @@ void mme_s11_handle_modify_bearer_response(
|
|||
source_ue = target_ue->source_ue;
|
||||
ogs_assert(source_ue);
|
||||
|
||||
CLEAR_ENB_UE_TIMER(source_ue->t_ue_context_release);
|
||||
rv = s1ap_send_ue_context_release_command(source_ue,
|
||||
S1AP_Cause_PR_radioNetwork,
|
||||
S1AP_CauseRadioNetwork_successful_handover,
|
||||
|
@ -227,6 +228,7 @@ void mme_s11_handle_delete_session_response(
|
|||
|
||||
enb_ue = mme_ue->enb_ue;
|
||||
if (enb_ue) {
|
||||
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
|
||||
rv = s1ap_send_ue_context_release_command(enb_ue,
|
||||
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
|
||||
S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
|
||||
|
@ -244,6 +246,7 @@ void mme_s11_handle_delete_session_response(
|
|||
|
||||
enb_ue = mme_ue->enb_ue;
|
||||
if (enb_ue) {
|
||||
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
|
||||
rv = s1ap_send_ue_context_release_command(enb_ue,
|
||||
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
|
||||
S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
|
||||
|
@ -509,6 +512,7 @@ void mme_s11_handle_release_access_bearers_response(
|
|||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
if (enb_ue) {
|
||||
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
|
||||
rv = s1ap_send_ue_context_release_command(enb_ue,
|
||||
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
|
||||
S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0);
|
||||
|
|
|
@ -219,9 +219,9 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
|
|||
ogs_assert(enb);
|
||||
ogs_assert(OGS_FSM_STATE(&enb->sm));
|
||||
|
||||
ogs_fsm_dispatch(&enb->sm, e);
|
||||
|
||||
ogs_timer_delete(e->timer);
|
||||
if (enb_ue_find_by_mme_ue_s1ap_id(enb_ue->mme_ue_s1ap_id)) {
|
||||
ogs_fsm_dispatch(&enb->sm, e);
|
||||
}
|
||||
break;
|
||||
|
||||
case MME_EVT_EMM_MESSAGE:
|
||||
|
@ -363,6 +363,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
|
|||
enb_ue = mme_ue->enb_ue;
|
||||
ogs_assert(enb_ue);
|
||||
|
||||
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
|
||||
rv = s1ap_send_ue_context_release_command(enb_ue,
|
||||
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
|
||||
S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "mme-context.h"
|
||||
|
||||
static mme_timer_cfg_t g_mme_timer_cfg[MAX_NUM_OF_MME_TIMER] = {
|
||||
[MME_TIMER_UE_CONTEXT_RELEASE] =
|
||||
{ .max_count = 2, .duration = ogs_time_from_sec(1) },
|
||||
[MME_TIMER_T3413] =
|
||||
{ .max_count = 2, .duration = ogs_time_from_sec(2) },
|
||||
[MME_TIMER_T3422] =
|
||||
|
@ -54,6 +56,8 @@ const char *mme_timer_get_name(mme_timer_e id)
|
|||
switch (id) {
|
||||
case MME_TIMER_S1_DELAYED_SEND:
|
||||
return "MME_TIMER_S1_DELAYED_SEND";
|
||||
case MME_TIMER_UE_CONTEXT_RELEASE:
|
||||
return "MME_TIMER_UE_CONTEXT_RELEASE";
|
||||
case MME_TIMER_T3413:
|
||||
return "MME_TIMER_T3413";
|
||||
case MME_TIMER_T3422:
|
||||
|
@ -91,6 +95,49 @@ void mme_timer_s1_delayed_send(void *data)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void s1_timer_event_send(
|
||||
mme_timer_e timer_id, enb_ue_t *enb_ue)
|
||||
{
|
||||
int rv;
|
||||
mme_event_t *e = NULL;
|
||||
ogs_assert(enb_ue);
|
||||
|
||||
e = mme_event_new(MME_EVT_S1AP_TIMER);
|
||||
e->timer_id = timer_id;
|
||||
e->enb_ue = enb_ue;
|
||||
e->enb = enb_ue->enb;
|
||||
|
||||
rv = ogs_queue_push(mme_self()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
|
||||
mme_event_free(e);
|
||||
}
|
||||
}
|
||||
|
||||
void mme_timer_ue_context_release(void *data)
|
||||
{
|
||||
s1_timer_event_send(MME_TIMER_UE_CONTEXT_RELEASE, data);
|
||||
}
|
||||
|
||||
static void emm_timer_event_send(
|
||||
mme_timer_e timer_id, mme_ue_t *mme_ue)
|
||||
{
|
||||
int rv;
|
||||
mme_event_t *e = NULL;
|
||||
ogs_assert(mme_ue);
|
||||
|
||||
e = mme_event_new(MME_EVT_EMM_TIMER);
|
||||
e->timer_id = timer_id;
|
||||
e->mme_ue = mme_ue;
|
||||
|
||||
rv = ogs_queue_push(mme_self()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
|
||||
mme_event_free(e);
|
||||
}
|
||||
}
|
||||
|
||||
void mme_timer_t3413_expire(void *data)
|
||||
{
|
||||
emm_timer_event_send(MME_TIMER_T3413, data);
|
||||
|
@ -111,28 +158,6 @@ void mme_timer_t3470_expire(void *data)
|
|||
{
|
||||
emm_timer_event_send(MME_TIMER_T3470, data);
|
||||
}
|
||||
void mme_timer_t3489_expire(void *data)
|
||||
{
|
||||
esm_timer_event_send(MME_TIMER_T3489, data);
|
||||
}
|
||||
|
||||
static void emm_timer_event_send(
|
||||
mme_timer_e timer_id, mme_ue_t *mme_ue)
|
||||
{
|
||||
int rv;
|
||||
mme_event_t *e = NULL;
|
||||
ogs_assert(mme_ue);
|
||||
|
||||
e = mme_event_new(MME_EVT_EMM_TIMER);
|
||||
e->timer_id = timer_id;
|
||||
e->mme_ue = mme_ue;
|
||||
|
||||
rv = ogs_queue_push(mme_self()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
|
||||
mme_event_free(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void esm_timer_event_send(
|
||||
mme_timer_e timer_id, mme_bearer_t *bearer)
|
||||
|
@ -156,6 +181,11 @@ static void esm_timer_event_send(
|
|||
}
|
||||
}
|
||||
|
||||
void mme_timer_t3489_expire(void *data)
|
||||
{
|
||||
esm_timer_event_send(MME_TIMER_T3489, data);
|
||||
}
|
||||
|
||||
void mme_timer_sgs_cli_conn_to_srv(void *data)
|
||||
{
|
||||
int rv;
|
||||
|
|
|
@ -32,6 +32,8 @@ typedef enum {
|
|||
|
||||
MME_TIMER_S1_DELAYED_SEND,
|
||||
|
||||
MME_TIMER_UE_CONTEXT_RELEASE,
|
||||
|
||||
/* Paging procedure for EPS services initiated */
|
||||
MME_TIMER_T3413,
|
||||
|
||||
|
@ -70,6 +72,7 @@ mme_timer_cfg_t *mme_timer_cfg(mme_timer_e id);
|
|||
const char *mme_timer_get_name(mme_timer_e id);
|
||||
|
||||
void mme_timer_s1_delayed_send(void *data);
|
||||
void mme_timer_ue_context_release(void *data);
|
||||
|
||||
void mme_timer_t3413_expire(void *data);
|
||||
void mme_timer_t3422_expire(void *data);
|
||||
|
|
|
@ -271,6 +271,7 @@ int nas_send_detach_accept(mme_ue_t *mme_ue)
|
|||
ogs_assert(rv == OGS_OK);
|
||||
}
|
||||
|
||||
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
|
||||
rv = s1ap_send_ue_context_release_command(enb_ue,
|
||||
S1AP_Cause_PR_nas, S1AP_CauseNas_detach,
|
||||
S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0);
|
||||
|
|
|
@ -928,6 +928,7 @@ void s1ap_handle_ue_context_release_request(
|
|||
}
|
||||
} else {
|
||||
ogs_debug(" S1 Context Not Associated");
|
||||
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
|
||||
rv = s1ap_send_ue_context_release_command(enb_ue,
|
||||
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
|
||||
S1AP_UE_CTX_REL_NO_ACTION, 0);
|
||||
|
@ -989,6 +990,7 @@ void s1ap_handle_ue_context_release_complete(
|
|||
ogs_assert(rv == OGS_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
mme_ue = enb_ue->mme_ue;
|
||||
|
||||
ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
|
||||
|
@ -1630,6 +1632,7 @@ void s1ap_handle_handover_failure(mme_enb_t *enb, s1ap_message_t *message)
|
|||
rv = s1ap_send_handover_preparation_failure(source_ue, Cause);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
CLEAR_ENB_UE_TIMER(target_ue->t_ue_context_release);
|
||||
rv = s1ap_send_ue_context_release_command(
|
||||
target_ue, S1AP_Cause_PR_radioNetwork,
|
||||
S1AP_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system,
|
||||
|
@ -1702,6 +1705,7 @@ void s1ap_handle_handover_cancel(mme_enb_t *enb, s1ap_message_t *message)
|
|||
rv = s1ap_send_handover_cancel_ack(source_ue);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
CLEAR_ENB_UE_TIMER(target_ue->t_ue_context_release);
|
||||
rv = s1ap_send_ue_context_release_command(
|
||||
target_ue, S1AP_Cause_PR_radioNetwork,
|
||||
S1AP_CauseRadioNetwork_handover_cancelled,
|
||||
|
|
|
@ -283,22 +283,47 @@ int s1ap_send_ue_context_release_command(
|
|||
int rv;
|
||||
ogs_pkbuf_t *s1apbuf = NULL;
|
||||
|
||||
ogs_assert(action != S1AP_UE_CTX_REL_INVALID_ACTION);
|
||||
|
||||
ogs_assert(enb_ue);
|
||||
enb_ue->ue_ctx_rel_action = action;
|
||||
|
||||
ogs_debug("[MME] UE Context release command");
|
||||
ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
|
||||
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
|
||||
ogs_debug(" Group[%d] Cause[%d] Action[%d] Delay[%d]",
|
||||
group, (int)cause, action, delay);
|
||||
|
||||
rv = s1ap_build_ue_context_release_command(&s1apbuf, enb_ue, group, cause);
|
||||
ogs_assert(rv == OGS_OK && s1apbuf);
|
||||
if (delay) {
|
||||
ogs_assert(action != S1AP_UE_CTX_REL_INVALID_ACTION);
|
||||
enb_ue->ue_ctx_rel_action = action;
|
||||
|
||||
rv = s1ap_delayed_send_to_enb_ue(enb_ue, s1apbuf, delay);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
ogs_debug(" Group[%d] Cause[%d] Action[%d] Delay[%d]",
|
||||
group, (int)cause, action, delay);
|
||||
|
||||
rv = s1ap_build_ue_context_release_command(
|
||||
&s1apbuf, enb_ue, group, cause);
|
||||
ogs_assert(rv == OGS_OK && s1apbuf);
|
||||
|
||||
rv = s1ap_delayed_send_to_enb_ue(enb_ue, s1apbuf, delay);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
} else {
|
||||
if (enb_ue->t_ue_context_release.pkbuf) {
|
||||
s1apbuf = enb_ue->t_ue_context_release.pkbuf;
|
||||
} else {
|
||||
ogs_assert(action != S1AP_UE_CTX_REL_INVALID_ACTION);
|
||||
enb_ue->ue_ctx_rel_action = action;
|
||||
|
||||
ogs_debug(" Group[%d] Cause[%d] Action[%d] Delay[%d]",
|
||||
group, (int)cause, action, delay);
|
||||
|
||||
rv = s1ap_build_ue_context_release_command(
|
||||
&s1apbuf, enb_ue, group, cause);
|
||||
ogs_assert(rv == OGS_OK && s1apbuf);
|
||||
}
|
||||
|
||||
enb_ue->t_ue_context_release.pkbuf = ogs_pkbuf_copy(s1apbuf);
|
||||
ogs_timer_start(enb_ue->t_ue_context_release.timer,
|
||||
mme_timer_cfg(MME_TIMER_UE_CONTEXT_RELEASE)->duration);
|
||||
|
||||
rv = s1ap_delayed_send_to_enb_ue(enb_ue, s1apbuf, 0);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
|
|
@ -192,6 +192,25 @@ void s1ap_state_operational(ogs_fsm_t *s, mme_event_t *e)
|
|||
ogs_assert(e->pkbuf);
|
||||
|
||||
ogs_assert(OGS_OK == s1ap_send_to_enb_ue(e->enb_ue, e->pkbuf));
|
||||
ogs_timer_delete(e->timer);
|
||||
break;
|
||||
case MME_TIMER_UE_CONTEXT_RELEASE:
|
||||
ogs_assert(e->enb_ue);
|
||||
if (e->enb_ue->t_ue_context_release.retry_count >=
|
||||
mme_timer_cfg(MME_TIMER_UE_CONTEXT_RELEASE)->max_count) {
|
||||
/* Paging failed */
|
||||
ogs_warn("[S1AP] UE Context Release failed. Stop Releasing");
|
||||
CLEAR_ENB_UE_TIMER(e->enb_ue->t_ue_context_release);
|
||||
|
||||
} else {
|
||||
e->enb_ue->t_ue_context_release.retry_count++;
|
||||
/*
|
||||
* If timeout, the saved pkbuf is used.
|
||||
* We don't have to set function parameter.
|
||||
* So, we just set all parameters to 0
|
||||
*/
|
||||
s1ap_send_ue_context_release_command(e->enb_ue, 0, 0, 0, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ogs_error("Unknown timer[%s:%d]",
|
||||
|
|
Loading…
Reference in New Issue