mirror of
https://github.com/open5gs/open5gs.git
synced 2025-11-03 13:33:26 +00:00
Implicit S1 Release
This commit is contained in:
@@ -75,7 +75,8 @@ status_t mme_context_init()
|
|||||||
self.guti_ue_hash = hash_make();
|
self.guti_ue_hash = hash_make();
|
||||||
|
|
||||||
/* Timer value */
|
/* Timer value */
|
||||||
self.t3413_value = 2; /* Paging retry Timer: 2 secs */
|
self.t3413_value = 2; /* Paging retry timer: 2 secs */
|
||||||
|
self.s1_holding_timer_value = 30; /* S1 holding timer: 30 secs */
|
||||||
|
|
||||||
context_initialized = 1;
|
context_initialized = 1;
|
||||||
|
|
||||||
@@ -1718,6 +1719,12 @@ enb_ue_t* enb_ue_add(mme_enb_t *enb)
|
|||||||
sizeof(enb_ue->mme_ue_s1ap_id), enb_ue);
|
sizeof(enb_ue->mme_ue_s1ap_id), enb_ue);
|
||||||
list_append(&enb->enb_ue_list, enb_ue);
|
list_append(&enb->enb_ue_list, enb_ue);
|
||||||
|
|
||||||
|
/* Create S1 holding timer */
|
||||||
|
enb_ue->holding_timer = timer_create(&self.tm_service,
|
||||||
|
MME_EVT_S1AP_S1_HOLDING_TIMER, self.s1_holding_timer_value * 1000);
|
||||||
|
d_assert(enb_ue->holding_timer, return NULL, "Null param");
|
||||||
|
timer_set_param1(enb_ue->holding_timer, enb_ue->index);
|
||||||
|
|
||||||
return enb_ue;
|
return enb_ue;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1730,10 +1737,19 @@ unsigned int enb_ue_count()
|
|||||||
|
|
||||||
status_t enb_ue_remove(enb_ue_t *enb_ue)
|
status_t enb_ue_remove(enb_ue_t *enb_ue)
|
||||||
{
|
{
|
||||||
|
status_t rv;
|
||||||
|
|
||||||
d_assert(self.mme_ue_s1ap_id_hash, return CORE_ERROR, "Null param");
|
d_assert(self.mme_ue_s1ap_id_hash, return CORE_ERROR, "Null param");
|
||||||
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
||||||
d_assert(enb_ue->enb, return CORE_ERROR, "Null param");
|
d_assert(enb_ue->enb, return CORE_ERROR, "Null param");
|
||||||
|
|
||||||
|
/* De-associate S1 with NAS/EMM */
|
||||||
|
rv = enb_ue_deassociate(enb_ue);
|
||||||
|
d_assert(rv == CORE_OK,,);
|
||||||
|
|
||||||
|
/* Delete All Timers */
|
||||||
|
tm_delete(enb_ue->holding_timer);
|
||||||
|
|
||||||
list_remove(&enb_ue->enb->enb_ue_list, enb_ue);
|
list_remove(&enb_ue->enb->enb_ue_list, enb_ue);
|
||||||
hash_set(self.mme_ue_s1ap_id_hash, &enb_ue->mme_ue_s1ap_id,
|
hash_set(self.mme_ue_s1ap_id_hash, &enb_ue->mme_ue_s1ap_id,
|
||||||
sizeof(enb_ue->mme_ue_s1ap_id), NULL);
|
sizeof(enb_ue->mme_ue_s1ap_id), NULL);
|
||||||
@@ -1840,7 +1856,7 @@ mme_ue_t* mme_ue_add(enb_ue_t *enb_ue)
|
|||||||
|
|
||||||
mme_self()->sgw = list_next(mme_self()->sgw);
|
mme_self()->sgw = list_next(mme_self()->sgw);
|
||||||
|
|
||||||
/* Create t3413 timer */
|
/* Create paging retry timer */
|
||||||
mme_ue->t3413 = timer_create(&self.tm_service, MME_EVT_EMM_T3413,
|
mme_ue->t3413 = timer_create(&self.tm_service, MME_EVT_EMM_T3413,
|
||||||
self.t3413_value * 1000);
|
self.t3413_value * 1000);
|
||||||
d_assert(mme_ue->t3413, return NULL, "Null param");
|
d_assert(mme_ue->t3413, return NULL, "Null param");
|
||||||
@@ -1855,6 +1871,7 @@ mme_ue_t* mme_ue_add(enb_ue_t *enb_ue)
|
|||||||
|
|
||||||
status_t mme_ue_remove(mme_ue_t *mme_ue)
|
status_t mme_ue_remove(mme_ue_t *mme_ue)
|
||||||
{
|
{
|
||||||
|
status_t rv;
|
||||||
event_t e;
|
event_t e;
|
||||||
|
|
||||||
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
||||||
@@ -1895,6 +1912,9 @@ status_t mme_ue_remove(mme_ue_t *mme_ue)
|
|||||||
/* Delete All Timers */
|
/* Delete All Timers */
|
||||||
tm_delete(mme_ue->t3413);
|
tm_delete(mme_ue->t3413);
|
||||||
|
|
||||||
|
rv = mme_ue_deassociate(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK,,);
|
||||||
|
|
||||||
mme_sess_remove_all(mme_ue);
|
mme_sess_remove_all(mme_ue);
|
||||||
mme_pdn_remove_all(mme_ue);
|
mme_pdn_remove_all(mme_ue);
|
||||||
|
|
||||||
@@ -2172,17 +2192,19 @@ status_t mme_ue_associate_enb_ue(mme_ue_t *mme_ue, enb_ue_t *enb_ue)
|
|||||||
return CORE_OK;
|
return CORE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t mme_ue_deassociate_enb_ue(enb_ue_t *enb_ue)
|
status_t enb_ue_deassociate(enb_ue_t *enb_ue)
|
||||||
{
|
{
|
||||||
mme_ue_t *mme_ue = NULL;
|
|
||||||
|
|
||||||
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
||||||
mme_ue = enb_ue->mme_ue;
|
|
||||||
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
|
||||||
|
|
||||||
mme_ue->enb_ue = NULL;
|
|
||||||
enb_ue->mme_ue = NULL;
|
enb_ue->mme_ue = NULL;
|
||||||
|
|
||||||
|
return CORE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t mme_ue_deassociate(mme_ue_t *mme_ue)
|
||||||
|
{
|
||||||
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
||||||
|
mme_ue->enb_ue = NULL;
|
||||||
|
|
||||||
return CORE_OK;
|
return CORE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,8 @@ typedef struct _mme_context_t {
|
|||||||
c_uint8_t relative_capacity;
|
c_uint8_t relative_capacity;
|
||||||
|
|
||||||
/* Timer value */
|
/* Timer value */
|
||||||
c_uint32_t t3413_value; /* Paging retry timer */
|
c_uint32_t t3413_value; /* Paging retry timer value */
|
||||||
|
c_uint32_t s1_holding_timer_value; /* S1 holding timer value */
|
||||||
|
|
||||||
/* Generator for unique identification */
|
/* Generator for unique identification */
|
||||||
c_uint32_t mme_ue_s1ap_id; /* mme_ue_s1ap_id generator */
|
c_uint32_t mme_ue_s1ap_id; /* mme_ue_s1ap_id generator */
|
||||||
@@ -180,6 +181,23 @@ struct _enb_ue_t {
|
|||||||
#define S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL 3
|
#define S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL 3
|
||||||
c_uint8_t ue_ctx_rel_action;
|
c_uint8_t ue_ctx_rel_action;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* S1 holding timer
|
||||||
|
*
|
||||||
|
* When eNodeB sends Attach Request, TAU Request, Service Request repeatly,
|
||||||
|
* S1(enb_ue_t) context is repeatly created.
|
||||||
|
*
|
||||||
|
* NAS(mme_ue_t) context is associated with last created S1(enb_ue_t)
|
||||||
|
* context, and older S1(enb_ue_t) context might not be freed.
|
||||||
|
*
|
||||||
|
* If NAS(mme_ue_t) has already been associated with
|
||||||
|
* older S1(enb_ue_t) context, the holding timer(30secs) is started.
|
||||||
|
* Newly associated S1(enb_ue_t) context holding timer is stopped.
|
||||||
|
*
|
||||||
|
* If the holding timer expires, S1(enb_ue_t) context will be deleted.
|
||||||
|
*/
|
||||||
|
tm_block_id holding_timer;
|
||||||
|
|
||||||
/* Related Context */
|
/* Related Context */
|
||||||
mme_enb_t *enb;
|
mme_enb_t *enb;
|
||||||
mme_ue_t *mme_ue;
|
mme_ue_t *mme_ue;
|
||||||
@@ -509,19 +527,16 @@ CORE_DECLARE(status_t) mme_ue_set_imsi(
|
|||||||
*
|
*
|
||||||
* o RECV Initial Context Setup Failure in EMM Registered State
|
* o RECV Initial Context Setup Failure in EMM Registered State
|
||||||
* ### MME_UE_DEASSOCIATE_ENB_UE() ###
|
* ### MME_UE_DEASSOCIATE_ENB_UE() ###
|
||||||
* ### MME_UE_ECM_IDLE() ###
|
|
||||||
* ### ENB_UE_REMOVE() ###
|
* ### ENB_UE_REMOVE() ###
|
||||||
|
* ### MME_UE_DEASSOCIATE() ###
|
||||||
*
|
*
|
||||||
* o SEND UE Context Release Command with NO_ACTION
|
* o SEND UE Context Release Command with NO_ACTION
|
||||||
* - RECV UE Context Release Complete
|
* - RECV UE Context Release Complete
|
||||||
* ### MME_UE_DEASSOCIATE_ENB_UE() ###
|
|
||||||
* ### MME_UE_ECM_IDLE() ###
|
|
||||||
* ### ENB_UE_REMOVE() ###
|
* ### ENB_UE_REMOVE() ###
|
||||||
|
* ### MME_UE_DEASSOCIATE() ###
|
||||||
*
|
*
|
||||||
* o SEND UE Context Release Command with REMOVE_MME_UE_CONTEXT
|
* o SEND UE Context Release Command with REMOVE_MME_UE_CONTEXT
|
||||||
* - RECV UE Context Release Complete
|
* - RECV UE Context Release Complete
|
||||||
* ### MME_UE_DEASSOCIATE_ENB_UE() ###
|
|
||||||
* ### MME_UE_ECM_IDLE() ###
|
|
||||||
* ### ENB_UE_REMOVE() ###
|
* ### ENB_UE_REMOVE() ###
|
||||||
* ### MME_UE_REMOVE() ###
|
* ### MME_UE_REMOVE() ###
|
||||||
*
|
*
|
||||||
@@ -553,7 +568,8 @@ CORE_DECLARE(status_t) mme_ue_set_imsi(
|
|||||||
*/
|
*/
|
||||||
CORE_DECLARE(status_t) mme_ue_associate_enb_ue(
|
CORE_DECLARE(status_t) mme_ue_associate_enb_ue(
|
||||||
mme_ue_t *mme_ue, enb_ue_t *enb_ue);
|
mme_ue_t *mme_ue, enb_ue_t *enb_ue);
|
||||||
CORE_DECLARE(status_t) mme_ue_deassociate_enb_ue(enb_ue_t *enb_ue);
|
CORE_DECLARE(status_t) enb_ue_deassociate(enb_ue_t *enb_ue);
|
||||||
|
CORE_DECLARE(status_t) mme_ue_deassociate(mme_ue_t *mme_ue);
|
||||||
CORE_DECLARE(status_t) source_ue_associate_target_ue(
|
CORE_DECLARE(status_t) source_ue_associate_target_ue(
|
||||||
enb_ue_t *source_ue, enb_ue_t *target_ue);
|
enb_ue_t *source_ue, enb_ue_t *target_ue);
|
||||||
CORE_DECLARE(status_t) source_ue_deassociate_target_ue(enb_ue_t *enb_ue);
|
CORE_DECLARE(status_t) source_ue_deassociate_target_ue(enb_ue_t *enb_ue);
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ char* mme_event_get_name(event_t *e)
|
|||||||
case MME_EVT_S1AP_LO_ACCEPT:
|
case MME_EVT_S1AP_LO_ACCEPT:
|
||||||
return "MME_EVT_S1AP_LO_ACCEPT";
|
return "MME_EVT_S1AP_LO_ACCEPT";
|
||||||
case MME_EVT_S1AP_LO_CONNREFUSED:
|
case MME_EVT_S1AP_LO_CONNREFUSED:
|
||||||
return"MME_EVT_S1AP_LO_CONNREFUSED";
|
return "MME_EVT_S1AP_LO_CONNREFUSED";
|
||||||
|
case MME_EVT_S1AP_S1_HOLDING_TIMER:
|
||||||
|
return "MME_EVT_S1AP_S1_HOLDING_TIMER";
|
||||||
|
|
||||||
case MME_EVT_EMM_MESSAGE:
|
case MME_EVT_EMM_MESSAGE:
|
||||||
return "MME_EVT_EMM_MESSAGE";
|
return "MME_EVT_EMM_MESSAGE";
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ typedef enum {
|
|||||||
MME_EVT_S1AP_DELAYED_SEND,
|
MME_EVT_S1AP_DELAYED_SEND,
|
||||||
MME_EVT_S1AP_LO_ACCEPT,
|
MME_EVT_S1AP_LO_ACCEPT,
|
||||||
MME_EVT_S1AP_LO_CONNREFUSED,
|
MME_EVT_S1AP_LO_CONNREFUSED,
|
||||||
|
MME_EVT_S1AP_S1_HOLDING_TIMER,
|
||||||
|
|
||||||
MME_EVT_EMM_MESSAGE,
|
MME_EVT_EMM_MESSAGE,
|
||||||
MME_EVT_EMM_T3413,
|
MME_EVT_EMM_T3413,
|
||||||
|
|||||||
@@ -212,6 +212,36 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||||||
tm_delete(timer);
|
tm_delete(timer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MME_EVT_S1AP_S1_HOLDING_TIMER:
|
||||||
|
{
|
||||||
|
enb_ue_t *enb_ue = NULL;
|
||||||
|
mme_ue_t *mme_ue = NULL;
|
||||||
|
|
||||||
|
enb_ue = enb_ue_find(event_get_param1(e));
|
||||||
|
d_assert(enb_ue, break, "No ENB UE context");
|
||||||
|
d_warn("Implicit S1 release");
|
||||||
|
d_warn(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
|
||||||
|
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
|
||||||
|
|
||||||
|
mme_ue = enb_ue->mme_ue;
|
||||||
|
d_assert(mme_ue, break, "No MME UE context");
|
||||||
|
d_warn("Associated NAS/EMM");
|
||||||
|
d_warn(" GUTI[G:%d,C:%d,M_TMSI:0x%x] IMSI[%s]",
|
||||||
|
mme_ue->guti.mme_gid,
|
||||||
|
mme_ue->guti.mme_code,
|
||||||
|
mme_ue->guti.m_tmsi,
|
||||||
|
MME_UE_HAVE_IMSI(mme_ue) ? mme_ue->imsi_bcd : "Unknown");
|
||||||
|
if (mme_ue->enb_ue)
|
||||||
|
d_warn(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
|
||||||
|
mme_ue->enb_ue->enb_ue_s1ap_id,
|
||||||
|
mme_ue->enb_ue->mme_ue_s1ap_id);
|
||||||
|
else
|
||||||
|
d_warn(" No Associated S1");
|
||||||
|
|
||||||
|
rv = enb_ue_remove(enb_ue);
|
||||||
|
d_assert(rv == CORE_OK,,);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MME_EVT_EMM_MESSAGE:
|
case MME_EVT_EMM_MESSAGE:
|
||||||
{
|
{
|
||||||
nas_message_t message;
|
nas_message_t message;
|
||||||
@@ -257,16 +287,21 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||||||
"nas_security_decode failed");
|
"nas_security_decode failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if 0 /* FIXME : how can we release S1(enb_ue_t) context ? */
|
|
||||||
|
/* If NAS(mme_ue_t) has already been associated with
|
||||||
|
* older S1(enb_ue_t) context, the holding timer(30secs)
|
||||||
|
* is started. Newly associated S1(enb_ue_t) context
|
||||||
|
* holding timer is stopped. */
|
||||||
if (mme_ue->enb_ue)
|
if (mme_ue->enb_ue)
|
||||||
{
|
{
|
||||||
d_warn("Implicitly S1 released");
|
d_warn("Start S1 holding timer");
|
||||||
d_warn(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
|
d_warn(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
|
||||||
mme_ue->enb_ue->enb_ue_s1ap_id,
|
mme_ue->enb_ue->enb_ue_s1ap_id,
|
||||||
mme_ue->enb_ue->mme_ue_s1ap_id);
|
mme_ue->enb_ue->mme_ue_s1ap_id);
|
||||||
enb_ue_remove(mme_ue->enb_ue);
|
tm_start(mme_ue->enb_ue->holding_timer);
|
||||||
}
|
}
|
||||||
#endif
|
tm_stop(enb_ue->holding_timer);
|
||||||
|
|
||||||
mme_ue_associate_enb_ue(mme_ue, enb_ue);
|
mme_ue_associate_enb_ue(mme_ue, enb_ue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -156,16 +156,21 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message)
|
|||||||
mme_ue->guti.m_tmsi,
|
mme_ue->guti.m_tmsi,
|
||||||
MME_UE_HAVE_IMSI(mme_ue)
|
MME_UE_HAVE_IMSI(mme_ue)
|
||||||
? mme_ue->imsi_bcd : "Unknown");
|
? mme_ue->imsi_bcd : "Unknown");
|
||||||
#if 0 /* FIXME : how can we release S1(enb_ue_t) context ? */
|
|
||||||
|
/* If NAS(mme_ue_t) has already been associated with
|
||||||
|
* older S1(enb_ue_t) context, the holding timer(30secs)
|
||||||
|
* is started. Newly associated S1(enb_ue_t) context
|
||||||
|
* holding timer is stopped. */
|
||||||
if (mme_ue->enb_ue)
|
if (mme_ue->enb_ue)
|
||||||
{
|
{
|
||||||
d_warn("Implicitly S1 released");
|
d_warn("Start S1 holding timer");
|
||||||
d_warn(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
|
d_warn(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
|
||||||
mme_ue->enb_ue->enb_ue_s1ap_id,
|
mme_ue->enb_ue->enb_ue_s1ap_id,
|
||||||
mme_ue->enb_ue->mme_ue_s1ap_id);
|
mme_ue->enb_ue->mme_ue_s1ap_id);
|
||||||
enb_ue_remove(mme_ue->enb_ue);
|
tm_start(mme_ue->enb_ue->holding_timer);
|
||||||
}
|
}
|
||||||
#endif
|
tm_stop(enb_ue->holding_timer);
|
||||||
|
|
||||||
mme_ue_associate_enb_ue(mme_ue, enb_ue);
|
mme_ue_associate_enb_ue(mme_ue, enb_ue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -392,12 +397,11 @@ void s1ap_handle_initial_context_setup_failure(
|
|||||||
|
|
||||||
#if 1 /* Implicit Release */
|
#if 1 /* Implicit Release */
|
||||||
d_trace(5, " Implicit Release\n");
|
d_trace(5, " Implicit Release\n");
|
||||||
rv = mme_ue_deassociate_enb_ue(enb_ue);
|
|
||||||
d_assert(rv == CORE_OK,, "mme_ue_deassociate_enb_ue() failed");
|
|
||||||
|
|
||||||
rv = enb_ue_remove(enb_ue);
|
rv = enb_ue_remove(enb_ue);
|
||||||
d_assert(rv == CORE_OK,, "enb_ue_remove() failed");
|
d_assert(rv == CORE_OK,, "enb_ue_remove() failed");
|
||||||
|
|
||||||
|
rv = mme_ue_deassociate(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK,, "enb_ue_remove() failed");
|
||||||
#else /* Explicit Release */
|
#else /* Explicit Release */
|
||||||
|
|
||||||
d_trace(5, " Explicit Release\n");
|
d_trace(5, " Explicit Release\n");
|
||||||
@@ -669,19 +673,17 @@ void s1ap_handle_ue_context_release_complete(
|
|||||||
case S1AP_UE_CTX_REL_NO_ACTION:
|
case S1AP_UE_CTX_REL_NO_ACTION:
|
||||||
{
|
{
|
||||||
d_trace(5, " No Action\n");
|
d_trace(5, " No Action\n");
|
||||||
rv = mme_ue_deassociate_enb_ue(enb_ue);
|
|
||||||
d_assert(rv == CORE_OK,, "mme_ue_deassociate_enb_ue() failed");
|
|
||||||
|
|
||||||
rv = enb_ue_remove(enb_ue);
|
rv = enb_ue_remove(enb_ue);
|
||||||
d_assert(rv == CORE_OK,, "enb_ue_remove() failed");
|
d_assert(rv == CORE_OK,, "enb_ue_remove() failed");
|
||||||
|
|
||||||
|
d_assert(mme_ue,,);
|
||||||
|
rv = mme_ue_deassociate(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK,, "enb_ue_remove() failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case S1AP_UE_CTX_REL_REMOVE_MME_UE_CONTEXT:
|
case S1AP_UE_CTX_REL_REMOVE_MME_UE_CONTEXT:
|
||||||
{
|
{
|
||||||
d_trace(5, " Action: UE(mme) context\n");
|
d_trace(5, " Action: UE(mme) context\n");
|
||||||
rv = mme_ue_deassociate_enb_ue(enb_ue);
|
|
||||||
d_assert(rv == CORE_OK,, "mme_ue_deassociate_enb_ue() failed");
|
|
||||||
|
|
||||||
rv = enb_ue_remove(enb_ue);
|
rv = enb_ue_remove(enb_ue);
|
||||||
d_assert(rv == CORE_OK,, "enb_ue_removeI() failed");
|
d_assert(rv == CORE_OK,, "enb_ue_removeI() failed");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user