forked from acouzens/open5gs
ECM_IDLE/CONNECTED is introduced
This commit is contained in:
parent
60cfbed747
commit
ae6e747e52
|
@ -1737,7 +1737,6 @@ unsigned int enb_ue_count()
|
|||
|
||||
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(enb_ue, return CORE_ERROR, "Null param");
|
||||
d_assert(enb_ue->enb, return CORE_ERROR, "Null param");
|
||||
|
@ -1746,9 +1745,6 @@ status_t enb_ue_remove(enb_ue_t *enb_ue)
|
|||
hash_set(self.mme_ue_s1ap_id_hash, &enb_ue->mme_ue_s1ap_id,
|
||||
sizeof(enb_ue->mme_ue_s1ap_id), NULL);
|
||||
|
||||
rv = source_ue_deassociate_target_ue(enb_ue);
|
||||
d_assert(rv == CORE_OK, return CORE_ERROR, "Null param");
|
||||
|
||||
index_free(&enb_ue_pool, enb_ue);
|
||||
|
||||
return CORE_OK;
|
||||
|
@ -1906,8 +1902,6 @@ status_t mme_ue_remove(mme_ue_t *mme_ue)
|
|||
mme_sess_remove_all(mme_ue);
|
||||
mme_pdn_remove_all(mme_ue);
|
||||
|
||||
mme_ue_deassociate_enb_ue(mme_ue->enb_ue);
|
||||
|
||||
index_free(&mme_ue_pool, mme_ue);
|
||||
|
||||
return CORE_OK;
|
||||
|
@ -2171,12 +2165,6 @@ status_t mme_ue_set_imsi(mme_ue_t *mme_ue, c_int8_t *imsi_bcd)
|
|||
return CORE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* S1AP Initial UE-Message : S-TMSI
|
||||
* NAS ATTACH_REQUEST : IMSI, GUTI
|
||||
* NAS TAU_REQUEST : GUTI
|
||||
* S1AP Handover Notification
|
||||
*/
|
||||
status_t mme_ue_associate_enb_ue(mme_ue_t *mme_ue, enb_ue_t *enb_ue)
|
||||
{
|
||||
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
||||
|
@ -2188,15 +2176,6 @@ status_t mme_ue_associate_enb_ue(mme_ue_t *mme_ue, enb_ue_t *enb_ue)
|
|||
return CORE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* mme_ue_remove()
|
||||
*
|
||||
* Note : should not call in enb_ue_remove()
|
||||
*
|
||||
* When mme_ue is removed, enb_ue->mme_ue must be NULL.
|
||||
* However, when enb_ue is removed, mme_ue->enb_ue need not be NULL.
|
||||
* mme_ue->enb_ue will be updated again when enb_ue is added.
|
||||
*/
|
||||
status_t mme_ue_deassociate_enb_ue(enb_ue_t *enb_ue)
|
||||
{
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
@ -2211,9 +2190,6 @@ status_t mme_ue_deassociate_enb_ue(enb_ue_t *enb_ue)
|
|||
return CORE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* S1AP Handover Required
|
||||
*/
|
||||
status_t source_ue_associate_target_ue(
|
||||
enb_ue_t *source_ue, enb_ue_t *target_ue)
|
||||
{
|
||||
|
@ -2231,13 +2207,6 @@ status_t source_ue_associate_target_ue(
|
|||
return CORE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* enb_ue_remove()
|
||||
*
|
||||
* enb_ue->mme_ue->enb_ue should not be set to NULL.
|
||||
* This is because enb_ue is not known as source_ue or target_ue.
|
||||
* Therefore, when enb_ue is removed, leave enb_ue->mme_ue->enb_ue as is.
|
||||
*/
|
||||
status_t source_ue_deassociate_target_ue(enb_ue_t *enb_ue)
|
||||
{
|
||||
enb_ue_t *source_ue = NULL;
|
||||
|
|
|
@ -285,7 +285,11 @@ struct _mme_ue_t {
|
|||
c_uint8_t ebi; /* EPS Bearer ID generator */
|
||||
list_t sess_list;
|
||||
|
||||
/* eNB UE context */
|
||||
#define MME_UE_ECM_IDLE(__mME) \
|
||||
((__mME) && ((__mME)->enb_ue == NULL))
|
||||
#define MME_UE_ECM_CONNECTED(__mME) \
|
||||
((__mME) && ((__mME)->enb_ue != NULL))
|
||||
/* S1 UE context */
|
||||
enb_ue_t *enb_ue;
|
||||
|
||||
/* Save PDN Connectivity Request */
|
||||
|
@ -495,6 +499,58 @@ CORE_DECLARE(mme_ue_t*) mme_ue_find_by_teid(c_uint32_t teid);
|
|||
CORE_DECLARE(mme_ue_t*) mme_ue_find_by_message(nas_message_t *message);
|
||||
CORE_DECLARE(status_t) mme_ue_set_imsi(
|
||||
mme_ue_t *mme_ue, c_int8_t *imsi_bcd);
|
||||
|
||||
/*
|
||||
* o RECV Initial UE-Message : S-TMSI
|
||||
* o RECV Attach Request : IMSI, GUTI
|
||||
* o RECV TAU Request : GUTI
|
||||
* ### MME_UE_ASSOCIATE_ENB_UE() ###
|
||||
* ### MME_UE_ECM_CONNECTED() ###
|
||||
*
|
||||
* o RECV Initial Context Setup Failure in EMM Registered State
|
||||
* ### MME_UE_DEASSOCIATE_ENB_UE() ###
|
||||
* ### MME_UE_ECM_IDLE() ###
|
||||
* ### ENB_UE_REMOVE() ###
|
||||
*
|
||||
* o SEND UE Context Release Command with NO_ACTION
|
||||
* - RECV UE Context Release Complete
|
||||
* ### MME_UE_DEASSOCIATE_ENB_UE() ###
|
||||
* ### MME_UE_ECM_IDLE() ###
|
||||
* ### ENB_UE_REMOVE() ###
|
||||
*
|
||||
* o SEND UE Context Release Command with REMOVE_MME_UE_CONTEXT
|
||||
* - RECV UE Context Release Complete
|
||||
* ### MME_UE_DEASSOCIATE_ENB_UE() ###
|
||||
* ### MME_UE_ECM_IDLE() ###
|
||||
* ### ENB_UE_REMOVE() ###
|
||||
* ### MME_UE_REMOVE() ###
|
||||
*
|
||||
*
|
||||
* o RECV Handover Required
|
||||
* ### SOURCE_UE_ASSOCIATE_TARGET_UE() ####
|
||||
* - SEND Handover Request
|
||||
*
|
||||
* o RECV Handover Notify
|
||||
* ### MME_UE_ASSOCIATE_ENB_UE(TARGET) ###
|
||||
* ### MME_UE_ECM_CONNECTED(TARGET) ###
|
||||
* - Modify Bearer Request/Response
|
||||
* - UE Context Release Command/Complete
|
||||
* ### SOURCE_UE_DEASSOCIATE_TARGET_UE() ####
|
||||
* ### ENB_UE_REMOVE() ####
|
||||
* - Delete Indirect Data Forwarding Tunnel Request/Response
|
||||
*
|
||||
* o RECV Handover Cancel
|
||||
* - UE Context Release Command/Complete
|
||||
* ### SOURCE_UE_DEASSOCIATE_TARGET_UE() ####
|
||||
* ### ENB_UE_REMOVE() ####
|
||||
* - Delete Indirect Data Forwarding Tunnel Request/Response
|
||||
*
|
||||
* o RECV Handover Failure
|
||||
* - UE Context Release Command/Complete
|
||||
* ### SOURCE_UE_DEASSOCIATE_TARGET_UE() ####
|
||||
* ### ENB_UE_REMOVE() ####
|
||||
* - Delete Indirect Data Forwarding Tunnel Request/Response
|
||||
*/
|
||||
CORE_DECLARE(status_t) mme_ue_associate_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);
|
||||
|
|
|
@ -269,6 +269,7 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
#endif
|
||||
mme_ue_associate_enb_ue(mme_ue, enb_ue);
|
||||
}
|
||||
else
|
||||
|
||||
d_assert(mme_ue, pkbuf_free(pkbuf); break, "No MME UE context");
|
||||
d_assert(FSM_STATE(&mme_ue->sm), pkbuf_free(pkbuf); break,
|
||||
|
@ -478,7 +479,21 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
mme_s11_handle_downlink_data_notification(
|
||||
xact, mme_ue, &message.downlink_data_notification);
|
||||
|
||||
if (mme_ue->enb_ue == NULL)
|
||||
/*
|
||||
* 5.3.4.2 in Spec 23.401
|
||||
* Under certain conditions, the current UE triggered Service Request
|
||||
* procedure can cause unnecessary Downlink Packet Notification messages
|
||||
* which increase the load of the MME.
|
||||
*
|
||||
* This can occur when uplink data sent in step 6 causes a response
|
||||
* on the downlink which arrives at the Serving GW before the Modify Bearer
|
||||
* Request message, step 8. This data cannot be forwarded from the Serving GW
|
||||
* to the eNodeB and hence it triggers a Downlink Data Notification message.
|
||||
*
|
||||
* If the MME receives a Downlink Data Notification after step 2 and
|
||||
* before step 9, the MME shall not send S1 interface paging messages
|
||||
*/
|
||||
if (MME_UE_ECM_IDLE(mme_ue))
|
||||
{
|
||||
s1ap_handle_paging(mme_ue);
|
||||
/* Start T3413 */
|
||||
|
|
|
@ -105,6 +105,7 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message)
|
|||
S1ap_CellIdentity_t *cell_ID = NULL;
|
||||
|
||||
d_assert(enb, return, "Null param");
|
||||
d_assert(enb->sock, return, "Null param");
|
||||
|
||||
ies = &message->s1ap_InitialUEMessage_IEs;
|
||||
d_assert(ies, return, "Null param");
|
||||
|
@ -194,7 +195,6 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message)
|
|||
sizeof(enb_ue->nas.e_cgi.cell_id));
|
||||
enb_ue->nas.e_cgi.cell_id = (ntohl(enb_ue->nas.e_cgi.cell_id) >> 4);
|
||||
|
||||
d_assert(enb->sock, enb_ue_remove(enb_ue); return,);
|
||||
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d] TAC[%d]\n",
|
||||
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id, enb_ue->nas.tai.tac);
|
||||
|
||||
|
@ -371,16 +371,51 @@ void s1ap_handle_initial_context_setup_failure(
|
|||
if (FSM_CHECK(&mme_ue->sm, emm_state_registered))
|
||||
{
|
||||
d_trace(5, " Registered State\n");
|
||||
|
||||
/*
|
||||
* 19.2.2.3 in Spec 36.300
|
||||
*
|
||||
* In case of failure, eNB and MME behaviours are not mandated.
|
||||
*
|
||||
* Both implicit release (local release at each node) and
|
||||
* explicit release (MME-initiated UE Context Release procedure)
|
||||
* may in principle be adopted. The eNB should ensure
|
||||
* that no hanging resources remain at the eNB.
|
||||
*/
|
||||
|
||||
#if 0 /* FIXME : Does it needed? */
|
||||
rv = nas_send_service_reject(mme_ue,
|
||||
EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
|
||||
d_assert(rv == CORE_OK,,
|
||||
"nas_send_service_reject() failed");
|
||||
#endif
|
||||
|
||||
#if 1 /* Implicitly Detach */
|
||||
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);
|
||||
d_assert(rv == CORE_OK,, "enb_ue_remove() failed");
|
||||
|
||||
#else /* Explicitly Detach */
|
||||
|
||||
d_trace(5, " Explicit Release\n");
|
||||
#if 1 /* NAS Cause : Detach */
|
||||
d_trace(5, " NAS-CAUSE: DETACH\n");
|
||||
rv = s1ap_send_ue_context_release_command(enb_ue,
|
||||
S1ap_Cause_PR_nas, S1ap_CauseNas_detach,
|
||||
S1AP_UE_CTX_REL_NO_ACTION, 0);
|
||||
d_assert(rv == CORE_OK,, "s1ap send error");
|
||||
#else /* NAS Cause : Normal Release */
|
||||
d_trace(5, " NAS-CAUSE: Normal Release\n");
|
||||
rv = s1ap_send_ue_context_release_command(enb_ue,
|
||||
S1ap_Cause_PR_nas, S1ap_CauseNas_normal_release,
|
||||
S1AP_UE_CTX_REL_NO_ACTION, 0);
|
||||
d_assert(rv == CORE_OK,, "s1ap send error");
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -611,7 +646,6 @@ void s1ap_handle_ue_context_release_complete(
|
|||
status_t rv;
|
||||
char buf[CORE_ADDRSTRLEN];
|
||||
|
||||
c_uint8_t ue_ctx_rel_action = 0;
|
||||
enb_ue_t *enb_ue = NULL;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
S1ap_UEContextReleaseComplete_IEs_t *ies = NULL;
|
||||
|
@ -625,44 +659,60 @@ void s1ap_handle_ue_context_release_complete(
|
|||
|
||||
enb_ue = enb_ue_find_by_mme_ue_s1ap_id(ies->mme_ue_s1ap_id);
|
||||
d_assert(enb_ue, return, "No UE Context[%d]", ies->mme_ue_s1ap_id);
|
||||
mme_ue = enb_ue->mme_ue;
|
||||
|
||||
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
||||
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
|
||||
|
||||
ue_ctx_rel_action = enb_ue->ue_ctx_rel_action;
|
||||
enb_ue->ue_ctx_rel_action = S1AP_UE_CTX_REL_INVALID_ACTION;
|
||||
mme_ue = enb_ue->mme_ue;
|
||||
|
||||
enb_ue_remove(enb_ue);
|
||||
|
||||
if (mme_ue)
|
||||
switch (enb_ue->ue_ctx_rel_action)
|
||||
{
|
||||
switch (ue_ctx_rel_action)
|
||||
case S1AP_UE_CTX_REL_NO_ACTION:
|
||||
{
|
||||
case S1AP_UE_CTX_REL_NO_ACTION:
|
||||
{
|
||||
d_trace(5, " No Action\n");
|
||||
break;
|
||||
}
|
||||
case S1AP_UE_CTX_REL_REMOVE_MME_UE_CONTEXT:
|
||||
{
|
||||
d_trace(5, " Action: UE(mme) context\n");
|
||||
mme_ue_remove(mme_ue);
|
||||
break;
|
||||
}
|
||||
case S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL:
|
||||
{
|
||||
d_trace(5, " Action: Delete indirect tunnel\n");
|
||||
rv = mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
|
||||
mme_ue);
|
||||
d_assert(rv == CORE_OK, return, "gtp send error");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_assert(0, return, "Invalid action[%d]", ue_ctx_rel_action);
|
||||
break;
|
||||
}
|
||||
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);
|
||||
d_assert(rv == CORE_OK,, "enb_ue_remove() failed");
|
||||
break;
|
||||
}
|
||||
case S1AP_UE_CTX_REL_REMOVE_MME_UE_CONTEXT:
|
||||
{
|
||||
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);
|
||||
d_assert(rv == CORE_OK,, "enb_ue_removeI() failed");
|
||||
|
||||
d_assert(mme_ue,,);
|
||||
rv = mme_ue_remove(mme_ue);
|
||||
d_assert(rv == CORE_OK,, "mme_ue_remove() failed");
|
||||
break;
|
||||
}
|
||||
case S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL:
|
||||
{
|
||||
d_trace(5, " Action: Delete indirect tunnel\n");
|
||||
|
||||
rv = source_ue_deassociate_target_ue(enb_ue);
|
||||
d_assert(rv == CORE_OK,,
|
||||
"source_ue_deassociate_target_ue() failed");
|
||||
|
||||
rv = enb_ue_remove(enb_ue);
|
||||
d_assert(rv == CORE_OK,, "enb_ue_removeI() failed");
|
||||
|
||||
d_assert(mme_ue,,);
|
||||
rv = mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
|
||||
mme_ue);
|
||||
d_assert(rv == CORE_OK,,
|
||||
"mme_gtp_send_delete_indirect_data_forwarding_tunnel_request()"
|
||||
"failed");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_assert(0,, "Invalid Action[%d]", enb_ue->ue_ctx_rel_action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -424,11 +424,10 @@ status_t s1ap_send_handover_request(
|
|||
d_assert(rv == CORE_OK, return CORE_ERROR,);
|
||||
|
||||
rv = s1ap_build_handover_request(&s1apbuf, mme_ue, target_ue, ies);
|
||||
d_assert(rv == CORE_OK && s1apbuf,
|
||||
enb_ue_remove(target_ue); return CORE_ERROR, "s1ap build error");
|
||||
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
|
||||
|
||||
rv = s1ap_send_to_enb(target_enb, s1apbuf);
|
||||
d_assert(rv == CORE_OK, enb_ue_remove(target_ue), "s1ap send error");
|
||||
d_assert(rv == CORE_OK,, "s1ap send error");
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue