diff --git a/src/mme/emm_build.c b/src/mme/emm_build.c index 0eda96d28..361575653 100644 --- a/src/mme/emm_build.c +++ b/src/mme/emm_build.c @@ -8,104 +8,6 @@ #include "mme_kdf.h" #include "emm_build.h" -status_t emm_build_identity_request( - pkbuf_t **emmbuf, mme_ue_t *mme_ue) -{ - nas_message_t message; - nas_identity_request_t *identity_request = - &message.emm.identity_request; - - d_assert(mme_ue, return CORE_ERROR, "Null param"); - - memset(&message, 0, sizeof(message)); - message.emm.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; - message.emm.h.message_type = NAS_IDENTITY_REQUEST; - - /* Request IMSI */ - identity_request->identity_type.type = NAS_IDENTITY_TYPE_2_IMSI; - - d_assert(nas_plain_encode(emmbuf, &message) == CORE_OK && *emmbuf,,); - - return CORE_OK; -} -status_t emm_build_security_mode_command( - pkbuf_t **emmbuf, mme_ue_t *mme_ue) -{ - status_t rv; - int i; - - nas_message_t message; - nas_security_mode_command_t *security_mode_command = - &message.emm.security_mode_command; - nas_security_algorithms_t *selected_nas_security_algorithms = - &security_mode_command->selected_nas_security_algorithms; - nas_key_set_identifier_t *nas_key_set_identifier = - &security_mode_command->nas_key_set_identifier; - nas_ue_security_capability_t *replayed_ue_security_capabilities = - &security_mode_command->replayed_ue_security_capabilities; - - d_assert(mme_ue, return CORE_ERROR, "Null param"); - - memset(&message, 0, sizeof(message)); - message.h.security_header_type = - NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_NEW_SECURITY_CONTEXT; - message.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; - - message.emm.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; - message.emm.h.message_type = NAS_SECURITY_MODE_COMMAND; - - for (i = 0; i < mme_self()->num_of_integrity_order; i++) - { - if (mme_ue->ue_network_capability.eia & - (0x80 >> mme_self()->integrity_order[i])) - { - mme_ue->selected_int_algorithm = mme_self()->integrity_order[i]; - break; - } - } - for (i = 0; i < mme_self()->num_of_ciphering_order; i++) - { - if (mme_ue->ue_network_capability.eea & - (0x80 >> mme_self()->ciphering_order[i])) - { - mme_ue->selected_enc_algorithm = mme_self()->ciphering_order[i]; - break; - } - } - - selected_nas_security_algorithms->type_of_integrity_protection_algorithm = - mme_ue->selected_int_algorithm; - selected_nas_security_algorithms->type_of_ciphering_algorithm = - mme_ue->selected_enc_algorithm; - - nas_key_set_identifier->tsc = 0; - nas_key_set_identifier->nas_key_set_identifier = 0; - - replayed_ue_security_capabilities->length = - sizeof(replayed_ue_security_capabilities->eea) + - sizeof(replayed_ue_security_capabilities->eia) + - sizeof(replayed_ue_security_capabilities->uea) + - sizeof(replayed_ue_security_capabilities->uia) + - sizeof(replayed_ue_security_capabilities->gea); - replayed_ue_security_capabilities->eea = mme_ue->ue_network_capability.eea; - replayed_ue_security_capabilities->eia = mme_ue->ue_network_capability.eia; - replayed_ue_security_capabilities->uea = mme_ue->ue_network_capability.uea; - replayed_ue_security_capabilities->uia = mme_ue->ue_network_capability.uia; - replayed_ue_security_capabilities->gea = - (mme_ue->ms_network_capability.gea1 << 6) | - mme_ue->ms_network_capability.extended_gea; - - mme_kdf_nas(MME_KDF_NAS_INT_ALG, mme_ue->selected_int_algorithm, - mme_ue->kasme, mme_ue->knas_int); - mme_kdf_nas(MME_KDF_NAS_ENC_ALG, mme_ue->selected_enc_algorithm, - mme_ue->kasme, mme_ue->knas_enc); - - rv = nas_security_encode(emmbuf, mme_ue, &message); - d_assert(rv == CORE_OK && *emmbuf, return CORE_ERROR, "emm build error"); - - return CORE_OK; -} - status_t emm_build_attach_accept( pkbuf_t **emmbuf, mme_ue_t *mme_ue, pkbuf_t *esmbuf) { @@ -206,6 +108,126 @@ status_t emm_build_attach_reject( return CORE_OK; } +status_t emm_build_identity_request( + pkbuf_t **emmbuf, mme_ue_t *mme_ue) +{ + nas_message_t message; + nas_identity_request_t *identity_request = + &message.emm.identity_request; + + d_assert(mme_ue, return CORE_ERROR, "Null param"); + + memset(&message, 0, sizeof(message)); + message.emm.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; + message.emm.h.message_type = NAS_IDENTITY_REQUEST; + + /* Request IMSI */ + identity_request->identity_type.type = NAS_IDENTITY_TYPE_2_IMSI; + + d_assert(nas_plain_encode(emmbuf, &message) == CORE_OK && *emmbuf,,); + + return CORE_OK; +} + +status_t emm_build_security_mode_command( + pkbuf_t **emmbuf, mme_ue_t *mme_ue) +{ + status_t rv; + int i; + + nas_message_t message; + nas_security_mode_command_t *security_mode_command = + &message.emm.security_mode_command; + nas_security_algorithms_t *selected_nas_security_algorithms = + &security_mode_command->selected_nas_security_algorithms; + nas_key_set_identifier_t *nas_key_set_identifier = + &security_mode_command->nas_key_set_identifier; + nas_ue_security_capability_t *replayed_ue_security_capabilities = + &security_mode_command->replayed_ue_security_capabilities; + + d_assert(mme_ue, return CORE_ERROR, "Null param"); + + memset(&message, 0, sizeof(message)); + message.h.security_header_type = + NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_NEW_SECURITY_CONTEXT; + message.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; + + message.emm.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; + message.emm.h.message_type = NAS_SECURITY_MODE_COMMAND; + + for (i = 0; i < mme_self()->num_of_integrity_order; i++) + { + if (mme_ue->ue_network_capability.eia & + (0x80 >> mme_self()->integrity_order[i])) + { + mme_ue->selected_int_algorithm = mme_self()->integrity_order[i]; + break; + } + } + for (i = 0; i < mme_self()->num_of_ciphering_order; i++) + { + if (mme_ue->ue_network_capability.eea & + (0x80 >> mme_self()->ciphering_order[i])) + { + mme_ue->selected_enc_algorithm = mme_self()->ciphering_order[i]; + break; + } + } + + selected_nas_security_algorithms->type_of_integrity_protection_algorithm = + mme_ue->selected_int_algorithm; + selected_nas_security_algorithms->type_of_ciphering_algorithm = + mme_ue->selected_enc_algorithm; + + nas_key_set_identifier->tsc = 0; + nas_key_set_identifier->nas_key_set_identifier = 0; + + replayed_ue_security_capabilities->length = + sizeof(replayed_ue_security_capabilities->eea) + + sizeof(replayed_ue_security_capabilities->eia) + + sizeof(replayed_ue_security_capabilities->uea) + + sizeof(replayed_ue_security_capabilities->uia) + + sizeof(replayed_ue_security_capabilities->gea); + replayed_ue_security_capabilities->eea = mme_ue->ue_network_capability.eea; + replayed_ue_security_capabilities->eia = mme_ue->ue_network_capability.eia; + replayed_ue_security_capabilities->uea = mme_ue->ue_network_capability.uea; + replayed_ue_security_capabilities->uia = mme_ue->ue_network_capability.uia; + replayed_ue_security_capabilities->gea = + (mme_ue->ms_network_capability.gea1 << 6) | + mme_ue->ms_network_capability.extended_gea; + + mme_kdf_nas(MME_KDF_NAS_INT_ALG, mme_ue->selected_int_algorithm, + mme_ue->kasme, mme_ue->knas_int); + mme_kdf_nas(MME_KDF_NAS_ENC_ALG, mme_ue->selected_enc_algorithm, + mme_ue->kasme, mme_ue->knas_enc); + + rv = nas_security_encode(emmbuf, mme_ue, &message); + d_assert(rv == CORE_OK && *emmbuf, return CORE_ERROR, "emm build error"); + + return CORE_OK; +} + +status_t emm_build_detach_accept(pkbuf_t **emmbuf, mme_ue_t *mme_ue) +{ + status_t rv; + nas_message_t message; + + d_assert(mme_ue, return CORE_ERROR, "Null param"); + + memset(&message, 0, sizeof(message)); + message.h.security_header_type = + NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED; + message.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; + + message.emm.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; + message.emm.h.message_type = NAS_DETACH_ACCEPT; + + rv = nas_security_encode(emmbuf, mme_ue, &message); + d_assert(rv == CORE_OK && emmbuf, return CORE_ERROR, "emm build error"); + + return CORE_OK; +} + status_t emm_build_tau_accept(pkbuf_t **emmbuf, mme_ue_t *mme_ue) { nas_message_t message; diff --git a/src/mme/emm_build.h b/src/mme/emm_build.h index bf79c4f88..fc84d11ee 100644 --- a/src/mme/emm_build.h +++ b/src/mme/emm_build.h @@ -7,17 +7,23 @@ extern "C" { #endif /* __cplusplus */ -CORE_DECLARE(status_t) emm_build_identity_request( - pkbuf_t **emmbuf, mme_ue_t *mme_ue); -CORE_DECLARE(status_t) emm_build_security_mode_command( - pkbuf_t **emmbuf, mme_ue_t *mme_ue); CORE_DECLARE(status_t) emm_build_attach_accept( pkbuf_t **emmbuf, mme_ue_t *mme_ue, pkbuf_t *esmbuf); CORE_DECLARE(status_t) emm_build_attach_reject( pkbuf_t **emmbuf, nas_emm_cause_t emm_cause, pkbuf_t *esmbuf); + +CORE_DECLARE(status_t) emm_build_identity_request( + pkbuf_t **emmbuf, mme_ue_t *mme_ue); +CORE_DECLARE(status_t) emm_build_security_mode_command( + pkbuf_t **emmbuf, mme_ue_t *mme_ue); + +CORE_DECLARE(status_t) emm_build_detach_accept( + pkbuf_t **emmbuf, mme_ue_t *mme_ue); + CORE_DECLARE(status_t) emm_build_tau_accept(pkbuf_t **emmbuf, mme_ue_t *mme_ue); CORE_DECLARE(status_t) emm_build_tau_reject(pkbuf_t **emmbuf, nas_emm_cause_t emm_cause,mme_ue_t *mme_ue); + CORE_DECLARE(status_t) emm_build_service_reject(pkbuf_t **emmbuf, nas_emm_cause_t emm_cause, mme_ue_t *mme_ue); diff --git a/src/mme/emm_handler.c b/src/mme/emm_handler.c index f2e9b15f2..da0df4cb2 100644 --- a/src/mme/emm_handler.c +++ b/src/mme/emm_handler.c @@ -10,14 +10,10 @@ #include "mme_kdf.h" #include "nas_security.h" #include "nas_conv.h" -#include "esm_build.h" -#include "emm_build.h" -#include "s1ap_build.h" + #include "s1ap_path.h" #include "nas_path.h" #include "mme_fd_path.h" - -#include "mme_s11_build.h" #include "mme_gtp_path.h" #include "emm_handler.h" @@ -255,25 +251,52 @@ void emm_handle_identity_response( d_assert(MME_UE_HAVE_IMSI(mme_ue), return, "No IMSI in IDENTITY_RESPONSE"); - if (SECURITY_CONTEXT_IS_VALID(mme_ue)) + if (mme_ue->nas_eps.type == MME_UE_EPS_ATTACH_TYPE) /* ATTACH_REQUEST */ { - 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)) + if (SECURITY_CONTEXT_IS_VALID(mme_ue)) { - rv = mme_gtp_send_delete_all_sessions(mme_ue); - d_assert(rv == CORE_OK, return, - "mme_gtp_send_delete_all_sessions failed"); + 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 { - mme_s6a_send_air(mme_ue); + 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); + } + } + else if (mme_ue->nas_eps.type == MME_UE_EPS_UPDATE_TYPE) /* TAU_REQUEST */ + { + if (SECURITY_CONTEXT_IS_VALID(mme_ue)) + { + /* 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)) + { + mme_s6a_send_air(mme_ue); + FSM_TRAN(&mme_ue->sm, &emm_state_authentication); + } + else + { + /* Send TAU reject */ + nas_send_tau_reject(mme_ue, + EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); + FSM_TRAN(&mme_ue->sm, &emm_state_detached); + } } - FSM_TRAN(&mme_ue->sm, &emm_state_authentication); } } @@ -341,72 +364,30 @@ void emm_handle_detach_request( } else { - emm_handle_detach_accept(mme_ue); + rv = nas_send_detach_accept(mme_ue); + d_assert(rv == CORE_OK, return, + "nas_send_detach_accept failed"); } } -void emm_handle_detach_accept(mme_ue_t *mme_ue) -{ - status_t rv; - enb_ue_t *enb_ue = NULL; - nas_message_t message; - pkbuf_t *emmbuf = 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"); - - /* reply with detach accept */ - if ((mme_ue->detach_type.switch_off & 0x1) == 0) - { - memset(&message, 0, sizeof(message)); - message.h.security_header_type = - NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED; - message.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; - - message.emm.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; - message.emm.h.message_type = NAS_DETACH_ACCEPT; - - d_trace(3, "[NAS] Detach accept : UE[%s] <-- EMM\n", - mme_ue->imsi_bcd); - - rv = nas_security_encode(&emmbuf, mme_ue, &message); - d_assert(rv == CORE_OK && emmbuf, return, "emm build error"); - d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,); - } - - /* FIXME : delay is needed */ - cause.present = S1ap_Cause_PR_nas; - cause.choice.nas = S1ap_CauseNas_detach; - rv = s1ap_send_ue_context_release_commmand(enb_ue, &cause); - d_assert(rv == CORE_OK, , "s1ap send error"); -} - void emm_handle_service_request( mme_ue_t *mme_ue, nas_service_request_t *service_request) { status_t rv; - pkbuf_t *s1apbuf = NULL; - enb_ue_t *enb_ue = NULL; - mme_sess_t *sess = NULL; d_assert(mme_ue, return, "Null param"); - enb_ue = mme_ue->enb_ue; - d_assert(enb_ue, return, "Null param"); if (!MME_UE_HAVE_IMSI(mme_ue)) { - /* Unknown UE. Send Service_reject to force UE to attach */ + /* Unknown UE. Send Service_reject to force UE to attach + * + * FIXME : how about FSM_TRAN(&mme_ue->sm, emm_state_identity); + */ nas_send_service_reject(mme_ue, EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); - return; } else { - sess = mme_sess_first(mme_ue); - d_assert(sess, return, "Null param"); - CLEAR_PAGING_INFO(mme_ue); /* Update Kenb */ @@ -414,10 +395,8 @@ void emm_handle_service_request( { mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32, mme_ue->kenb); - rv = s1ap_build_initial_context_setup_request(&s1apbuf, sess, NULL); - d_assert(rv == CORE_OK && s1apbuf, return, "s1ap build error"); - - d_assert(nas_send_to_enb(enb_ue, s1apbuf) == CORE_OK,, "s1ap send error"); + rv = s1ap_send_initial_context_setup_request(mme_ue); + d_assert(rv == CORE_OK, return, "s1ap send error"); } else { @@ -529,31 +508,6 @@ void emm_handle_tau_request( guti.m_tmsi, MME_UE_HAVE_IMSI(mme_ue) ? mme_ue->imsi_bcd : "Unknown"); - -#if 0 - if (!MME_UE_HAVE_IMSI(mme_ue)) - { - /* Unknown GUTI */ - - /* FIXME : Need to check if GUTI is allocated to old MME. - * if so , transmit context request to get the context of ue. - */ - - /* Send TAU reject */ - nas_send_tau_reject(mme_ue, - EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); - } - else if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) - { - /* Need Authencation */ - d_warn("Need Authenticatoin"); - } - else - { - /* Send TAU accept */ - nas_send_tau_accept(mme_ue); - } -#endif break; } default: @@ -567,16 +521,7 @@ void emm_handle_tau_request( if (!MME_UE_HAVE_IMSI(mme_ue)) { -#if 0 /* FIXME : TAU message does not have PDC_CONNECTIVTY message. - So even if ininiate the attach-like procedure, it failed. - */ - /* Unknown GUTI */ FSM_TRAN(&mme_ue->sm, &emm_state_identity); -#else - /* Send TAU reject */ - nas_send_tau_reject(mme_ue, - EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); -#endif } else { @@ -590,15 +535,16 @@ void emm_handle_tau_request( { 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"); + mme_s6a_send_air(mme_ue); + FSM_TRAN(&mme_ue->sm, &emm_state_authentication); } else { - mme_s6a_send_air(mme_ue); + /* Send TAU reject */ + nas_send_tau_reject(mme_ue, + EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); + FSM_TRAN(&mme_ue->sm, &emm_state_detached); } - FSM_TRAN(&mme_ue->sm, &emm_state_authentication); } } } diff --git a/src/mme/emm_handler.h b/src/mme/emm_handler.h index 0ec1cdfa7..c52e4815d 100644 --- a/src/mme/emm_handler.h +++ b/src/mme/emm_handler.h @@ -21,7 +21,6 @@ CORE_DECLARE(void) emm_handle_authentication_response( CORE_DECLARE(void) emm_handle_detach_request( mme_ue_t *mme_ue, nas_detach_request_from_ue_t *detach_request); -CORE_DECLARE(void) emm_handle_detach_accept(mme_ue_t *mme_ue); CORE_DECLARE(void) emm_handle_service_request( mme_ue_t *mme_ue, nas_service_request_t *service_request); diff --git a/src/mme/emm_sm.c b/src/mme/emm_sm.c index da31bf94d..b8a0c6230 100644 --- a/src/mme/emm_sm.c +++ b/src/mme/emm_sm.c @@ -60,6 +60,7 @@ void emm_state_detached(fsm_t *s, event_t *e) nas_message_t *message = (nas_message_t *)event_get_param4(e); d_assert(message, break, "Null param"); +#if 0 /* FIXME : Does it needed? */ if (message->emm.h.security_header_type == NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) { @@ -67,6 +68,7 @@ void emm_state_detached(fsm_t *s, event_t *e) mme_ue, &message->emm.service_request); break; } +#endif switch(message->emm.h.message_type) { @@ -76,12 +78,15 @@ void emm_state_detached(fsm_t *s, event_t *e) mme_ue, &message->emm.attach_request); break; } + +#if 0 /* FIXME : Does it needed? */ case NAS_TRACKING_AREA_UPDATE_REQUEST: { emm_handle_tau_request( mme_ue, &message->emm.tracking_area_update_request); break; } +#endif default: { d_warn("Unknown message type = %d", @@ -340,6 +345,22 @@ void emm_state_default_esm(fsm_t *s, event_t *e) FSM_TRAN(s, &emm_state_attached); 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"); + FSM_TRAN(s, &emm_state_attached); + break; + } case NAS_EMM_STATUS: { emm_handle_emm_status(mme_ue, &message->emm.emm_status); @@ -425,21 +446,6 @@ void emm_state_attached(fsm_t *s, event_t *e) mme_ue, &message->emm.tracking_area_update_request); 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: { d_warn("Unknown message(type:%d)", diff --git a/src/mme/esm_handler.c b/src/mme/esm_handler.c index 3f037ecc7..bc8301e0d 100644 --- a/src/mme/esm_handler.c +++ b/src/mme/esm_handler.c @@ -70,21 +70,9 @@ void esm_handle_pdn_connectivity_request(mme_bearer_t *bearer, { 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); + rv = nas_send_attach_accept(mme_ue); + d_assert(rv == CORE_OK, return, + "nas_send_attach_accept failed"); } else { @@ -135,20 +123,14 @@ void esm_handle_information_response(mme_sess_t *sess, void esm_handle_activate_default_bearer_accept(mme_bearer_t *bearer) { status_t rv; - mme_ue_t *mme_ue = NULL; - enb_ue_t *enb_ue = NULL; d_assert(bearer, return, "Null param"); - mme_ue = bearer->mme_ue; - d_assert(mme_ue, return, "Null param"); - enb_ue = mme_ue->enb_ue; - d_assert(enb_ue, return, "Null param"); mme_bearer_t *dedicated_bearer = mme_bearer_next(bearer); while(dedicated_bearer) { rv = nas_send_activate_dedicated_bearer_context_request( - enb_ue, dedicated_bearer); + dedicated_bearer); d_assert(rv == CORE_OK, return, "nas_send_activate_dedicated_bearer_context failed"); diff --git a/src/mme/mme_s11_handler.c b/src/mme/mme_s11_handler.c index 90fc58d81..93c494f9e 100644 --- a/src/mme/mme_s11_handler.c +++ b/src/mme/mme_s11_handler.c @@ -7,27 +7,27 @@ #include "mme_event.h" #include "mme_context.h" -#include "s1ap_build.h" #include "s1ap_path.h" +#include "mme_gtp_path.h" +#include "nas_path.h" +#include "mme_fd_path.h" + #include "mme_s11_build.h" #include "mme_s11_handler.h" -#include "mme_gtp_path.h" -#include "esm_build.h" -#include "nas_path.h" -void mme_s11_handle_create_session_response(gtp_xact_t *xact, - mme_bearer_t *bearer, gtp_create_session_response_t *rsp) +void mme_s11_handle_create_session_response( + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_create_session_response_t *rsp) { status_t rv; gtp_f_teid_t *sgw_s11_teid = NULL; gtp_f_teid_t *sgw_s1u_teid = NULL; - mme_ue_t *mme_ue = NULL; + mme_bearer_t *bearer = NULL; mme_sess_t *sess = NULL; pdn_t *pdn = NULL; d_assert(xact, return, "Null param"); - d_assert(bearer, return, "Null param"); + d_assert(mme_ue, return, "Null param"); d_assert(rsp, return, "Null param"); if (rsp->sender_f_teid_for_control_plane.presence == 0) @@ -45,9 +45,22 @@ void mme_s11_handle_create_session_response(gtp_xact_t *xact, d_error("No S1U TEID"); return; } + if (rsp->bearer_contexts_created.presence == 0) + { + d_error("No Bearer"); + return; + } + if (rsp->bearer_contexts_created. eps_bearer_id.presence == 0) + { + d_error("No EPS Bearer ID"); + return; + } - mme_ue = bearer->mme_ue; d_assert(mme_ue, return, "Null param"); + + bearer = mme_bearer_find_by_ue_ebi(mme_ue, + rsp->bearer_contexts_created.eps_bearer_id.u8); + d_assert(bearer, return, "Null param"); sess = bearer->sess; d_assert(sess, return, "Null param"); pdn = sess->pdn; @@ -77,6 +90,19 @@ void mme_s11_handle_create_session_response(gtp_xact_t *xact, rv = gtp_xact_commit(xact); d_assert(rv == CORE_OK, return, "xact_commit error"); + + if (FSM_CHECK(&mme_ue->sm, emm_state_default_esm)) + { + rv = nas_send_attach_accept(mme_ue); + d_assert(rv == CORE_OK, return, "nas_send_attach_accept failed"); + } + else if (FSM_CHECK(&mme_ue->sm, emm_state_attached)) + { + rv = nas_send_activate_default_bearer_context_request(bearer); + d_assert(rv == CORE_OK, return, "nas send failed"); + } + else + d_assert(0,, "Invalid EMM state"); } void mme_s11_handle_modify_bearer_response( @@ -95,6 +121,69 @@ void mme_s11_handle_modify_bearer_response( d_assert(rv == CORE_OK, return, "xact_commit error"); } +void mme_s11_handle_delete_session_response( + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_delete_session_response_t *rsp) +{ + status_t rv; + mme_sess_t *sess = NULL; + + d_assert(rsp, return, "Null param"); + sess = GTP_XACT_RETRIEVE_SESSION(xact); + d_assert(sess, return, "Null param"); + + if (rsp->cause.presence == 0) + { + d_error("No Cause"); + return; + } + + d_trace(3, "[GTP] Delete Session Response : MME[%d] <-- SGW[%d]\n", + mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + + rv = gtp_xact_commit(xact); + d_assert(rv == CORE_OK, return, "xact_commit error"); + + if (FSM_CHECK(&mme_ue->sm, emm_state_authentication)) + { + mme_sess_remove(sess); + if (mme_sess_first(mme_ue) == NULL) + { + CLEAR_SGW_S11_PATH(mme_ue); + mme_s6a_send_air(mme_ue); + } + } + else if (FSM_CHECK(&mme_ue->sm, emm_state_detached)) + { + mme_sess_remove(sess); + if (mme_sess_first(mme_ue) == NULL) + { + CLEAR_SGW_S11_PATH(mme_ue); + rv = nas_send_detach_accept(mme_ue); + d_assert(rv == CORE_OK, return, "nas_send_detach_accept failed"); + + } + } + else if (FSM_CHECK(&mme_ue->sm, emm_state_attached)) + { + mme_bearer_t *bearer = mme_default_bearer_in_sess(sess); + d_assert(bearer, return, "Null param"); + + if (FSM_CHECK(&bearer->sm, esm_state_disconnect)) + { + + rv = nas_send_deactivate_bearer_context_request(bearer); + d_assert(rv == CORE_OK, return, + "nas_send_deactivate_bearer_context_request failed"); + } + else + { + d_assert(0,, "Invalid ESM state"); + } + } + else + d_assert(0,, "Invalid EMM state"); + +} void mme_s11_handle_create_bearer_request( gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_create_bearer_request_t *req) { @@ -181,11 +270,16 @@ void mme_s11_handle_release_access_bearers_response( gtp_release_access_bearers_response_t *rsp) { status_t rv; + enb_ue_t *enb_ue = NULL; + S1ap_Cause_t cause; d_assert(xact, return, "Null param"); d_assert(mme_ue, return, "Null param"); d_assert(rsp, return, "Null param"); + enb_ue = mme_ue->enb_ue; + d_assert(enb_ue, return, "Null param"); + if (rsp->cause.presence == 0) { d_error("No Cause"); @@ -197,6 +291,11 @@ void mme_s11_handle_release_access_bearers_response( rv = gtp_xact_commit(xact); d_assert(rv == CORE_OK, return, "xact_commit error"); + + 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"); } void mme_s11_handle_downlink_data_notification( diff --git a/src/mme/mme_s11_handler.h b/src/mme/mme_s11_handler.h index 69c628e45..9ba8d495f 100644 --- a/src/mme/mme_s11_handler.h +++ b/src/mme/mme_s11_handler.h @@ -10,8 +10,7 @@ extern "C" { #endif /* __cplusplus */ CORE_DECLARE(void) mme_s11_handle_create_session_response( - gtp_xact_t *xact, mme_bearer_t *bearer, - gtp_create_session_response_t *rsp); + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_create_session_response_t *rsp); CORE_DECLARE(void) mme_s11_handle_modify_bearer_response( gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_modify_bearer_response_t *rsp); CORE_DECLARE(void) mme_s11_handle_delete_session_response( diff --git a/src/mme/mme_s6a_handler.c b/src/mme/mme_s6a_handler.c index 33fb9d16e..2ed15bfb8 100644 --- a/src/mme/mme_s6a_handler.c +++ b/src/mme/mme_s6a_handler.c @@ -2,10 +2,11 @@ #include "core_debug.h" -#include "mme_s6a_handler.h" #include "s6a_message.h" #include "nas_path.h" +#include "mme_s6a_handler.h" + void mme_s6a_handle_aia(mme_ue_t *mme_ue, s6a_aia_message_t *aia_message) { pkbuf_t *emmbuf = NULL; @@ -44,6 +45,7 @@ void mme_s6a_handle_aia(mme_ue_t *mme_ue, s6a_aia_message_t *aia_message) void mme_s6a_handle_ula(mme_ue_t *mme_ue, s6a_ula_message_t *ula_message) { + status_t rv; s6a_subscription_data_t *subscription_data = NULL; d_assert(mme_ue, return, "Null param"); @@ -53,4 +55,22 @@ void mme_s6a_handle_ula(mme_ue_t *mme_ue, s6a_ula_message_t *ula_message) memcpy(&mme_ue->subscription_data, subscription_data, sizeof(s6a_subscription_data_t)); + + if (FSM_CHECK(&mme_ue->sm, emm_state_default_esm)) + { + if (mme_ue->nas_eps.type == MME_UE_EPS_ATTACH_TYPE) /* ATTACH_REQUEST */ + { + rv = nas_send_emm_to_esm(mme_ue, &mme_ue->pdn_connectivity_request); + d_assert(rv == CORE_OK,, "nas_send_emm_to_esm failed"); + } + else if (mme_ue->nas_eps.type == MME_UE_EPS_UPDATE_TYPE) /* TAU_REQUEST */ + { + rv = nas_send_tau_accept(mme_ue); + d_assert(rv == CORE_OK, return, "nas_send_tau_accept failed"); + } + else + d_assert(0,, "Invalid Type(%d)", mme_ue->nas_eps.type); + } + else + d_assert(0,, "Invaild EMM state"); } diff --git a/src/mme/mme_sm.c b/src/mme/mme_sm.c index 7bc26342e..aec2b0081 100644 --- a/src/mme/mme_sm.c +++ b/src/mme/mme_sm.c @@ -6,18 +6,16 @@ #include "mme_event.h" -#include "s1ap_build.h" #include "s1ap_handler.h" #include "s1ap_path.h" -#include "mme_fd_path.h" -#include "mme_gtp_path.h" -#include "mme_s11_handler.h" #include "nas_security.h" #include "nas_path.h" #include "emm_handler.h" -#include "esm_build.h" #include "esm_handler.h" +#include "mme_gtp_path.h" +#include "mme_s11_handler.h" #include "fd_lib.h" +#include "mme_fd_path.h" #include "mme_s6a_handler.h" void mme_state_initial(fsm_t *s, event_t *e) @@ -255,7 +253,6 @@ void mme_state_operational(fsm_t *s, event_t *e) } pkbuf_free(pkbuf); - break; } case MME_EVT_S6A_MESSAGE: @@ -270,56 +267,31 @@ void mme_state_operational(fsm_t *s, event_t *e) s6a_message = s6abuf->payload; d_assert(s6a_message, return, "Null param"); + if (s6a_message->result_code != ER_DIAMETER_SUCCESS) + { + rv = nas_send_attach_reject(mme_ue, + S1ap_CauseNas_authentication_failure, + EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED, + ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); + d_assert(rv == CORE_OK,, + "nas_send_attach_reject failed"); + + mme_ue_remove(mme_ue); + + pkbuf_free(s6abuf); + break; + } + switch(s6a_message->cmd_code) { case S6A_CMD_CODE_AUTHENTICATION_INFORMATION: { - if (s6a_message->result_code != ER_DIAMETER_SUCCESS) - { - rv = nas_send_attach_reject(mme_ue, - S1ap_CauseNas_authentication_failure, - EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED, - ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); - d_assert(rv == CORE_OK,, - "nas_send_attach_reject failed"); - - mme_ue_remove(mme_ue); - break; - } - mme_s6a_handle_aia(mme_ue, &s6a_message->aia_message); break; } case S6A_CMD_CODE_UPDATE_LOCATION: { - if (s6a_message->result_code != ER_DIAMETER_SUCCESS) - { - rv = nas_send_attach_reject(mme_ue, - S1ap_CauseNas_unspecified, - EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED, - ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); - d_assert(rv == CORE_OK,, - "nas_send_attach_reject failed"); - - mme_ue_remove(mme_ue); - break; - } - mme_s6a_handle_ula(mme_ue, &s6a_message->ula_message); - - if (FSM_CHECK(&mme_ue->sm, emm_state_default_esm)) - { - rv = nas_send_emm_to_esm(mme_ue, - &mme_ue->pdn_connectivity_request); - d_assert(rv == CORE_OK,, - "nas_send_emm_to_esm failed"); - } - else if (FSM_CHECK(&mme_ue->sm, emm_state_attached)) - { - d_error("Not implemented for Tracking Area Update"); - } - else - d_assert(0,, "Invaild EMM state"); break; } default: @@ -339,7 +311,6 @@ void mme_state_operational(fsm_t *s, event_t *e) gtp_xact_t *xact = NULL; gtp_message_t message; mme_ue_t *mme_ue = NULL; - enb_ue_t *enb_ue = NULL; d_assert(pkbuf, break, "Null param"); d_assert(gnode, pkbuf_free(pkbuf); break, "Null param"); @@ -357,174 +328,26 @@ void mme_state_operational(fsm_t *s, event_t *e) switch(message.h.type) { case GTP_CREATE_SESSION_RESPONSE_TYPE: - { - mme_bearer_t *bearer = NULL; - - gtp_create_session_response_t *rsp - = &message.create_session_response; - d_assert(rsp, return, "Null param"); - - if (rsp->bearer_contexts_created.presence == 0) - { - d_error("No Bearer"); - return; - } - if (rsp->bearer_contexts_created. - eps_bearer_id.presence == 0) - { - d_error("No EPS Bearer ID"); - return; - } - - bearer = mme_bearer_find_by_ue_ebi(mme_ue, - rsp->bearer_contexts_created.eps_bearer_id.u8); - d_assert(bearer, return, "Null param"); - - mme_s11_handle_create_session_response(xact, bearer, rsp); - - if (FSM_CHECK(&mme_ue->sm, emm_state_default_esm)) - { - 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 if (FSM_CHECK(&mme_ue->sm, emm_state_attached)) - { - mme_sess_t *sess = NULL; - enb_ue_t *enb_ue = NULL; - pkbuf_t *esmbuf = NULL, *s1apbuf = NULL; - - sess = bearer->sess; - d_assert(sess, return, "Null param"); - enb_ue = mme_ue->enb_ue; - d_assert(enb_ue, return, "Null param"); - - rv = esm_build_activate_default_bearer_context_request( - &esmbuf, sess); - d_assert(rv == CORE_OK && esmbuf, return, - "esm build error"); - - d_trace(3, "[NAS] Activate default bearer " - "context request : EMM <-- ESM\n"); - - rv = s1ap_build_e_rab_setup_request( - &s1apbuf, bearer, esmbuf); - d_assert(rv == CORE_OK && s1apbuf, - pkbuf_free(esmbuf); return, "s1ap build error"); - - d_assert(nas_send_to_enb(enb_ue, s1apbuf) == CORE_OK,,); - } - else - d_assert(0, break, "Invalid EMM state"); - + mme_s11_handle_create_session_response( + xact, mme_ue, &message.create_session_response); break; - } case GTP_MODIFY_BEARER_RESPONSE_TYPE: mme_s11_handle_modify_bearer_response( xact, mme_ue, &message.modify_bearer_response); break; case GTP_DELETE_SESSION_RESPONSE_TYPE: - { - mme_sess_t *sess = NULL; - gtp_delete_session_response_t *rsp = - &message.delete_session_response; - - d_assert(rsp, return, "Null param"); - sess = GTP_XACT_RETRIEVE_SESSION(xact); - d_assert(sess, return, "Null param"); - - if (rsp->cause.presence == 0) - { - d_error("No Cause"); - return; - } - - d_trace(3, "[GTP] Delete Session Response : " - "MME[%d] <-- SGW[%d]\n", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - - rv = gtp_xact_commit(xact); - d_assert(rv == CORE_OK, return, "xact_commit error"); - - if (FSM_CHECK(&mme_ue->sm, emm_state_authentication)) - { - mme_sess_remove(sess); - if (mme_sess_first(mme_ue) == NULL) - { - CLEAR_SGW_S11_PATH(mme_ue); - mme_s6a_send_air(mme_ue); - } - } - else if (FSM_CHECK(&mme_ue->sm, emm_state_detached)) - { - mme_sess_remove(sess); - if (mme_sess_first(mme_ue) == NULL) - { - CLEAR_SGW_S11_PATH(mme_ue); - emm_handle_detach_accept(mme_ue); - } - } - else if (FSM_CHECK(&mme_ue->sm, emm_state_attached)) - { - mme_bearer_t *bearer = mme_default_bearer_in_sess(sess); - d_assert(bearer, return, "Null param"); - - if (FSM_CHECK(&bearer->sm, esm_state_disconnect)) - { - enb_ue = mme_ue->enb_ue; - d_assert(enb_ue, break, "Null param"); - - rv = nas_send_deactivate_bearer_context_request( - enb_ue, bearer); - d_assert(rv == CORE_OK, break, - "nas_send_deactivate_bearer" - "_context_request failed"); - } - else - { - d_assert(0, break, "Invalid ESM state"); - } - } - else - d_assert(0, break, "Invalid EMM state"); - + mme_s11_handle_delete_session_response( + xact, mme_ue, &message.delete_session_response); break; - } case GTP_CREATE_BEARER_REQUEST_TYPE: mme_s11_handle_create_bearer_request( xact, mme_ue, &message.create_bearer_request); break; case GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE: - { - S1ap_Cause_t cause; - - enb_ue = mme_ue->enb_ue; - d_assert(enb_ue, break, "Null param"); - mme_s11_handle_release_access_bearers_response( xact, mme_ue, &message.release_access_bearers_response); - - 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; - } - case GTP_DOWNLINK_DATA_NOTIFICATION_TYPE: - { mme_s11_handle_downlink_data_notification( xact, mme_ue, &message.downlink_data_notification); @@ -532,7 +355,6 @@ void mme_state_operational(fsm_t *s, event_t *e) /* Start T3413 */ tm_start(mme_ue->t3413); break; - } default: d_warn("Not implmeneted(type:%d)", message.h.type); break; diff --git a/src/mme/nas_path.c b/src/mme/nas_path.c index b9e6bea93..14fc6a7d4 100644 --- a/src/mme/nas_path.c +++ b/src/mme/nas_path.c @@ -8,10 +8,13 @@ #include "nas_path.h" #include "mme_event.h" -status_t nas_send_to_enb(enb_ue_t *enb_ue, pkbuf_t *pkbuf) +status_t nas_send_to_enb(mme_ue_t *mme_ue, pkbuf_t *pkbuf) { mme_enb_t *enb = NULL; + enb_ue_t *enb_ue = NULL; + d_assert(mme_ue, return CORE_ERROR, "Null param"); + enb_ue = mme_ue->enb_ue; d_assert(enb_ue, return CORE_ERROR, "Null param"); enb = enb_ue->enb; d_assert(enb, return CORE_ERROR, "Null param"); @@ -41,13 +44,13 @@ status_t nas_send_emm_to_esm( return CORE_OK; } -status_t nas_send_to_downlink_nas_transport( - mme_ue_t *mme_ue, pkbuf_t *pkbuf) +status_t nas_send_to_downlink_nas_transport(mme_ue_t *mme_ue, pkbuf_t *pkbuf) { status_t rv; pkbuf_t *s1apbuf = NULL; enb_ue_t *enb_ue = NULL; + d_assert(mme_ue, return CORE_ERROR, "Null param"); enb_ue = mme_ue->enb_ue; d_assert(enb_ue, return CORE_ERROR, "Null param"); @@ -55,21 +58,21 @@ status_t nas_send_to_downlink_nas_transport( d_assert(rv == CORE_OK && s1apbuf, pkbuf_free(pkbuf); return CORE_ERROR, "s1ap build error"); - return nas_send_to_enb(enb_ue, s1apbuf); + rv = nas_send_to_enb(mme_ue, s1apbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "nas send error"); + + return CORE_OK; } status_t nas_send_attach_accept(mme_ue_t *mme_ue) { status_t rv; mme_sess_t *sess = NULL; - enb_ue_t *enb_ue = NULL; pkbuf_t *esmbuf = NULL, *emmbuf = NULL, *s1apbuf = NULL; d_assert(mme_ue, return CORE_ERROR, "Null param"); sess = mme_sess_first(mme_ue); d_assert(sess, return CORE_ERROR, "Null param"); - enb_ue = mme_ue->enb_ue; - d_assert(enb_ue, return CORE_ERROR, "Null param"); rv = esm_build_activate_default_bearer_context_request(&esmbuf, sess); d_assert(rv == CORE_OK && esmbuf, return CORE_ERROR, "esm build error"); @@ -87,7 +90,8 @@ status_t nas_send_attach_accept(mme_ue_t *mme_ue) 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,,); + rv = nas_send_to_enb(mme_ue, s1apbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "nas send error"); return CORE_OK; } @@ -134,6 +138,38 @@ status_t nas_send_attach_reject(mme_ue_t *mme_ue, return CORE_OK; } +status_t nas_send_detach_accept(mme_ue_t *mme_ue) +{ + 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"); + + /* reply with detach accept */ + if ((mme_ue->detach_type.switch_off & 0x1) == 0) + { + rv = emm_build_detach_accept(&emmbuf, mme_ue); + d_assert(rv == CORE_OK && emmbuf, return CORE_ERROR, + "nas_build_detach_accept failed"); + + rv = nas_send_to_downlink_nas_transport(mme_ue, emmbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "nas send failed"); + } + + /* FIXME : delay is needed */ + cause.present = S1ap_Cause_PR_nas; + cause.choice.nas = S1ap_CauseNas_detach; + rv = s1ap_send_ue_context_release_commmand(enb_ue, &cause); + d_assert(rv == CORE_OK, return CORE_ERROR, "s1ap send error"); + + return CORE_OK; +} + + status_t nas_send_pdn_connectivity_reject( mme_sess_t *sess, nas_esm_cause_t esm_cause) { @@ -155,14 +191,44 @@ status_t nas_send_pdn_connectivity_reject( return CORE_OK; } -status_t nas_send_activate_dedicated_bearer_context_request( - enb_ue_t *enb_ue, mme_bearer_t *bearer) +status_t nas_send_activate_default_bearer_context_request(mme_bearer_t *bearer) { status_t rv; pkbuf_t *esmbuf = NULL, *s1apbuf = NULL; + mme_sess_t *sess = NULL; + mme_ue_t *mme_ue = NULL; - d_assert(enb_ue, return CORE_ERROR, "Null param"); d_assert(bearer, return CORE_ERROR, "Null param"); + sess = bearer->sess; + d_assert(sess, return CORE_ERROR, "Null param"); + mme_ue = bearer->mme_ue; + d_assert(mme_ue, return CORE_ERROR, "Null param"); + + rv = esm_build_activate_default_bearer_context_request(&esmbuf, sess); + d_assert(rv == CORE_OK && esmbuf, return CORE_ERROR, "esm build error"); + + d_trace(3, "[NAS] Activate default bearer context request : EMM <-- ESM\n"); + + rv = s1ap_build_e_rab_setup_request(&s1apbuf, bearer, esmbuf); + d_assert(rv == CORE_OK && s1apbuf, + pkbuf_free(esmbuf); return CORE_ERROR, "s1ap build error"); + + rv = nas_send_to_enb(mme_ue, s1apbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "nas send error"); + + return CORE_OK; +} + +status_t nas_send_activate_dedicated_bearer_context_request( + mme_bearer_t *bearer) +{ + status_t rv; + pkbuf_t *esmbuf = NULL, *s1apbuf = NULL; + mme_ue_t *mme_ue = NULL; + + d_assert(bearer, return CORE_ERROR, "Null param"); + mme_ue = bearer->mme_ue; + d_assert(mme_ue, return CORE_ERROR, "Null param"); rv = esm_build_activate_dedicated_bearer_context_request(&esmbuf, bearer); d_assert(rv == CORE_OK && esmbuf, return CORE_ERROR, "esm build error"); @@ -174,20 +240,22 @@ status_t nas_send_activate_dedicated_bearer_context_request( d_assert(rv == CORE_OK && s1apbuf, pkbuf_free(esmbuf); return CORE_ERROR, "s1ap build error"); - d_assert(nas_send_to_enb(enb_ue, s1apbuf) == CORE_OK,,); + rv = nas_send_to_enb(mme_ue, s1apbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "nas send error"); return CORE_OK; } -status_t nas_send_deactivate_bearer_context_request( - enb_ue_t *enb_ue, mme_bearer_t *bearer) +status_t nas_send_deactivate_bearer_context_request(mme_bearer_t *bearer) { status_t rv; pkbuf_t *esmbuf = NULL, *s1apbuf = NULL; S1ap_Cause_t cause; + mme_ue_t *mme_ue = NULL; - d_assert(enb_ue, return CORE_ERROR, "Null param"); d_assert(bearer, return CORE_ERROR, "Null param"); + mme_ue = bearer->mme_ue; + d_assert(mme_ue, return CORE_ERROR, "Null param"); rv = esm_build_deactivate_bearer_context_request( &esmbuf, bearer, ESM_CAUSE_REGULAR_DEACTIVATION); @@ -201,7 +269,8 @@ status_t nas_send_deactivate_bearer_context_request( d_assert(rv == CORE_OK && s1apbuf, pkbuf_free(esmbuf); return CORE_ERROR, "s1ap build error"); - d_assert(nas_send_to_enb(enb_ue, s1apbuf) == CORE_OK,,); + rv = nas_send_to_enb(mme_ue, s1apbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "nas send error"); return CORE_OK; } @@ -211,14 +280,16 @@ 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)) { + S1ap_Cause_t cause; + enb_ue = mme_ue->enb_ue; + + d_assert(enb_ue, return CORE_ERROR, "Null param"); + /* Build TAU accept */ rv = emm_build_tau_accept(&emmbuf, mme_ue); d_assert(rv == CORE_OK, return CORE_ERROR, "emm build error"); @@ -246,7 +317,8 @@ status_t nas_send_tau_accept(mme_ue_t *mme_ue) 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,,); + rv = nas_send_to_enb(mme_ue, s1apbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "nas send error"); } return CORE_OK; @@ -272,7 +344,8 @@ status_t nas_send_tau_reject(mme_ue_t *mme_ue, nas_emm_cause_t emm_cause) } /* Send Dl NAS to UE */ - d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,); + rv = nas_send_to_downlink_nas_transport(mme_ue, emmbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "nas dl send error"); /* FIXME : delay required before sending UE context release to make sure @@ -305,8 +378,8 @@ status_t nas_send_service_reject(mme_ue_t *mme_ue, nas_emm_cause_t emm_cause) } /* Send Dl NAS to UE */ - d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,); - + rv = nas_send_to_downlink_nas_transport(mme_ue, emmbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "nas dl send error"); /* FIXME : delay required before sending UE context release to make sure * that UE receive DL NAS ? */ diff --git a/src/mme/nas_path.h b/src/mme/nas_path.h index 6898b1a15..6ebdc846c 100644 --- a/src/mme/nas_path.h +++ b/src/mme/nas_path.h @@ -9,24 +9,31 @@ extern "C" { #endif /* __cplusplus */ -CORE_DECLARE(status_t) nas_send_to_enb(enb_ue_t *enb_ue, pkbuf_t *pkbuf); +CORE_DECLARE(status_t) nas_send_to_enb(mme_ue_t *mme_ue, pkbuf_t *pkbuf); CORE_DECLARE(status_t) nas_send_emm_to_esm( mme_ue_t *mme_ue, nas_esm_message_container_t *esm_message_container); CORE_DECLARE(status_t) nas_send_to_downlink_nas_transport( mme_ue_t *mme_ue, pkbuf_t *pkbuf); + CORE_DECLARE(status_t) nas_send_attach_accept(mme_ue_t *mme_ue); CORE_DECLARE(status_t) nas_send_attach_reject(mme_ue_t *mme_ue, e_S1ap_CauseNas s1ap_cause_nas, nas_emm_cause_t emm_cause, nas_esm_cause_t esm_cause); +CORE_DECLARE(status_t) nas_send_detach_accept(mme_ue_t *mme_ue); + CORE_DECLARE(status_t) nas_send_pdn_connectivity_reject( mme_sess_t *sess, nas_esm_cause_t esm_cause); +CORE_DECLARE(status_t) nas_send_activate_default_bearer_context_request( + mme_bearer_t *bearer); CORE_DECLARE(status_t) nas_send_activate_dedicated_bearer_context_request( - enb_ue_t *enb_ue, mme_bearer_t *bearer); + mme_bearer_t *bearer); CORE_DECLARE(status_t) nas_send_deactivate_bearer_context_request( - enb_ue_t *enb_ue, mme_bearer_t *bearer); + 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); + CORE_DECLARE(status_t) nas_send_service_reject(mme_ue_t *mme_ue, nas_emm_cause_t emm_cause); diff --git a/src/mme/s1ap_build.c b/src/mme/s1ap_build.c index 1efed6e1c..25e0b4174 100644 --- a/src/mme/s1ap_build.c +++ b/src/mme/s1ap_build.c @@ -10,6 +10,8 @@ #include "s1ap_build.h" #include "s1ap_conv.h" +static void s1ap_build_cause(S1ap_Cause_t *dst, S1ap_Cause_t *src); + status_t s1ap_build_setup_rsp(pkbuf_t **pkbuf) { int erval; @@ -402,35 +404,6 @@ status_t s1ap_build_e_rab_setup_request( return CORE_OK; } -static void s1ap_build_cause(S1ap_Cause_t *dst, S1ap_Cause_t *src) -{ - d_assert(src, return, "Null param"); - d_assert(dst, return, "Null param"); - - dst->present = src->present; - switch(dst->present) - { - case S1ap_Cause_PR_radioNetwork: - dst->choice.radioNetwork = src->choice.radioNetwork; - break; - case S1ap_Cause_PR_transport: - dst->choice.transport = src->choice.transport; - break; - case S1ap_Cause_PR_nas: - dst->choice.nas = src->choice.nas; - break; - case S1ap_Cause_PR_protocol: - dst->choice.protocol = src->choice.protocol; - break; - case S1ap_Cause_PR_misc: - dst->choice.misc = src->choice.misc; - break; - default: - d_error("Invalid src type : %d", dst->present); - break; - } -} - status_t s1ap_build_e_rab_release_command(pkbuf_t **s1apbuf, mme_bearer_t *bearer, pkbuf_t *esmbuf, S1ap_Cause_t *cause) { @@ -617,3 +590,33 @@ status_t s1ap_build_paging(pkbuf_t **s1apbuf, mme_ue_t *mme_ue) return CORE_OK; } + +static void s1ap_build_cause(S1ap_Cause_t *dst, S1ap_Cause_t *src) +{ + d_assert(src, return, "Null param"); + d_assert(dst, return, "Null param"); + + dst->present = src->present; + switch(dst->present) + { + case S1ap_Cause_PR_radioNetwork: + dst->choice.radioNetwork = src->choice.radioNetwork; + break; + case S1ap_Cause_PR_transport: + dst->choice.transport = src->choice.transport; + break; + case S1ap_Cause_PR_nas: + dst->choice.nas = src->choice.nas; + break; + case S1ap_Cause_PR_protocol: + dst->choice.protocol = src->choice.protocol; + break; + case S1ap_Cause_PR_misc: + dst->choice.misc = src->choice.misc; + break; + default: + d_error("Invalid src type : %d", dst->present); + break; + } +} + diff --git a/src/mme/s1ap_handler.c b/src/mme/s1ap_handler.c index aecede6a0..5205cf427 100644 --- a/src/mme/s1ap_handler.c +++ b/src/mme/s1ap_handler.c @@ -5,11 +5,11 @@ #include "mme_event.h" #include "s1ap_conv.h" -#include "s1ap_build.h" #include "s1ap_path.h" #include "nas_path.h" #include "mme_gtp_path.h" +#include "s1ap_build.h" #include "s1ap_handler.h" void s1ap_handle_s1_setup_request(mme_enb_t *enb, s1ap_message_t *message) @@ -250,15 +250,9 @@ void s1ap_handle_ue_capability_info_indication( void s1ap_handle_activate_default_bearer_accept(mme_bearer_t *bearer) { status_t rv; - mme_ue_t *mme_ue = NULL; - enb_ue_t *enb_ue = NULL; mme_bearer_t *dedicated_bearer = NULL; d_assert(bearer, return, "Null param"); - mme_ue = bearer->mme_ue; - d_assert(mme_ue, return, "Null param"); - enb_ue = mme_ue->enb_ue; - d_assert(enb_ue, return, "Null param"); rv = mme_gtp_send_modify_bearer_request(bearer); d_assert(rv == CORE_OK, return, @@ -268,7 +262,7 @@ void s1ap_handle_activate_default_bearer_accept(mme_bearer_t *bearer) while(dedicated_bearer) { rv = nas_send_activate_dedicated_bearer_context_request( - enb_ue, dedicated_bearer); + dedicated_bearer); d_assert(rv == CORE_OK, return, "nas_send_activate_dedicated_bearer_context failed"); @@ -499,7 +493,6 @@ void s1ap_handle_ue_context_release_complete( enb_ue_remove(enb_ue); } -/* FIXME : Where is a good location S1AP handler or EMM handler?*/ void s1ap_handle_paging(mme_ue_t *mme_ue) { pkbuf_t *s1apbuf = NULL; diff --git a/src/mme/s1ap_path.c b/src/mme/s1ap_path.c index eb931364e..cdbe3421a 100644 --- a/src/mme/s1ap_path.c +++ b/src/mme/s1ap_path.c @@ -4,8 +4,10 @@ #include "mme_event.h" -#include "s1ap_build.h" #include "nas_security.h" +#include "nas_path.h" + +#include "s1ap_build.h" #include "s1ap_path.h" static int _s1ap_accept_cb(net_sock_t *net_sock, void *data); @@ -350,6 +352,25 @@ status_t s1ap_send_to_nas(enb_ue_t *enb_ue, S1ap_NAS_PDU_t *nasPdu) return CORE_OK; } +status_t s1ap_send_initial_context_setup_request(mme_ue_t *mme_ue) +{ + status_t rv; + pkbuf_t *s1apbuf = NULL; + mme_sess_t *sess = NULL; + + d_assert(mme_ue, return CORE_ERROR, "Null param"); + + sess = mme_sess_first(mme_ue); + d_assert(sess, return CORE_ERROR, "Null param"); + + rv = s1ap_build_initial_context_setup_request(&s1apbuf, sess, NULL); + d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error"); + + rv = nas_send_to_enb(mme_ue, s1apbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "s1ap send error"); + + return CORE_OK; +} status_t s1ap_send_ue_context_release_commmand( enb_ue_t *enb_ue, S1ap_Cause_t *cause) diff --git a/src/mme/s1ap_path.h b/src/mme/s1ap_path.h index 6031dac3d..0bfcc39a2 100644 --- a/src/mme/s1ap_path.h +++ b/src/mme/s1ap_path.h @@ -19,6 +19,9 @@ CORE_DECLARE(status_t) s1ap_send_to_enb(mme_enb_t *enb, pkbuf_t *pkb); CORE_DECLARE(status_t) s1ap_send_to_nas( 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_initial_context_setup_request( + mme_ue_t *mme_ue); CORE_DECLARE(status_t) s1ap_send_ue_context_release_commmand( enb_ue_t *enb_ue, S1ap_Cause_t *cause);