forked from acouzens/open5gs
tracking area update for multiple MME
This commit is contained in:
parent
fc974bb707
commit
5455642098
|
@ -15,6 +15,7 @@
|
||||||
#include "s1ap_build.h"
|
#include "s1ap_build.h"
|
||||||
#include "s1ap_path.h"
|
#include "s1ap_path.h"
|
||||||
#include "nas_path.h"
|
#include "nas_path.h"
|
||||||
|
#include "mme_fd_path.h"
|
||||||
|
|
||||||
#include "mme_s11_build.h"
|
#include "mme_s11_build.h"
|
||||||
#include "mme_gtp_path.h"
|
#include "mme_gtp_path.h"
|
||||||
|
@ -24,7 +25,11 @@
|
||||||
void emm_handle_attach_request(
|
void emm_handle_attach_request(
|
||||||
mme_ue_t *mme_ue, nas_attach_request_t *attach_request)
|
mme_ue_t *mme_ue, nas_attach_request_t *attach_request)
|
||||||
{
|
{
|
||||||
|
status_t rv;
|
||||||
|
|
||||||
enb_ue_t *enb_ue = NULL;
|
enb_ue_t *enb_ue = NULL;
|
||||||
|
nas_eps_attach_type_t *eps_attach_type =
|
||||||
|
&attach_request->eps_attach_type;
|
||||||
nas_eps_mobile_identity_t *eps_mobile_identity =
|
nas_eps_mobile_identity_t *eps_mobile_identity =
|
||||||
&attach_request->eps_mobile_identity;
|
&attach_request->eps_mobile_identity;
|
||||||
nas_esm_message_container_t *esm_message_container =
|
nas_esm_message_container_t *esm_message_container =
|
||||||
|
@ -37,6 +42,18 @@ void emm_handle_attach_request(
|
||||||
d_assert(esm_message_container, return, "Null param");
|
d_assert(esm_message_container, return, "Null param");
|
||||||
d_assert(esm_message_container->length, return, "Null param");
|
d_assert(esm_message_container->length, return, "Null param");
|
||||||
|
|
||||||
|
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||||
|
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32,
|
||||||
|
mme_ue->kenb);
|
||||||
|
|
||||||
|
CLEAR_EPS_BEARER_ID(mme_ue);
|
||||||
|
CLEAR_PAGING_INFO(mme_ue);
|
||||||
|
|
||||||
|
/* Set EPS Attach Type */
|
||||||
|
memcpy(&mme_ue->nas_eps.attach, eps_attach_type,
|
||||||
|
sizeof(nas_eps_attach_type_t));
|
||||||
|
mme_ue->nas_eps.type = MME_UE_EPS_ATTACH_TYPE;
|
||||||
|
|
||||||
/* Store UE specific information */
|
/* Store UE specific information */
|
||||||
if (attach_request->presencemask &
|
if (attach_request->presencemask &
|
||||||
NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT)
|
NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT)
|
||||||
|
@ -112,6 +129,35 @@ void emm_handle_attach_request(
|
||||||
}
|
}
|
||||||
|
|
||||||
NAS_STORE_DATA(&mme_ue->pdn_connectivity_request, esm_message_container);
|
NAS_STORE_DATA(&mme_ue->pdn_connectivity_request, esm_message_container);
|
||||||
|
|
||||||
|
if (!MME_UE_HAVE_IMSI(mme_ue))
|
||||||
|
{
|
||||||
|
/* Unknown GUTI */
|
||||||
|
FSM_TRAN(&mme_ue->sm, &emm_state_identity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||||
|
{
|
||||||
|
rv = nas_send_emm_to_esm(mme_ue, &mme_ue->pdn_connectivity_request);
|
||||||
|
d_assert(rv == CORE_OK,, "nas_send_emm_to_esm failed");
|
||||||
|
FSM_TRAN(&mme_ue->sm, &emm_state_default_esm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (MME_HAVE_SGW_S11_PATH(mme_ue))
|
||||||
|
{
|
||||||
|
rv = mme_gtp_send_delete_all_sessions(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK, return,
|
||||||
|
"mme_gtp_send_delete_all_sessions failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mme_s6a_send_air(mme_ue);
|
||||||
|
}
|
||||||
|
FSM_TRAN(&mme_ue->sm, &emm_state_authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emm_handle_attach_complete(
|
void emm_handle_attach_complete(
|
||||||
|
@ -177,6 +223,8 @@ void emm_handle_attach_complete(
|
||||||
void emm_handle_identity_response(
|
void emm_handle_identity_response(
|
||||||
mme_ue_t *mme_ue, nas_identity_response_t *identity_response)
|
mme_ue_t *mme_ue, nas_identity_response_t *identity_response)
|
||||||
{
|
{
|
||||||
|
status_t rv;
|
||||||
|
|
||||||
nas_mobile_identity_t *mobile_identity = NULL;
|
nas_mobile_identity_t *mobile_identity = NULL;
|
||||||
enb_ue_t *enb_ue = NULL;
|
enb_ue_t *enb_ue = NULL;
|
||||||
|
|
||||||
|
@ -204,6 +252,29 @@ void emm_handle_identity_response(
|
||||||
{
|
{
|
||||||
d_warn("Not supported Identity type(%d)", mobile_identity->imsi.type);
|
d_warn("Not supported Identity type(%d)", mobile_identity->imsi.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d_assert(MME_UE_HAVE_IMSI(mme_ue), return, "No IMSI in IDENTITY_RESPONSE");
|
||||||
|
|
||||||
|
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||||
|
{
|
||||||
|
rv = nas_send_emm_to_esm(mme_ue, &mme_ue->pdn_connectivity_request);
|
||||||
|
d_assert(rv == CORE_OK, return, "nas_send_emm_to_esm failed");
|
||||||
|
FSM_TRAN(&mme_ue->sm, &emm_state_default_esm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (MME_HAVE_SGW_S11_PATH(mme_ue))
|
||||||
|
{
|
||||||
|
rv = mme_gtp_send_delete_all_sessions(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK, return,
|
||||||
|
"mme_gtp_send_delete_all_sessions failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mme_s6a_send_air(mme_ue);
|
||||||
|
}
|
||||||
|
FSM_TRAN(&mme_ue->sm, &emm_state_authentication);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emm_handle_authentication_response(mme_ue_t *mme_ue,
|
void emm_handle_authentication_response(mme_ue_t *mme_ue,
|
||||||
|
@ -229,6 +300,7 @@ void emm_handle_authentication_response(mme_ue_t *mme_ue,
|
||||||
void emm_handle_detach_request(
|
void emm_handle_detach_request(
|
||||||
mme_ue_t *mme_ue, nas_detach_request_from_ue_t *detach_request)
|
mme_ue_t *mme_ue, nas_detach_request_from_ue_t *detach_request)
|
||||||
{
|
{
|
||||||
|
status_t rv;
|
||||||
enb_ue_t *enb_ue = NULL;
|
enb_ue_t *enb_ue = NULL;
|
||||||
|
|
||||||
d_assert(detach_request, return, "Null param");
|
d_assert(detach_request, return, "Null param");
|
||||||
|
@ -260,22 +332,30 @@ void emm_handle_detach_request(
|
||||||
|
|
||||||
/* Save detach type */
|
/* Save detach type */
|
||||||
mme_ue->detach_type = detach_request->detach_type;
|
mme_ue->detach_type = detach_request->detach_type;
|
||||||
|
|
||||||
|
if (MME_HAVE_SGW_S11_PATH(mme_ue))
|
||||||
|
{
|
||||||
|
rv = mme_gtp_send_delete_all_sessions(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK, return,
|
||||||
|
"mme_gtp_send_delete_all_sessions failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emm_handle_detach_accept(mme_ue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emm_handle_detach_accept(mme_ue_t *mme_ue)
|
void emm_handle_detach_accept(mme_ue_t *mme_ue)
|
||||||
{
|
{
|
||||||
status_t rv;
|
status_t rv;
|
||||||
mme_enb_t *enb = NULL;
|
|
||||||
enb_ue_t *enb_ue = NULL;
|
enb_ue_t *enb_ue = NULL;
|
||||||
nas_message_t message;
|
nas_message_t message;
|
||||||
pkbuf_t *emmbuf = NULL, *s1apbuf = NULL;
|
pkbuf_t *emmbuf = NULL;
|
||||||
S1ap_Cause_t cause;
|
S1ap_Cause_t cause;
|
||||||
|
|
||||||
d_assert(mme_ue, return, "Null param");
|
d_assert(mme_ue, return, "Null param");
|
||||||
enb_ue = mme_ue->enb_ue;
|
enb_ue = mme_ue->enb_ue;
|
||||||
d_assert(enb_ue, return, "Null param");
|
d_assert(enb_ue, return, "Null param");
|
||||||
enb = enb_ue->enb;
|
|
||||||
d_assert(enb, return, "Null param");
|
|
||||||
|
|
||||||
/* reply with detach accept */
|
/* reply with detach accept */
|
||||||
if ((mme_ue->detach_type.switch_off & 0x1) == 0)
|
if ((mme_ue->detach_type.switch_off & 0x1) == 0)
|
||||||
|
@ -296,13 +376,11 @@ void emm_handle_detach_accept(mme_ue_t *mme_ue)
|
||||||
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME : delay is needed */
|
||||||
cause.present = S1ap_Cause_PR_nas;
|
cause.present = S1ap_Cause_PR_nas;
|
||||||
cause.choice.nas = S1ap_CauseNas_detach;
|
cause.choice.nas = S1ap_CauseNas_detach;
|
||||||
|
rv = s1ap_send_ue_context_release_commmand(enb_ue, &cause);
|
||||||
rv = s1ap_build_ue_context_release_commmand(&s1apbuf, enb_ue, &cause);
|
d_assert(rv == CORE_OK, , "s1ap send error");
|
||||||
d_assert(rv == CORE_OK && s1apbuf, return, "s1ap build error");
|
|
||||||
|
|
||||||
d_assert(s1ap_send_to_enb(enb, s1apbuf) == CORE_OK,, "s1ap send error");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void emm_handle_service_request(
|
void emm_handle_service_request(
|
||||||
|
@ -319,6 +397,12 @@ void emm_handle_service_request(
|
||||||
sess = mme_sess_first(mme_ue);
|
sess = mme_sess_first(mme_ue);
|
||||||
d_assert(sess, return, "Null param");
|
d_assert(sess, return, "Null param");
|
||||||
|
|
||||||
|
/* Update Kenb */
|
||||||
|
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||||
|
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32, mme_ue->kenb);
|
||||||
|
|
||||||
|
CLEAR_PAGING_INFO(mme_ue);
|
||||||
|
|
||||||
rv = s1ap_build_initial_context_setup_request(&s1apbuf, sess, NULL);
|
rv = s1ap_build_initial_context_setup_request(&s1apbuf, sess, NULL);
|
||||||
d_assert(rv == CORE_OK && s1apbuf, return, "s1ap build error");
|
d_assert(rv == CORE_OK && s1apbuf, return, "s1ap build error");
|
||||||
|
|
||||||
|
@ -336,6 +420,10 @@ void emm_handle_emm_status(mme_ue_t *mme_ue, nas_emm_status_t *emm_status)
|
||||||
void emm_handle_tau_request(
|
void emm_handle_tau_request(
|
||||||
mme_ue_t *mme_ue, nas_tracking_area_update_request_t *tau_request)
|
mme_ue_t *mme_ue, nas_tracking_area_update_request_t *tau_request)
|
||||||
{
|
{
|
||||||
|
status_t rv;
|
||||||
|
|
||||||
|
nas_eps_update_type_t *eps_update_type =
|
||||||
|
&tau_request->eps_update_type;
|
||||||
nas_eps_mobile_identity_t *eps_mobile_identity =
|
nas_eps_mobile_identity_t *eps_mobile_identity =
|
||||||
&tau_request->old_guti;
|
&tau_request->old_guti;
|
||||||
enb_ue_t *enb_ue = NULL;
|
enb_ue_t *enb_ue = NULL;
|
||||||
|
@ -344,6 +432,13 @@ void emm_handle_tau_request(
|
||||||
enb_ue = mme_ue->enb_ue;
|
enb_ue = mme_ue->enb_ue;
|
||||||
d_assert(enb_ue, return, "Null param");
|
d_assert(enb_ue, return, "Null param");
|
||||||
|
|
||||||
|
CLEAR_PAGING_INFO(mme_ue);
|
||||||
|
|
||||||
|
/* Set EPS Attach Type */
|
||||||
|
memcpy(&mme_ue->nas_eps.update, eps_update_type,
|
||||||
|
sizeof(nas_eps_update_type_t));
|
||||||
|
mme_ue->nas_eps.type = MME_UE_EPS_UPDATE_TYPE;
|
||||||
|
|
||||||
/* Store UE specific information */
|
/* Store UE specific information */
|
||||||
if (tau_request->presencemask &
|
if (tau_request->presencemask &
|
||||||
NAS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT)
|
NAS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT)
|
||||||
|
@ -407,6 +502,7 @@ void emm_handle_tau_request(
|
||||||
MME_UE_HAVE_IMSI(mme_ue)
|
MME_UE_HAVE_IMSI(mme_ue)
|
||||||
? mme_ue->imsi_bcd : "Unknown");
|
? mme_ue->imsi_bcd : "Unknown");
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (!MME_UE_HAVE_IMSI(mme_ue))
|
if (!MME_UE_HAVE_IMSI(mme_ue))
|
||||||
{
|
{
|
||||||
/* Unknown GUTI */
|
/* Unknown GUTI */
|
||||||
|
@ -416,7 +512,7 @@ void emm_handle_tau_request(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Send TAU reject */
|
/* Send TAU reject */
|
||||||
emm_handle_tau_reject(mme_ue,
|
nas_send_tau_reject(mme_ue,
|
||||||
EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK);
|
EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK);
|
||||||
}
|
}
|
||||||
else if (!SECURITY_CONTEXT_IS_VALID(mme_ue))
|
else if (!SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||||
|
@ -427,9 +523,9 @@ void emm_handle_tau_request(
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Send TAU accept */
|
/* Send TAU accept */
|
||||||
emm_handle_tau_accept(mme_ue);
|
nas_send_tau_accept(mme_ue);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -440,78 +536,33 @@ void emm_handle_tau_request(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void emm_handle_tau_accept(mme_ue_t *mme_ue)
|
if (!MME_UE_HAVE_IMSI(mme_ue))
|
||||||
{
|
|
||||||
status_t rv;
|
|
||||||
mme_enb_t *enb = NULL;
|
|
||||||
enb_ue_t *enb_ue = NULL;
|
|
||||||
pkbuf_t *emmbuf = NULL, *s1apbuf = NULL;
|
|
||||||
S1ap_Cause_t cause;
|
|
||||||
|
|
||||||
d_assert(mme_ue, return, "Null param");
|
|
||||||
enb_ue = mme_ue->enb_ue;
|
|
||||||
d_assert(enb_ue, return, "Null param");
|
|
||||||
enb = enb_ue->enb;
|
|
||||||
d_assert(enb, return, "Null param");
|
|
||||||
|
|
||||||
/* Build TAU accept */
|
|
||||||
if (emm_build_tau_accept(&emmbuf, mme_ue) != CORE_OK)
|
|
||||||
{
|
{
|
||||||
d_error("emm_build_tau_accept error");
|
/* Unknown GUTI */
|
||||||
pkbuf_free(emmbuf);
|
FSM_TRAN(&mme_ue->sm, &emm_state_identity);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* Send Dl NAS to UE */
|
|
||||||
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
|
||||||
|
|
||||||
|
|
||||||
/* FIXME : delay required before sending UE context release to make sure
|
|
||||||
* that UE receive DL NAS ? */
|
|
||||||
cause.present = S1ap_Cause_PR_nas;
|
|
||||||
cause.choice.nas = S1ap_CauseNas_normal_release;
|
|
||||||
|
|
||||||
rv = s1ap_build_ue_context_release_commmand(&s1apbuf, enb_ue, &cause);
|
|
||||||
d_assert(rv == CORE_OK && s1apbuf, return, "s1ap build error");
|
|
||||||
|
|
||||||
d_assert(s1ap_send_to_enb(enb, s1apbuf) == CORE_OK,, "s1ap send error");
|
|
||||||
}
|
|
||||||
|
|
||||||
void emm_handle_tau_reject(mme_ue_t *mme_ue, nas_emm_cause_t emm_cause)
|
|
||||||
{
|
|
||||||
status_t rv;
|
|
||||||
mme_enb_t *enb = NULL;
|
|
||||||
enb_ue_t *enb_ue = NULL;
|
|
||||||
pkbuf_t *emmbuf = NULL, *s1apbuf = NULL;
|
|
||||||
S1ap_Cause_t cause;
|
|
||||||
|
|
||||||
d_assert(mme_ue, return, "Null param");
|
|
||||||
enb_ue = mme_ue->enb_ue;
|
|
||||||
d_assert(enb_ue, return, "Null param");
|
|
||||||
enb = enb_ue->enb;
|
|
||||||
d_assert(enb, return, "Null param");
|
|
||||||
|
|
||||||
/* Build TAU reject */
|
|
||||||
if (emm_build_tau_reject(&emmbuf, emm_cause, mme_ue) != CORE_OK)
|
|
||||||
{
|
{
|
||||||
d_error("emm_build_tau_accept error");
|
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||||
pkbuf_free(emmbuf);
|
{
|
||||||
return;
|
/* Send TAU accept */
|
||||||
|
rv = nas_send_tau_accept(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK, return, "nas_send_tau_accept failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (MME_HAVE_SGW_S11_PATH(mme_ue))
|
||||||
|
{
|
||||||
|
rv = mme_gtp_send_delete_all_sessions(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK, return,
|
||||||
|
"mme_gtp_send_delete_all_sessions failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mme_s6a_send_air(mme_ue);
|
||||||
|
}
|
||||||
|
FSM_TRAN(&mme_ue->sm, &emm_state_authentication);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send Dl NAS to UE */
|
|
||||||
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
|
||||||
|
|
||||||
|
|
||||||
/* FIXME : delay required before sending UE context release to make sure
|
|
||||||
* that UE receive DL NAS ? */
|
|
||||||
cause.present = S1ap_Cause_PR_nas;
|
|
||||||
cause.choice.nas = S1ap_CauseNas_normal_release;
|
|
||||||
|
|
||||||
rv = s1ap_build_ue_context_release_commmand(&s1apbuf, enb_ue, &cause);
|
|
||||||
d_assert(rv == CORE_OK && s1apbuf, return, "s1ap build error");
|
|
||||||
|
|
||||||
d_assert(s1ap_send_to_enb(enb, s1apbuf) == CORE_OK,, "s1ap send error");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,6 @@ CORE_DECLARE(void) emm_handle_emm_status(
|
||||||
mme_ue_t *mme_ue, nas_emm_status_t *emm_status);
|
mme_ue_t *mme_ue, nas_emm_status_t *emm_status);
|
||||||
CORE_DECLARE(void) emm_handle_tau_request(
|
CORE_DECLARE(void) emm_handle_tau_request(
|
||||||
mme_ue_t *mme_ue, nas_tracking_area_update_request_t *tau_request);
|
mme_ue_t *mme_ue, nas_tracking_area_update_request_t *tau_request);
|
||||||
CORE_DECLARE(void) emm_handle_tau_accept(mme_ue_t *mme_ue);
|
|
||||||
CORE_DECLARE(void) emm_handle_tau_reject(mme_ue_t *mme_ue,
|
|
||||||
nas_esm_cause_t emm_cause);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
123
src/mme/emm_sm.c
123
src/mme/emm_sm.c
|
@ -14,11 +14,9 @@
|
||||||
#include "emm_build.h"
|
#include "emm_build.h"
|
||||||
#include "esm_handler.h"
|
#include "esm_handler.h"
|
||||||
#include "nas_path.h"
|
#include "nas_path.h"
|
||||||
|
#include "s1ap_path.h"
|
||||||
#include "mme_gtp_path.h"
|
#include "mme_gtp_path.h"
|
||||||
|
|
||||||
static void emm_state_attach_request(fsm_t *s, event_t *e,
|
|
||||||
mme_ue_t *mme_ue, nas_message_t *message);
|
|
||||||
|
|
||||||
void emm_state_initial(fsm_t *s, event_t *e)
|
void emm_state_initial(fsm_t *s, event_t *e)
|
||||||
{
|
{
|
||||||
d_assert(s, return, "Null param");
|
d_assert(s, return, "Null param");
|
||||||
|
@ -66,7 +64,8 @@ void emm_state_detached(fsm_t *s, event_t *e)
|
||||||
{
|
{
|
||||||
case NAS_ATTACH_REQUEST:
|
case NAS_ATTACH_REQUEST:
|
||||||
{
|
{
|
||||||
emm_state_attach_request(s, e, mme_ue, message);
|
emm_handle_attach_request(
|
||||||
|
mme_ue, &message->emm.attach_request);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,33 +121,6 @@ void emm_state_identity(fsm_t *s, event_t *e)
|
||||||
{
|
{
|
||||||
emm_handle_identity_response(mme_ue,
|
emm_handle_identity_response(mme_ue,
|
||||||
&message->emm.identity_response);
|
&message->emm.identity_response);
|
||||||
|
|
||||||
d_assert(MME_UE_HAVE_IMSI(mme_ue), break,
|
|
||||||
"No IMSI in IDENTITY_RESPONSE");
|
|
||||||
|
|
||||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
|
||||||
{
|
|
||||||
status_t rv;
|
|
||||||
rv = nas_send_emm_to_esm(mme_ue,
|
|
||||||
&mme_ue->pdn_connectivity_request);
|
|
||||||
d_assert(rv == CORE_OK,,
|
|
||||||
"nas_send_emm_to_esm failed");
|
|
||||||
FSM_TRAN(s, &emm_state_default_esm);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (MME_HAVE_SGW_S11_PATH(mme_ue))
|
|
||||||
{
|
|
||||||
rv = mme_gtp_send_delete_all_sessions(mme_ue);
|
|
||||||
d_assert(rv == CORE_OK, break,
|
|
||||||
"mme_gtp_send_delete_all_sessions failed");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mme_s6a_send_air(mme_ue);
|
|
||||||
}
|
|
||||||
FSM_TRAN(s, &emm_state_authentication);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NAS_EMM_STATUS:
|
case NAS_EMM_STATUS:
|
||||||
|
@ -401,15 +373,8 @@ void emm_state_attached(fsm_t *s, event_t *e)
|
||||||
if (message->emm.h.security_header_type
|
if (message->emm.h.security_header_type
|
||||||
== NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE)
|
== NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE)
|
||||||
{
|
{
|
||||||
/* Update Kenb */
|
|
||||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
|
||||||
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32,
|
|
||||||
mme_ue->kenb);
|
|
||||||
|
|
||||||
mme_ue_paged(mme_ue);
|
|
||||||
emm_handle_service_request(
|
emm_handle_service_request(
|
||||||
mme_ue, &message->emm.service_request);
|
mme_ue, &message->emm.service_request);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +382,8 @@ void emm_state_attached(fsm_t *s, event_t *e)
|
||||||
{
|
{
|
||||||
case NAS_ATTACH_REQUEST:
|
case NAS_ATTACH_REQUEST:
|
||||||
{
|
{
|
||||||
emm_state_attach_request(s, e, mme_ue, message);
|
emm_handle_attach_request(
|
||||||
|
mme_ue, &message->emm.attach_request);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NAS_EMM_STATUS:
|
case NAS_EMM_STATUS:
|
||||||
|
@ -430,29 +396,30 @@ void emm_state_attached(fsm_t *s, event_t *e)
|
||||||
{
|
{
|
||||||
emm_handle_detach_request(
|
emm_handle_detach_request(
|
||||||
mme_ue, &message->emm.detach_request_from_ue);
|
mme_ue, &message->emm.detach_request_from_ue);
|
||||||
|
|
||||||
if (MME_HAVE_SGW_S11_PATH(mme_ue))
|
|
||||||
{
|
|
||||||
status_t rv;
|
|
||||||
rv = mme_gtp_send_delete_all_sessions(mme_ue);
|
|
||||||
d_assert(rv == CORE_OK, break,
|
|
||||||
"mme_gtp_send_delete_all_sessions failed");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
emm_handle_detach_accept(mme_ue);
|
|
||||||
}
|
|
||||||
|
|
||||||
FSM_TRAN(s, &emm_state_detached);
|
FSM_TRAN(s, &emm_state_detached);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NAS_TRACKING_AREA_UPDATE_REQUEST:
|
case NAS_TRACKING_AREA_UPDATE_REQUEST:
|
||||||
{
|
{
|
||||||
mme_ue_paged(mme_ue);
|
|
||||||
emm_handle_tau_request(
|
emm_handle_tau_request(
|
||||||
mme_ue, &message->emm.tracking_area_update_request);
|
mme_ue, &message->emm.tracking_area_update_request);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NAS_TRACKING_AREA_UPDATE_COMPLETE:
|
||||||
|
{
|
||||||
|
status_t rv;
|
||||||
|
S1ap_Cause_t cause;
|
||||||
|
enb_ue_t *enb_ue = mme_ue->enb_ue;
|
||||||
|
|
||||||
|
d_assert(enb_ue, return, "Null param");
|
||||||
|
|
||||||
|
cause.present = S1ap_Cause_PR_nas;
|
||||||
|
cause.choice.nas = S1ap_CauseNas_normal_release;
|
||||||
|
|
||||||
|
rv = s1ap_send_ue_context_release_commmand(enb_ue, &cause);
|
||||||
|
d_assert(rv == CORE_OK, return, "s1ap send error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
d_warn("Unknown message(type:%d)",
|
d_warn("Unknown message(type:%d)",
|
||||||
|
@ -527,53 +494,3 @@ void emm_state_exception(fsm_t *s, event_t *e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emm_state_attach_request(fsm_t *s, event_t *e,
|
|
||||||
mme_ue_t *mme_ue, nas_message_t *message)
|
|
||||||
{
|
|
||||||
status_t rv;
|
|
||||||
|
|
||||||
d_assert(s, return, "Null param");
|
|
||||||
d_assert(e, return, "Null param");
|
|
||||||
d_assert(mme_ue, return, "Null param");
|
|
||||||
d_assert(message, return, "Null param");
|
|
||||||
|
|
||||||
/* Update Kenb */
|
|
||||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
|
||||||
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32,
|
|
||||||
mme_ue->kenb);
|
|
||||||
|
|
||||||
CLEAR_EPS_BEARER_ID(mme_ue);
|
|
||||||
mme_ue_paged(mme_ue);
|
|
||||||
|
|
||||||
emm_handle_attach_request(mme_ue, &message->emm.attach_request);
|
|
||||||
|
|
||||||
if (!MME_UE_HAVE_IMSI(mme_ue))
|
|
||||||
{
|
|
||||||
/* Unknown GUTI */
|
|
||||||
FSM_TRAN(s, &emm_state_identity);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
|
||||||
{
|
|
||||||
rv = nas_send_emm_to_esm(mme_ue, &mme_ue->pdn_connectivity_request);
|
|
||||||
d_assert(rv == CORE_OK,, "nas_send_emm_to_esm failed");
|
|
||||||
FSM_TRAN(s, &emm_state_default_esm);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (MME_HAVE_SGW_S11_PATH(mme_ue))
|
|
||||||
{
|
|
||||||
rv = mme_gtp_send_delete_all_sessions(mme_ue);
|
|
||||||
d_assert(rv == CORE_OK, return,
|
|
||||||
"mme_gtp_send_delete_all_sessions failed");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mme_s6a_send_air(mme_ue);
|
|
||||||
}
|
|
||||||
FSM_TRAN(s, &emm_state_authentication);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,15 +10,24 @@
|
||||||
|
|
||||||
#include "esm_build.h"
|
#include "esm_build.h"
|
||||||
|
|
||||||
void esm_handle_pdn_connectivity_request(mme_sess_t *sess,
|
void esm_handle_pdn_connectivity_request(mme_bearer_t *bearer,
|
||||||
nas_pdn_connectivity_request_t *pdn_connectivity_request)
|
nas_pdn_connectivity_request_t *pdn_connectivity_request)
|
||||||
{
|
{
|
||||||
|
status_t rv;
|
||||||
mme_ue_t *mme_ue = NULL;
|
mme_ue_t *mme_ue = NULL;
|
||||||
|
mme_sess_t *sess = NULL;
|
||||||
|
|
||||||
|
d_assert(bearer, return, "Null param");
|
||||||
|
sess = bearer->sess;
|
||||||
d_assert(sess, return, "Null param");
|
d_assert(sess, return, "Null param");
|
||||||
mme_ue = sess->mme_ue;
|
mme_ue = sess->mme_ue;
|
||||||
d_assert(mme_ue, return, "Null param");
|
d_assert(mme_ue, return, "Null param");
|
||||||
|
|
||||||
|
d_assert(MME_UE_HAVE_IMSI(mme_ue), return,
|
||||||
|
"No IMSI in PDN_CPNNECTIVITY_REQUEST");
|
||||||
|
d_assert(SECURITY_CONTEXT_IS_VALID(mme_ue), return,
|
||||||
|
"No Security Context in PDN_CPNNECTIVITY_REQUEST");
|
||||||
|
|
||||||
if (pdn_connectivity_request->presencemask &
|
if (pdn_connectivity_request->presencemask &
|
||||||
NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_PRESENT)
|
NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_PRESENT)
|
||||||
{
|
{
|
||||||
|
@ -36,11 +45,53 @@ void esm_handle_pdn_connectivity_request(mme_sess_t *sess,
|
||||||
|
|
||||||
NAS_STORE_DATA(&sess->ue_pco, protocol_configuration_options);
|
NAS_STORE_DATA(&sess->ue_pco, protocol_configuration_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MME_UE_HAVE_APN(mme_ue))
|
||||||
|
{
|
||||||
|
if (FSM_CHECK(&mme_ue->sm, emm_state_attached))
|
||||||
|
{
|
||||||
|
rv = mme_gtp_send_create_session_request(sess);
|
||||||
|
d_assert(rv == CORE_OK, return,
|
||||||
|
"mme_gtp_send_create_session_request failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (MME_HAVE_SGW_S11_PATH(mme_ue))
|
||||||
|
{
|
||||||
|
if (mme_ue->nas_eps.type == MME_UE_EPS_ATTACH_TYPE)
|
||||||
|
{
|
||||||
|
rv = nas_send_attach_accept(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK, return,
|
||||||
|
"nas_send_attach_accept failed");
|
||||||
|
}
|
||||||
|
else if (mme_ue->nas_eps.type == MME_UE_EPS_UPDATE_TYPE)
|
||||||
|
{
|
||||||
|
rv = nas_send_tau_accept(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK, return,
|
||||||
|
"nas_send_tau_accept failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
d_assert(0, return, "Invalid EPS type(%d)",
|
||||||
|
mme_ue->nas_eps.type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = mme_gtp_send_create_session_request(sess);
|
||||||
|
d_assert(rv == CORE_OK, return,
|
||||||
|
"mme_gtp_send_create_session_request failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FSM_TRAN(&bearer->sm, esm_state_information);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void esm_handle_information_response(mme_sess_t *sess,
|
void esm_handle_information_response(mme_sess_t *sess,
|
||||||
nas_esm_information_response_t *esm_information_response)
|
nas_esm_information_response_t *esm_information_response)
|
||||||
{
|
{
|
||||||
|
status_t rv;
|
||||||
mme_ue_t *mme_ue = NULL;
|
mme_ue_t *mme_ue = NULL;
|
||||||
|
|
||||||
d_assert(sess, return, "Null param");
|
d_assert(sess, return, "Null param");
|
||||||
|
@ -63,6 +114,10 @@ void esm_handle_information_response(mme_sess_t *sess,
|
||||||
&esm_information_response->protocol_configuration_options;
|
&esm_information_response->protocol_configuration_options;
|
||||||
NAS_STORE_DATA(&sess->ue_pco, protocol_configuration_options);
|
NAS_STORE_DATA(&sess->ue_pco, protocol_configuration_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv = mme_gtp_send_create_session_request(sess);
|
||||||
|
d_assert(rv == CORE_OK, return,
|
||||||
|
"mme_gtp_send_create_session_request failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
void esm_handle_activate_default_bearer_accept(mme_bearer_t *bearer)
|
void esm_handle_activate_default_bearer_accept(mme_bearer_t *bearer)
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
CORE_DECLARE(void) esm_handle_pdn_connectivity_request(mme_sess_t *sess,
|
CORE_DECLARE(void) esm_handle_pdn_connectivity_request(mme_bearer_t *bearer,
|
||||||
nas_pdn_connectivity_request_t *pdn_connectivity_request);
|
nas_pdn_connectivity_request_t *pdn_connectivity_request);
|
||||||
CORE_DECLARE(void) esm_handle_information_response(mme_sess_t *sess,
|
CORE_DECLARE(void) esm_handle_information_response(mme_sess_t *sess,
|
||||||
nas_esm_information_response_t *bearer_information_response);
|
nas_esm_information_response_t *bearer_information_response);
|
||||||
|
|
|
@ -13,10 +13,6 @@
|
||||||
#include "nas_path.h"
|
#include "nas_path.h"
|
||||||
#include "mme_gtp_path.h"
|
#include "mme_gtp_path.h"
|
||||||
|
|
||||||
static void esm_state_pdn_connectivity_request(
|
|
||||||
fsm_t *s, event_t *e, mme_ue_t *mme_ue, mme_sess_t *sess,
|
|
||||||
mme_bearer_t *bearer, nas_message_t *message);
|
|
||||||
|
|
||||||
void esm_state_initial(fsm_t *s, event_t *e)
|
void esm_state_initial(fsm_t *s, event_t *e)
|
||||||
{
|
{
|
||||||
d_assert(s, return, "Null param");
|
d_assert(s, return, "Null param");
|
||||||
|
@ -71,8 +67,8 @@ void esm_state_inactive(fsm_t *s, event_t *e)
|
||||||
{
|
{
|
||||||
case NAS_PDN_CONNECTIVITY_REQUEST:
|
case NAS_PDN_CONNECTIVITY_REQUEST:
|
||||||
{
|
{
|
||||||
esm_state_pdn_connectivity_request(s, e,
|
esm_handle_pdn_connectivity_request(
|
||||||
mme_ue, sess, bearer, message);
|
bearer, &message->esm.pdn_connectivity_request);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT:
|
case NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT:
|
||||||
|
@ -176,8 +172,6 @@ void esm_state_information(fsm_t *s, event_t *e)
|
||||||
mme_ue->imsi_bcd, sess->pti);
|
mme_ue->imsi_bcd, sess->pti);
|
||||||
esm_handle_information_response(
|
esm_handle_information_response(
|
||||||
sess, &message->esm.esm_information_response);
|
sess, &message->esm.esm_information_response);
|
||||||
|
|
||||||
mme_s11_handle_create_session_request(sess);
|
|
||||||
FSM_TRAN(s, esm_state_inactive);
|
FSM_TRAN(s, esm_state_inactive);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -237,8 +231,8 @@ void esm_state_active(fsm_t *s, event_t *e)
|
||||||
{
|
{
|
||||||
case NAS_PDN_CONNECTIVITY_REQUEST:
|
case NAS_PDN_CONNECTIVITY_REQUEST:
|
||||||
{
|
{
|
||||||
esm_state_pdn_connectivity_request(s, e,
|
esm_handle_pdn_connectivity_request(
|
||||||
mme_ue, sess, bearer, message);
|
bearer, &message->esm.pdn_connectivity_request);
|
||||||
FSM_TRAN(s, esm_state_inactive);
|
FSM_TRAN(s, esm_state_inactive);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -366,53 +360,3 @@ void esm_state_bearer_exception(fsm_t *s, event_t *e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void esm_state_pdn_connectivity_request(
|
|
||||||
fsm_t *s, event_t *e, mme_ue_t *mme_ue, mme_sess_t *sess,
|
|
||||||
mme_bearer_t *bearer, nas_message_t *message)
|
|
||||||
{
|
|
||||||
d_assert(s, return, "Null param");
|
|
||||||
d_assert(e, return, "Null param");
|
|
||||||
d_assert(mme_ue, return, "Null param");
|
|
||||||
d_assert(sess, return, "Null param");
|
|
||||||
d_assert(bearer, return, "Null param");
|
|
||||||
d_assert(message, return, "Null param");
|
|
||||||
|
|
||||||
d_trace(3, "[NAS] PDN connectivity request : UE[%s] --> ESM[%d]\n",
|
|
||||||
mme_ue->imsi_bcd, sess->pti);
|
|
||||||
|
|
||||||
d_assert(MME_UE_HAVE_IMSI(mme_ue), return,
|
|
||||||
"No IMSI in PDN_CPNNECTIVITY_REQUEST");
|
|
||||||
d_assert(SECURITY_CONTEXT_IS_VALID(mme_ue), return,
|
|
||||||
"No Security Context in PDN_CPNNECTIVITY_REQUEST");
|
|
||||||
|
|
||||||
esm_handle_pdn_connectivity_request(
|
|
||||||
sess, &message->esm.pdn_connectivity_request);
|
|
||||||
|
|
||||||
if (MME_UE_HAVE_APN(mme_ue))
|
|
||||||
{
|
|
||||||
if (FSM_CHECK(&mme_ue->sm, emm_state_attached))
|
|
||||||
{
|
|
||||||
mme_s11_handle_create_session_request(sess);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (MME_HAVE_SGW_S11_PATH(mme_ue))
|
|
||||||
{
|
|
||||||
status_t rv;
|
|
||||||
rv = nas_send_attach_accept(mme_ue);
|
|
||||||
d_assert(rv == CORE_OK, return,
|
|
||||||
"nas_send_attach_accept failed");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mme_s11_handle_create_session_request(sess);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FSM_TRAN(s, esm_state_information);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1164,15 +1164,11 @@ status_t mme_ue_remove(mme_ue_t *mme_ue)
|
||||||
if (mme_ue->imsi_len != 0)
|
if (mme_ue->imsi_len != 0)
|
||||||
hash_set(self.imsi_ue_hash, mme_ue->imsi, mme_ue->imsi_len, NULL);
|
hash_set(self.imsi_ue_hash, mme_ue->imsi, mme_ue->imsi_len, NULL);
|
||||||
|
|
||||||
/* Delete t3413 timer */
|
/* Clear the saved PDN Connectivity Request */
|
||||||
tm_delete(mme_ue->t3413);
|
|
||||||
|
|
||||||
/* Free the saved PDN Connectivity Request */
|
|
||||||
NAS_CLEAR_DATA(&mme_ue->pdn_connectivity_request);
|
NAS_CLEAR_DATA(&mme_ue->pdn_connectivity_request);
|
||||||
|
|
||||||
/* Free the saved paging msg */
|
/* Clear Paging info : t3413, last_paing_msg */
|
||||||
if (mme_ue->last_paging_msg)
|
CLEAR_PAGING_INFO(mme_ue);
|
||||||
pkbuf_free(mme_ue->last_paging_msg);
|
|
||||||
|
|
||||||
/* Free UeRadioCapability */
|
/* Free UeRadioCapability */
|
||||||
if (mme_ue->radio_capa)
|
if (mme_ue->radio_capa)
|
||||||
|
@ -1738,16 +1734,3 @@ pdn_t* mme_pdn_find_by_apn(mme_ue_t *mme_ue, c_int8_t *apn)
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mme_ue_paged(mme_ue_t *mme_ue)
|
|
||||||
{
|
|
||||||
d_assert(mme_ue, return , "Null param");
|
|
||||||
|
|
||||||
tm_stop(mme_ue->t3413);
|
|
||||||
if (mme_ue->last_paging_msg)
|
|
||||||
{
|
|
||||||
pkbuf_free(mme_ue->last_paging_msg);
|
|
||||||
mme_ue->last_paging_msg = NULL;
|
|
||||||
}
|
|
||||||
mme_ue->max_paging_retry = 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -143,6 +143,16 @@ struct _mme_ue_t {
|
||||||
index_t index; /* An index of this node */
|
index_t index; /* An index of this node */
|
||||||
fsm_t sm; /* A state machine */
|
fsm_t sm; /* A state machine */
|
||||||
|
|
||||||
|
struct {
|
||||||
|
#define MME_UE_EPS_ATTACH_TYPE 1
|
||||||
|
#define MME_UE_EPS_UPDATE_TYPE 2
|
||||||
|
c_uint8_t type;
|
||||||
|
union {
|
||||||
|
nas_eps_attach_type_t attach;
|
||||||
|
nas_eps_update_type_t update;
|
||||||
|
};
|
||||||
|
} nas_eps;
|
||||||
|
|
||||||
/* UE identity */
|
/* UE identity */
|
||||||
#define MME_UE_HAVE_IMSI(__mME) \
|
#define MME_UE_HAVE_IMSI(__mME) \
|
||||||
((__mME) && ((__mME)->imsi_len))
|
((__mME) && ((__mME)->imsi_len))
|
||||||
|
@ -230,6 +240,18 @@ struct _mme_ue_t {
|
||||||
nas_esm_message_container_t pdn_connectivity_request;
|
nas_esm_message_container_t pdn_connectivity_request;
|
||||||
|
|
||||||
/* Paging */
|
/* Paging */
|
||||||
|
#define CLEAR_PAGING_INFO(__mME) \
|
||||||
|
do { \
|
||||||
|
d_assert((__mME), break, "Null param"); \
|
||||||
|
\
|
||||||
|
tm_stop((__mME)->t3413); \
|
||||||
|
if ((__mME)->last_paging_msg) \
|
||||||
|
{ \
|
||||||
|
pkbuf_free((__mME)->last_paging_msg); \
|
||||||
|
(__mME)->last_paging_msg = NULL; \
|
||||||
|
} \
|
||||||
|
(__mME)->max_paging_retry = 0; \
|
||||||
|
} while(0);
|
||||||
pkbuf_t *last_paging_msg;
|
pkbuf_t *last_paging_msg;
|
||||||
tm_block_id t3413;
|
tm_block_id t3413;
|
||||||
#define MAX_NUM_OF_PAGING 2
|
#define MAX_NUM_OF_PAGING 2
|
||||||
|
@ -268,10 +290,10 @@ typedef struct _mme_sess_t {
|
||||||
/* Related Context */
|
/* Related Context */
|
||||||
#define CONNECT_SGW_GTP_NODE(__sESS) \
|
#define CONNECT_SGW_GTP_NODE(__sESS) \
|
||||||
do { \
|
do { \
|
||||||
d_assert((__sESS), return, "Null param"); \
|
d_assert((__sESS), break, "Null param"); \
|
||||||
(__sESS)->sgw = mme_sgw_next((__sESS)->sgw); \
|
(__sESS)->sgw = mme_sgw_next((__sESS)->sgw); \
|
||||||
if (!(__sESS)->sgw) (__sESS)->sgw = mme_sgw_first(); \
|
if (!(__sESS)->sgw) (__sESS)->sgw = mme_sgw_first(); \
|
||||||
d_assert((__sESS)->sgw, return, "Null param"); \
|
d_assert((__sESS)->sgw, break, "Null param"); \
|
||||||
} while(0)
|
} while(0)
|
||||||
mme_sgw_t *sgw;
|
mme_sgw_t *sgw;
|
||||||
mme_ue_t *mme_ue;
|
mme_ue_t *mme_ue;
|
||||||
|
@ -400,7 +422,6 @@ CORE_DECLARE(enb_ue_t*) enb_ue_find_by_mme_ue_s1ap_id(c_uint32_t mme_ue_s1ap
|
||||||
CORE_DECLARE(enb_ue_t*) enb_ue_first_in_enb(mme_enb_t *enb);
|
CORE_DECLARE(enb_ue_t*) enb_ue_first_in_enb(mme_enb_t *enb);
|
||||||
CORE_DECLARE(enb_ue_t*) enb_ue_next_in_enb(enb_ue_t *enb_ue);
|
CORE_DECLARE(enb_ue_t*) enb_ue_next_in_enb(enb_ue_t *enb_ue);
|
||||||
|
|
||||||
CORE_DECLARE(void) mme_ue_paged(mme_ue_t *mme_ue);
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
|
@ -91,6 +91,38 @@ status_t mme_gtp_close()
|
||||||
return CORE_OK;
|
return CORE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t mme_gtp_send_create_session_request(mme_sess_t *sess)
|
||||||
|
{
|
||||||
|
status_t rv;
|
||||||
|
gtp_header_t h;
|
||||||
|
pkbuf_t *pkbuf = NULL;
|
||||||
|
gtp_xact_t *xact = NULL;
|
||||||
|
mme_ue_t *mme_ue = NULL;
|
||||||
|
|
||||||
|
/* Use round-robin for selecting SGW */
|
||||||
|
CONNECT_SGW_GTP_NODE(sess);
|
||||||
|
|
||||||
|
mme_ue = sess->mme_ue;
|
||||||
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
||||||
|
|
||||||
|
memset(&h, 0, sizeof(gtp_header_t));
|
||||||
|
h.type = GTP_CREATE_SESSION_REQUEST_TYPE;
|
||||||
|
h.teid = mme_ue->sgw_s11_teid;
|
||||||
|
|
||||||
|
rv = mme_s11_build_create_session_request(&pkbuf, h.type, sess);
|
||||||
|
d_assert(rv == CORE_OK, return CORE_ERROR,
|
||||||
|
"S11 build error");
|
||||||
|
|
||||||
|
xact = gtp_xact_local_create(sess->sgw, &h, pkbuf);
|
||||||
|
d_assert(xact, return CORE_ERROR, "Null param");
|
||||||
|
|
||||||
|
rv = gtp_xact_commit(xact);
|
||||||
|
d_assert(rv == CORE_OK, return CORE_ERROR, "xact_commit error");
|
||||||
|
|
||||||
|
return CORE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t mme_gtp_send_modify_bearer_request(mme_bearer_t *bearer)
|
status_t mme_gtp_send_modify_bearer_request(mme_bearer_t *bearer)
|
||||||
{
|
{
|
||||||
status_t rv;
|
status_t rv;
|
||||||
|
|
|
@ -12,6 +12,7 @@ extern "C" {
|
||||||
CORE_DECLARE(status_t) mme_gtp_open();
|
CORE_DECLARE(status_t) mme_gtp_open();
|
||||||
CORE_DECLARE(status_t) mme_gtp_close();
|
CORE_DECLARE(status_t) mme_gtp_close();
|
||||||
|
|
||||||
|
CORE_DECLARE(status_t) mme_gtp_send_create_session_request(mme_sess_t *sess);
|
||||||
CORE_DECLARE(status_t) mme_gtp_send_modify_bearer_request(
|
CORE_DECLARE(status_t) mme_gtp_send_modify_bearer_request(
|
||||||
mme_bearer_t *bearer);
|
mme_bearer_t *bearer);
|
||||||
CORE_DECLARE(status_t) mme_gtp_send_delete_session_request(
|
CORE_DECLARE(status_t) mme_gtp_send_delete_session_request(
|
||||||
|
|
|
@ -15,35 +15,6 @@
|
||||||
#include "esm_build.h"
|
#include "esm_build.h"
|
||||||
#include "nas_path.h"
|
#include "nas_path.h"
|
||||||
|
|
||||||
void mme_s11_handle_create_session_request(mme_sess_t *sess)
|
|
||||||
{
|
|
||||||
status_t rv;
|
|
||||||
gtp_header_t h;
|
|
||||||
pkbuf_t *pkbuf = NULL;
|
|
||||||
gtp_xact_t *xact = NULL;
|
|
||||||
mme_ue_t *mme_ue = NULL;
|
|
||||||
|
|
||||||
/* Use round-robin for selecting SGW */
|
|
||||||
CONNECT_SGW_GTP_NODE(sess);
|
|
||||||
|
|
||||||
mme_ue = sess->mme_ue;
|
|
||||||
d_assert(mme_ue, return, "Null param");
|
|
||||||
|
|
||||||
memset(&h, 0, sizeof(gtp_header_t));
|
|
||||||
h.type = GTP_CREATE_SESSION_REQUEST_TYPE;
|
|
||||||
h.teid = mme_ue->sgw_s11_teid;
|
|
||||||
|
|
||||||
rv = mme_s11_build_create_session_request(&pkbuf, h.type, sess);
|
|
||||||
d_assert(rv == CORE_OK, return,
|
|
||||||
"S11 build error");
|
|
||||||
|
|
||||||
xact = gtp_xact_local_create(sess->sgw, &h, pkbuf);
|
|
||||||
d_assert(xact, return, "Null param");
|
|
||||||
|
|
||||||
rv = gtp_xact_commit(xact);
|
|
||||||
d_assert(rv == CORE_OK, return, "xact_commit error");
|
|
||||||
}
|
|
||||||
|
|
||||||
void mme_s11_handle_create_session_response(gtp_xact_t *xact,
|
void mme_s11_handle_create_session_response(gtp_xact_t *xact,
|
||||||
mme_bearer_t *bearer, gtp_create_session_response_t *rsp)
|
mme_bearer_t *bearer, gtp_create_session_response_t *rsp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
CORE_DECLARE(void) mme_s11_handle_create_session_request(mme_sess_t *sess);
|
|
||||||
CORE_DECLARE(void) mme_s11_handle_create_session_response(
|
CORE_DECLARE(void) mme_s11_handle_create_session_response(
|
||||||
gtp_xact_t *xact, mme_bearer_t *bearer,
|
gtp_xact_t *xact, mme_bearer_t *bearer,
|
||||||
gtp_create_session_response_t *rsp);
|
gtp_create_session_response_t *rsp);
|
||||||
|
|
|
@ -386,9 +386,21 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
||||||
|
|
||||||
if (FSM_CHECK(&mme_ue->sm, emm_state_default_esm))
|
if (FSM_CHECK(&mme_ue->sm, emm_state_default_esm))
|
||||||
{
|
{
|
||||||
rv = nas_send_attach_accept(mme_ue);
|
if (mme_ue->nas_eps.type == MME_UE_EPS_ATTACH_TYPE)
|
||||||
d_assert(rv == CORE_OK, return,
|
{
|
||||||
"nas_send_attach_accept failed");
|
rv = nas_send_attach_accept(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK, return,
|
||||||
|
"nas_send_attach_accept failed");
|
||||||
|
}
|
||||||
|
else if (mme_ue->nas_eps.type == MME_UE_EPS_UPDATE_TYPE)
|
||||||
|
{
|
||||||
|
rv = nas_send_tau_accept(mme_ue);
|
||||||
|
d_assert(rv == CORE_OK, return,
|
||||||
|
"nas_send_tau_accept failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
d_assert(0, return, "Invalid EPS type(%d)",
|
||||||
|
mme_ue->nas_eps.type);
|
||||||
}
|
}
|
||||||
else if (FSM_CHECK(&mme_ue->sm, emm_state_attached))
|
else if (FSM_CHECK(&mme_ue->sm, emm_state_attached))
|
||||||
{
|
{
|
||||||
|
@ -495,10 +507,15 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
||||||
break;
|
break;
|
||||||
case GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE:
|
case GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE:
|
||||||
{
|
{
|
||||||
|
S1ap_Cause_t cause;
|
||||||
|
|
||||||
mme_s11_handle_release_access_bearers_response(
|
mme_s11_handle_release_access_bearers_response(
|
||||||
xact, mme_ue, &message.release_access_bearers_response);
|
xact, mme_ue, &message.release_access_bearers_response);
|
||||||
|
|
||||||
s1ap_handle_release_access_bearers_response(enb_ue);
|
cause.present = S1ap_Cause_PR_nas;
|
||||||
|
cause.choice.nas = S1ap_CauseNas_normal_release;
|
||||||
|
rv = s1ap_send_ue_context_release_commmand(enb_ue, &cause);
|
||||||
|
d_assert(rv == CORE_OK,, "s1ap send error");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ status_t nas_send_attach_reject(mme_ue_t *mme_ue,
|
||||||
mme_enb_t *enb = NULL;
|
mme_enb_t *enb = NULL;
|
||||||
enb_ue_t *enb_ue = NULL;
|
enb_ue_t *enb_ue = NULL;
|
||||||
mme_sess_t *sess = NULL;
|
mme_sess_t *sess = NULL;
|
||||||
pkbuf_t *s1apbuf = NULL, *esmbuf = NULL, *emmbuf = NULL;
|
pkbuf_t *esmbuf = NULL, *emmbuf = NULL;
|
||||||
S1ap_Cause_t cause;
|
S1ap_Cause_t cause;
|
||||||
|
|
||||||
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
||||||
|
@ -126,14 +126,11 @@ status_t nas_send_attach_reject(mme_ue_t *mme_ue,
|
||||||
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||||
d_trace(3, "[NAS] Attach reject : UE[%s] <-- EMM\n", mme_ue->imsi_bcd);
|
d_trace(3, "[NAS] Attach reject : UE[%s] <-- EMM\n", mme_ue->imsi_bcd);
|
||||||
|
|
||||||
|
/* FIXME : delay is needed */
|
||||||
cause.present = S1ap_Cause_PR_nas;
|
cause.present = S1ap_Cause_PR_nas;
|
||||||
cause.choice.nas = s1ap_cause_nas;;
|
cause.choice.nas = s1ap_cause_nas;;
|
||||||
|
rv = s1ap_send_ue_context_release_commmand(enb_ue, &cause);
|
||||||
rv = s1ap_build_ue_context_release_commmand(&s1apbuf, enb_ue, &cause);
|
d_assert(rv == CORE_OK, return CORE_ERROR, "s1ap send error");
|
||||||
d_assert(rv == CORE_OK && s1apbuf,
|
|
||||||
return CORE_ERROR, "s1ap build error");
|
|
||||||
d_assert(s1ap_send_to_enb(enb, s1apbuf) == CORE_OK,
|
|
||||||
return CORE_ERROR, "s1ap send error");
|
|
||||||
|
|
||||||
return CORE_OK;
|
return CORE_OK;
|
||||||
}
|
}
|
||||||
|
@ -188,3 +185,81 @@ status_t nas_send_deactivate_bearer_context_request(
|
||||||
|
|
||||||
return CORE_OK;
|
return CORE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t nas_send_tau_accept(mme_ue_t *mme_ue)
|
||||||
|
{
|
||||||
|
status_t rv;
|
||||||
|
enb_ue_t *enb_ue = NULL;
|
||||||
|
pkbuf_t *s1apbuf = NULL, *emmbuf = NULL;
|
||||||
|
S1ap_Cause_t cause;
|
||||||
|
|
||||||
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
||||||
|
enb_ue = mme_ue->enb_ue;
|
||||||
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
||||||
|
|
||||||
|
if (FSM_CHECK(&mme_ue->sm, emm_state_attached))
|
||||||
|
{
|
||||||
|
/* Build TAU accept */
|
||||||
|
rv = emm_build_tau_accept(&emmbuf, mme_ue);
|
||||||
|
d_assert(rv == CORE_OK, return CORE_ERROR, "emm build error");
|
||||||
|
|
||||||
|
/* Send Dl NAS to UE */
|
||||||
|
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||||
|
|
||||||
|
/* FIXME : delay required before sending UE context release to make sure
|
||||||
|
* that UE receive DL NAS ? */
|
||||||
|
cause.present = S1ap_Cause_PR_nas;
|
||||||
|
cause.choice.nas = S1ap_CauseNas_normal_release;
|
||||||
|
rv = s1ap_send_ue_context_release_commmand(enb_ue, &cause);
|
||||||
|
d_assert(rv == CORE_OK, return CORE_ERROR, "s1ap send error");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mme_sess_t *sess = mme_sess_first(mme_ue);
|
||||||
|
d_assert(sess, return CORE_ERROR, "Null param");
|
||||||
|
|
||||||
|
rv = emm_build_tau_accept(&emmbuf, mme_ue);
|
||||||
|
d_assert(rv == CORE_OK, return CORE_ERROR, "emm build error");
|
||||||
|
|
||||||
|
rv = s1ap_build_initial_context_setup_request(&s1apbuf, sess, emmbuf);
|
||||||
|
d_assert(rv == CORE_OK && s1apbuf,
|
||||||
|
pkbuf_free(emmbuf); return CORE_ERROR, "s1ap build error");
|
||||||
|
|
||||||
|
d_assert(nas_send_to_enb(enb_ue, s1apbuf) == CORE_OK,,);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CORE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t nas_send_tau_reject(mme_ue_t *mme_ue, nas_emm_cause_t emm_cause)
|
||||||
|
{
|
||||||
|
status_t rv;
|
||||||
|
enb_ue_t *enb_ue = NULL;
|
||||||
|
pkbuf_t *emmbuf = NULL;
|
||||||
|
S1ap_Cause_t cause;
|
||||||
|
|
||||||
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
||||||
|
enb_ue = mme_ue->enb_ue;
|
||||||
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
||||||
|
|
||||||
|
/* Build TAU reject */
|
||||||
|
if (emm_build_tau_reject(&emmbuf, emm_cause, mme_ue) != CORE_OK)
|
||||||
|
{
|
||||||
|
d_error("emm_build_tau_accept error");
|
||||||
|
pkbuf_free(emmbuf);
|
||||||
|
return CORE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send Dl NAS to UE */
|
||||||
|
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME : delay required before sending UE context release to make sure
|
||||||
|
* that UE receive DL NAS ? */
|
||||||
|
cause.present = S1ap_Cause_PR_nas;
|
||||||
|
cause.choice.nas = S1ap_CauseNas_normal_release;
|
||||||
|
rv = s1ap_send_ue_context_release_commmand(enb_ue, &cause);
|
||||||
|
d_assert(rv == CORE_OK, return CORE_ERROR, "s1ap send error");
|
||||||
|
|
||||||
|
return CORE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@ CORE_DECLARE(status_t) nas_send_activate_dedicated_bearer_context_request(
|
||||||
enb_ue_t *enb_ue, mme_bearer_t *bearer);
|
enb_ue_t *enb_ue, mme_bearer_t *bearer);
|
||||||
CORE_DECLARE(status_t) nas_send_deactivate_bearer_context_request(
|
CORE_DECLARE(status_t) nas_send_deactivate_bearer_context_request(
|
||||||
enb_ue_t *enb_ue, mme_bearer_t *bearer);
|
enb_ue_t *enb_ue, mme_bearer_t *bearer);
|
||||||
|
CORE_DECLARE(status_t) nas_send_tau_accept(mme_ue_t *mme_ue);
|
||||||
|
CORE_DECLARE(status_t) nas_send_tau_reject(mme_ue_t *mme_ue,
|
||||||
|
nas_esm_cause_t emm_cause);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -400,6 +400,7 @@ void s1ap_handle_e_rab_setup_response(
|
||||||
void s1ap_handle_ue_context_release_request(
|
void s1ap_handle_ue_context_release_request(
|
||||||
mme_enb_t *enb, s1ap_message_t *message)
|
mme_enb_t *enb, s1ap_message_t *message)
|
||||||
{
|
{
|
||||||
|
status_t rv;
|
||||||
char buf[INET_ADDRSTRLEN];
|
char buf[INET_ADDRSTRLEN];
|
||||||
|
|
||||||
enb_ue_t *enb_ue = NULL;
|
enb_ue_t *enb_ue = NULL;
|
||||||
|
@ -425,7 +426,6 @@ void s1ap_handle_ue_context_release_request(
|
||||||
if (cause == S1ap_CauseRadioNetwork_user_inactivity)
|
if (cause == S1ap_CauseRadioNetwork_user_inactivity)
|
||||||
{
|
{
|
||||||
mme_ue_t *mme_ue = enb_ue->mme_ue;
|
mme_ue_t *mme_ue = enb_ue->mme_ue;
|
||||||
status_t rv;
|
|
||||||
|
|
||||||
if (MME_HAVE_SGW_S11_PATH(mme_ue))
|
if (MME_HAVE_SGW_S11_PATH(mme_ue))
|
||||||
{
|
{
|
||||||
|
@ -441,7 +441,12 @@ void s1ap_handle_ue_context_release_request(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s1ap_handle_release_access_bearers_response(enb_ue);
|
S1ap_Cause_t cause;
|
||||||
|
|
||||||
|
cause.present = S1ap_Cause_PR_nas;
|
||||||
|
cause.choice.nas = S1ap_CauseNas_normal_release;
|
||||||
|
rv = s1ap_send_ue_context_release_commmand(enb_ue, &cause);
|
||||||
|
d_assert(rv == CORE_OK, return, "s1ap send error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -471,26 +476,6 @@ void s1ap_handle_ue_context_release_request(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void s1ap_handle_release_access_bearers_response(enb_ue_t *enb_ue)
|
|
||||||
{
|
|
||||||
status_t rv;
|
|
||||||
mme_enb_t *enb = NULL;
|
|
||||||
pkbuf_t *s1apbuf;
|
|
||||||
S1ap_Cause_t cause;
|
|
||||||
|
|
||||||
d_assert(enb_ue, return, "Null param");
|
|
||||||
enb = enb_ue->enb;
|
|
||||||
d_assert(enb, return, "Null param");
|
|
||||||
|
|
||||||
cause.present = S1ap_Cause_PR_nas;
|
|
||||||
cause.choice.nas = S1ap_CauseNas_normal_release;
|
|
||||||
|
|
||||||
rv = s1ap_build_ue_context_release_commmand(&s1apbuf, enb_ue, &cause);
|
|
||||||
d_assert(rv == CORE_OK && s1apbuf, return, "s1ap build error");
|
|
||||||
|
|
||||||
d_assert(s1ap_send_to_enb(enb, s1apbuf) == CORE_OK,, "s1ap send error");
|
|
||||||
}
|
|
||||||
|
|
||||||
void s1ap_handle_ue_context_release_complete(
|
void s1ap_handle_ue_context_release_complete(
|
||||||
mme_enb_t *enb, s1ap_message_t *message)
|
mme_enb_t *enb, s1ap_message_t *message)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,9 +26,6 @@ CORE_DECLARE(void) s1ap_handle_ue_context_release_request(
|
||||||
CORE_DECLARE(void) s1ap_handle_ue_context_release_complete(
|
CORE_DECLARE(void) s1ap_handle_ue_context_release_complete(
|
||||||
mme_enb_t *enb, s1ap_message_t *message);
|
mme_enb_t *enb, s1ap_message_t *message);
|
||||||
|
|
||||||
CORE_DECLARE(void) s1ap_handle_release_access_bearers_response(
|
|
||||||
enb_ue_t *enb_ue);
|
|
||||||
|
|
||||||
/* FIXME : Can I move the function to EMM handler? */
|
/* FIXME : Can I move the function to EMM handler? */
|
||||||
CORE_DECLARE(void) s1ap_handle_paging(mme_ue_t *mme_ue);
|
CORE_DECLARE(void) s1ap_handle_paging(mme_ue_t *mme_ue);
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
|
|
||||||
#include "mme_event.h"
|
#include "mme_event.h"
|
||||||
|
|
||||||
#include "s1ap_path.h"
|
#include "s1ap_build.h"
|
||||||
#include "nas_security.h"
|
#include "nas_security.h"
|
||||||
|
#include "s1ap_path.h"
|
||||||
|
|
||||||
static int _s1ap_accept_cb(net_sock_t *net_sock, void *data);
|
static int _s1ap_accept_cb(net_sock_t *net_sock, void *data);
|
||||||
|
|
||||||
|
@ -350,3 +351,23 @@ status_t s1ap_send_to_nas(enb_ue_t *enb_ue, S1ap_NAS_PDU_t *nasPdu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t s1ap_send_ue_context_release_commmand(
|
||||||
|
enb_ue_t *enb_ue, S1ap_Cause_t *cause)
|
||||||
|
{
|
||||||
|
status_t rv;
|
||||||
|
mme_enb_t *enb = NULL;
|
||||||
|
pkbuf_t *s1apbuf = NULL;
|
||||||
|
|
||||||
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
||||||
|
d_assert(cause, return CORE_ERROR, "Null param");
|
||||||
|
enb = enb_ue->enb;
|
||||||
|
d_assert(enb, return CORE_ERROR, "Null param");
|
||||||
|
|
||||||
|
rv = s1ap_build_ue_context_release_commmand(&s1apbuf, enb_ue, cause);
|
||||||
|
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
|
||||||
|
|
||||||
|
d_assert(s1ap_send_to_enb(enb, s1apbuf) == CORE_OK,
|
||||||
|
return CORE_ERROR, "s1ap send error");
|
||||||
|
|
||||||
|
return CORE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ CORE_DECLARE(status_t) s1ap_send_to_enb(mme_enb_t *enb, pkbuf_t *pkb);
|
||||||
CORE_DECLARE(status_t) s1ap_send_to_nas(
|
CORE_DECLARE(status_t) s1ap_send_to_nas(
|
||||||
enb_ue_t *enb_ue, S1ap_NAS_PDU_t *nasPdu);
|
enb_ue_t *enb_ue, S1ap_NAS_PDU_t *nasPdu);
|
||||||
CORE_DECLARE(status_t) s1ap_send_to_esm(mme_ue_t *mme_ue, pkbuf_t *esmbuf);
|
CORE_DECLARE(status_t) s1ap_send_to_esm(mme_ue_t *mme_ue, pkbuf_t *esmbuf);
|
||||||
|
CORE_DECLARE(status_t) s1ap_send_ue_context_release_commmand(
|
||||||
|
enb_ue_t *enb_ue, S1ap_Cause_t *cause);
|
||||||
|
|
||||||
int _s1ap_recv_cb(net_sock_t *net_sock, void *data);
|
int _s1ap_recv_cb(net_sock_t *net_sock, void *data);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue