From 1c50feebd2adb4a6b899c7957975475aa9563442 Mon Sep 17 00:00:00 2001 From: Lionel Gauthier <lionel.gauthier@eurecom.fr> Date: Tue, 23 Dec 2014 13:36:31 +0000 Subject: [PATCH] S1AP UE context release git-svn-id: http://svn.eurecom.fr/openair4G/trunk@6315 818b1a75-f10b-46b9-bf7c-635c3b92a50f --- openair2/COMMON/s1ap_messages_types.h | 18 +++- openair2/RRC/LITE/rrc_eNB.c | 11 ++- openair2/RRC/LITE/rrc_eNB_S1AP.c | 118 +++++++++++++++++--------- openair2/RRC/LITE/rrc_eNB_S1AP.h | 13 ++- 4 files changed, 115 insertions(+), 45 deletions(-) diff --git a/openair2/COMMON/s1ap_messages_types.h b/openair2/COMMON/s1ap_messages_types.h index 2a21e8a8ef..04e4209b67 100644 --- a/openair2/COMMON/s1ap_messages_types.h +++ b/openair2/COMMON/s1ap_messages_types.h @@ -475,6 +475,7 @@ typedef struct s1ap_paging_ind_s { paging_priority_t paging_priority; } s1ap_paging_ind_t; +// S1AP --> RRC messages typedef struct s1ap_ue_release_command_s { unsigned eNB_ue_s1ap_id:24; @@ -483,10 +484,21 @@ typedef struct s1ap_ue_release_command_s { //-------------------------------------------------------------------------------------------// -// S1AP <-> RRC messages +typedef enum S1ap_Cause_e { + S1AP_CAUSE_NOTHING, /* No components present */ + S1AP_CAUSE_RADIO_NETWORK, + S1AP_CAUSE_TRANSPORT, + S1AP_CAUSE_NAS, + S1AP_CAUSE_PROTOCOL, + S1AP_CAUSE_MISC, + /* Extensions may appear below */ + +} s1ap_Cause_t; +// S1AP <-- RRC messages typedef struct s1ap_ue_release_req_s { - unsigned eNB_ue_s1ap_id:24; - /* TODO: add cause */ + unsigned eNB_ue_s1ap_id:24; + s1ap_Cause_t cause; + long cause_value; } s1ap_ue_release_req_t, s1ap_ue_release_resp_t; #endif /* S1AP_MESSAGES_TYPES_H_ */ diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index 4a3cfe56d7..f358f42273 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -540,9 +540,18 @@ void rrc_eNB_free_UE_index( LOG_W(RRC, "[eNB %d] Removing UE %d rv 0x%" PRIx64 "\n", enb_mod_idP, ue_mod_idP, eNB_rrc_inst[enb_mod_idP].Info.UE_list[ue_mod_idP]); + +#if defined(ENABLE_USE_MME) + rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_mod_idP, S1AP_CAUSE_RADIO_NETWORK, 0); // ue_mod_idP ??? or ??? + /* From 3GPP 36300v10 p129 : 19.2.2.2.2 S1 UE Context Release Request (eNB triggered) + * If the E-UTRAN internal reason is a radio link failure detected in the eNB, the eNB shall wait a sufficient time before + * triggering the S1 UE Context Release Request procedure + * in order to allow the UE to perform the NAS recovery + * procedure, see TS 23.401 [17]. + */ +#endif eNB_rrc_inst[enb_mod_idP].Info.UE[ue_mod_idP].Status = RRC_IDLE; eNB_rrc_inst[enb_mod_idP].Info.UE_list[ue_mod_idP] = 0; - rrc_rlc_remove_ue(enb_mod_idP, ue_mod_idP, frameP,ENB_FLAG_YES); pdcp_remove_UE(enb_mod_idP, ue_mod_idP, frameP); diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.c b/openair2/RRC/LITE/rrc_eNB_S1AP.c index 5561b00a38..efdb169a11 100644 --- a/openair2/RRC/LITE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LITE/rrc_eNB_S1AP.c @@ -90,9 +90,8 @@ static uint16_t get_next_ue_initial_id(uint8_t mod_id) { /* Never use UE_INITIAL_ID_INVALID this is the invalid id! */ if (ue_initial_id[mod_id] == UE_INITIAL_ID_INVALID) { - ue_initial_id[mod_id]++; + ue_initial_id[mod_id]++; } - return ue_initial_id[mod_id]; } @@ -109,16 +108,16 @@ static uint8_t get_UE_index_from_initial_id(uint8_t mod_id, uint16_t ue_initial_ LOG_D(RRC, "[eNB %d] get_UE_index_from_initial_id: ue_initial_id %d\n", ue_initial_id); for (ue_index = 0; ue_index < NUMBER_OF_UE_MAX; ue_index++) { - /* Check if this UE is in use */ - LOG_D(RRC, "[eNB %d][UE %d] UE rv 0x%" PRIx64 " %d\n", mod_id, ue_index, - eNB_rrc_inst[mod_id].Info.UE_list[ue_index], eNB_rrc_inst[mod_id].Info.UE[ue_index].ue_initial_id); - - if (eNB_rrc_inst[mod_id].Info.UE_list[ue_index] != 0) { - /* Check if the initial id match */ - if (eNB_rrc_inst[mod_id].Info.UE[ue_index].ue_initial_id == ue_initial_id) { - return ue_index; + /* Check if this UE is in use */ + LOG_D(RRC, "[eNB %d][UE %d] UE rv 0x%" PRIx64 " %d\n", mod_id, ue_index, + eNB_rrc_inst[mod_id].Info.UE_list[ue_index], eNB_rrc_inst[mod_id].Info.UE[ue_index].ue_initial_id); + + if (eNB_rrc_inst[mod_id].Info.UE_list[ue_index] != 0) { + /* Check if the initial id match */ + if (eNB_rrc_inst[mod_id].Info.UE[ue_index].ue_initial_id == ue_initial_id) { + return ue_index; + } } - } } return UE_INDEX_INVALID; } @@ -137,20 +136,20 @@ static uint8_t get_UE_index_from_eNB_ue_s1ap_id(uint8_t mod_id, uint32_t eNB_ue_ for (ue_index = 0; ue_index < NUMBER_OF_UE_MAX; ue_index++) { /* Check if this UE is in use */ - LOG_D(RRC, "[eNB %d][UE %d] UE rv 0x%" PRIx64 " %d\n", mod_id, ue_index, - eNB_rrc_inst[mod_id].Info.UE_list[ue_index], eNB_rrc_inst[mod_id].Info.UE[ue_index].eNB_ue_s1ap_id); + LOG_D(RRC, "[eNB %d][UE %d] UE rv 0x%" PRIx64 " %d\n", mod_id, ue_index, + eNB_rrc_inst[mod_id].Info.UE_list[ue_index], eNB_rrc_inst[mod_id].Info.UE[ue_index].eNB_ue_s1ap_id); - if (eNB_rrc_inst[mod_id].Info.UE_list[ue_index] != 0) { - /* Check if the initial id match */ - if (eNB_rrc_inst[mod_id].Info.UE[ue_index].eNB_ue_s1ap_id == eNB_ue_s1ap_id) { - return ue_index; + if (eNB_rrc_inst[mod_id].Info.UE_list[ue_index] != 0) { + /* Check if the initial id match */ + if (eNB_rrc_inst[mod_id].Info.UE[ue_index].eNB_ue_s1ap_id == eNB_ue_s1ap_id) { + return ue_index; + } } - } } LOG_D(RRC, - "[eNB %d] return UE_INDEX_INVALID for eNB_ue_s1ap_id %u\n", - mod_id, - eNB_ue_s1ap_id); + "[eNB %d] return UE_INDEX_INVALID for eNB_ue_s1ap_id %u\n", + mod_id, + eNB_ue_s1ap_id); return UE_INDEX_INVALID; } @@ -166,12 +165,12 @@ static uint8_t get_UE_index_from_s1ap_ids(uint8_t mod_id, uint16_t ue_initial_id uint8_t ue_index; if (ue_initial_id == UE_INITIAL_ID_INVALID) { - /* If "ue_initial_id" is not set search if "eNB_ue_s1ap_id" is know by RRC */ - ue_index = get_UE_index_from_eNB_ue_s1ap_id (mod_id, eNB_ue_s1ap_id); + /* If "ue_initial_id" is not set search if "eNB_ue_s1ap_id" is know by RRC */ + ue_index = get_UE_index_from_eNB_ue_s1ap_id (mod_id, eNB_ue_s1ap_id); } else { - /* If "ue_initial_id" is set there is probably not yet an associated "eNB_ue_s1ap_id" with S1AP */ - ue_index = get_UE_index_from_initial_id (mod_id, ue_initial_id); + /* If "ue_initial_id" is set there is probably not yet an associated "eNB_ue_s1ap_id" with S1AP */ + ue_index = get_UE_index_from_initial_id (mod_id, ue_initial_id); } return ue_index; @@ -188,11 +187,11 @@ static e_SecurityAlgorithmConfig__cipheringAlgorithm rrc_eNB_select_ciphering(ui return SecurityAlgorithmConfig__cipheringAlgorithm_eea0; if (algorithms & S1AP_ENCRYPTION_EEA2_MASK) { - return SecurityAlgorithmConfig__cipheringAlgorithm_eea2; + return SecurityAlgorithmConfig__cipheringAlgorithm_eea2; } if (algorithms & S1AP_ENCRYPTION_EEA1_MASK) { - return SecurityAlgorithmConfig__cipheringAlgorithm_eea1; + return SecurityAlgorithmConfig__cipheringAlgorithm_eea1; } return SecurityAlgorithmConfig__cipheringAlgorithm_eea0; @@ -206,11 +205,11 @@ static e_SecurityAlgorithmConfig__cipheringAlgorithm rrc_eNB_select_ciphering(ui static e_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_integrity(uint16_t algorithms) { if (algorithms & S1AP_INTEGRITY_EIA2_MASK) { - return SecurityAlgorithmConfig__integrityProtAlgorithm_eia2; + return SecurityAlgorithmConfig__integrityProtAlgorithm_eia2; } if (algorithms & S1AP_INTEGRITY_EIA1_MASK) { - return SecurityAlgorithmConfig__integrityProtAlgorithm_eia1; + return SecurityAlgorithmConfig__integrityProtAlgorithm_eia1; } return INTEGRITY_ALGORITHM_NONE; @@ -242,14 +241,14 @@ static int rrc_eNB_process_security (uint8_t mod_id, uint8_t ue_index, security_ /* Select relevant algorithms */ cipheringAlgorithm = rrc_eNB_select_ciphering (eNB_rrc_inst[mod_id].Info.UE[ue_index].security_capabilities.encryption_algorithms); if (eNB_rrc_inst[mod_id].ciphering_algorithm[ue_index] != cipheringAlgorithm) { - eNB_rrc_inst[mod_id].ciphering_algorithm[ue_index] = cipheringAlgorithm; - changed = TRUE; + eNB_rrc_inst[mod_id].ciphering_algorithm[ue_index] = cipheringAlgorithm; + changed = TRUE; } integrityProtAlgorithm = rrc_eNB_select_integrity (eNB_rrc_inst[mod_id].Info.UE[ue_index].security_capabilities.integrity_algorithms); if (eNB_rrc_inst[mod_id].integrity_algorithm[ue_index] != integrityProtAlgorithm) { - eNB_rrc_inst[mod_id].integrity_algorithm[ue_index] = integrityProtAlgorithm; - changed = TRUE; + eNB_rrc_inst[mod_id].integrity_algorithm[ue_index] = integrityProtAlgorithm; + changed = TRUE; } LOG_I (RRC, "[eNB %d][UE %d] Selected security algorithms (%x): %x, %x, %s\n", @@ -296,13 +295,13 @@ static void rrc_pdcp_config_security(uint8_t enb_mod_idP, uint8_t ue_mod_idP, ui /* Derive the keys from kenb */ if (SRB_configList != NULL) { derive_key_up_enc(eNB_rrc_inst[enb_mod_idP].ciphering_algorithm[ue_mod_idP], - eNB_rrc_inst[enb_mod_idP].kenb[ue_mod_idP], &kUPenc); + eNB_rrc_inst[enb_mod_idP].kenb[ue_mod_idP], &kUPenc); } derive_key_rrc_enc(eNB_rrc_inst[enb_mod_idP].ciphering_algorithm[ue_mod_idP], - eNB_rrc_inst[enb_mod_idP].kenb[ue_mod_idP], &kRRCenc); + eNB_rrc_inst[enb_mod_idP].kenb[ue_mod_idP], &kRRCenc); derive_key_rrc_int(eNB_rrc_inst[enb_mod_idP].integrity_algorithm[ue_mod_idP], - eNB_rrc_inst[enb_mod_idP].kenb[ue_mod_idP], &kRRCint); + eNB_rrc_inst[enb_mod_idP].kenb[ue_mod_idP], &kRRCint); #define DEBUG_SECURITY 1 @@ -313,17 +312,17 @@ static void rrc_pdcp_config_security(uint8_t enb_mod_idP, uint8_t ue_mod_idP, ui int i; msg("\nKeNB:"); for(i = 0; i < 32; i++) - msg("%02x", eNB_rrc_inst[enb_mod_idP].kenb[ue_mod_idP][i]); + msg("%02x", eNB_rrc_inst[enb_mod_idP].kenb[ue_mod_idP][i]); msg("\n"); msg("\nKRRCenc:"); for(i = 0; i < 32; i++) - msg("%02x", kRRCenc[i]); + msg("%02x", kRRCenc[i]); msg("\n"); msg("\nKRRCint:"); for(i = 0; i < 32; i++) - msg("%02x", kRRCint[i]); + msg("%02x", kRRCint[i]); msg("\n"); } @@ -808,6 +807,47 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ (MessageDef *msg_p, const char * } } +/*------------------------------------------------------------------------------*/ +void rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ (uint8_t mod_id, uint8_t ue_index, s1ap_Cause_t causeP, long cause_valueP) { + uint32_t eNB_ue_s1ap_id; + + if (ue_index == UE_INDEX_INVALID) { + LOG_W(RRC, + "[eNB] In S1AP_UE_CONTEXT_RELEASE_COMMAND: invalid UE\n"); + return (-1); + } else { + int e_rab; + int mod_id = 0; + eNB_RRC_UE_INFO *UE_info = &eNB_rrc_inst[mod_id].Info.UE[ue_index]; +/* MessageDef *msg_delete_tunnels_p = NULL; + + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ); + memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), + 0, + sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); + + // do not wait response + GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).ue_index = ue_index; + for (e_rab = 0; e_rab < UE_info->nb_of_e_rabs; e_rab++) { + GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[e_rab] = UE_info->enb_gtp_ebi[e_rab]; + // erase data + UE_info->enb_gtp_teid[e_rab] = 0; + memset(&UE_info->enb_gtp_addrs[e_rab], 0, sizeof(UE_info->enb_gtp_addrs[e_rab])); + UE_info->enb_gtp_ebi[e_rab] = 0; + } + itti_send_msg_to_task(TASK_GTPV1_U, mod_id, msg_delete_tunnels_p); +*/ + MessageDef *msg_complete_p = NULL; + msg_complete_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_REQ); + S1AP_UE_CONTEXT_RELEASE_REQ(msg_complete_p).eNB_ue_s1ap_id = UE_info->eNB_ue_s1ap_id; + S1AP_UE_CONTEXT_RELEASE_REQ(msg_complete_p).cause = causeP; + S1AP_UE_CONTEXT_RELEASE_REQ(msg_complete_p).cause_value = cause_valueP; + itti_send_msg_to_task(TASK_S1AP, mod_id, msg_complete_p); + return (0); + } +} + + /*------------------------------------------------------------------------------*/ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const char *msg_name, instance_t instance) { uint32_t eNB_ue_s1ap_id; diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.h b/openair2/RRC/LITE/rrc_eNB_S1AP.h index 1cec5e6ee2..a724c487bf 100644 --- a/openair2/RRC/LITE/rrc_eNB_S1AP.h +++ b/openair2/RRC/LITE/rrc_eNB_S1AP.h @@ -51,7 +51,6 @@ *\param ue_index Instance ID of UE in the eNB. */ void rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(uint8_t Mod_id, uint8_t UE_index); -# endif /*! \fn void rrc_eNB_send_S1AP_UPLINK_NAS(uint8_t Mod_id, uint8_t UE_index, UL_DCCH_Message_t *ul_dcch_msg) *\brief create a S1AP_UPLINK_NAS to transfer a NAS message to S1AP. @@ -79,9 +78,19 @@ void rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(uint8_t mod_id, uint8_t ue_index, UL_ void rrc_eNB_send_S1AP_NAS_FIRST_REQ(uint8_t Mod_id, uint8_t UE_index, RRCConnectionSetupComplete_r8_IEs_t *rrcConnectionSetupComplete); + +/*! \fn rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(uint8_t Mod_id, uint8_t UE_index, s1ap_Cause_t causeP, long cause_valueP) + *\brief create a S1AP_UE_CONTEXT_RELEASE_REQ message, the message is sent by the eNB to S1AP task to request the release of +the UE-associated S1-logical connection over the S1 interface. . + *\param mod_id Instance ID of eNB. + *\param ue_index Instance ID of UE in the eNB. + *\param causeP Origin of the cause for the UE removal. + *\param cause_valueP Contextual value (in regard of the origin) of the cause. + */ +void rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ (uint8_t mod_id, uint8_t ue_index, s1ap_Cause_t causeP, long cause_valueP); + /* Down link procedures */ -# if defined(ENABLE_ITTI) /*! \fn rrc_eNB_process_S1AP_DOWNLINK_NAS(MessageDef *msg_p, const char *msg_name, instance_t instance, mui_t *rrc_eNB_mui) *\brief process a S1AP_DOWNLINK_NAS message received from S1AP and transfer the embedded NAS message to UE. *\param msg_p Message received by RRC. -- GitLab