Commit 1c50feeb authored by Lionel Gauthier's avatar Lionel Gauthier

S1AP UE context release

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@6315 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 445ca246
...@@ -475,6 +475,7 @@ typedef struct s1ap_paging_ind_s { ...@@ -475,6 +475,7 @@ typedef struct s1ap_paging_ind_s {
paging_priority_t paging_priority; paging_priority_t paging_priority;
} s1ap_paging_ind_t; } s1ap_paging_ind_t;
// S1AP --> RRC messages
typedef struct s1ap_ue_release_command_s { typedef struct s1ap_ue_release_command_s {
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
...@@ -483,10 +484,21 @@ typedef struct s1ap_ue_release_command_s { ...@@ -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 { typedef struct s1ap_ue_release_req_s {
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
/* TODO: add cause */ s1ap_Cause_t cause;
long cause_value;
} s1ap_ue_release_req_t, s1ap_ue_release_resp_t; } s1ap_ue_release_req_t, s1ap_ue_release_resp_t;
#endif /* S1AP_MESSAGES_TYPES_H_ */ #endif /* S1AP_MESSAGES_TYPES_H_ */
...@@ -540,9 +540,18 @@ void rrc_eNB_free_UE_index( ...@@ -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, 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]); 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[ue_mod_idP].Status = RRC_IDLE;
eNB_rrc_inst[enb_mod_idP].Info.UE_list[ue_mod_idP] = 0; 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); rrc_rlc_remove_ue(enb_mod_idP, ue_mod_idP, frameP,ENB_FLAG_YES);
pdcp_remove_UE(enb_mod_idP, ue_mod_idP, frameP); pdcp_remove_UE(enb_mod_idP, ue_mod_idP, frameP);
......
...@@ -90,9 +90,8 @@ static uint16_t get_next_ue_initial_id(uint8_t mod_id) { ...@@ -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! */ /* Never use UE_INITIAL_ID_INVALID this is the invalid id! */
if (ue_initial_id[mod_id] == UE_INITIAL_ID_INVALID) { 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]; 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_ ...@@ -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); 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++) { for (ue_index = 0; ue_index < NUMBER_OF_UE_MAX; ue_index++) {
/* Check if this UE is in use */ /* Check if this UE is in use */
LOG_D(RRC, "[eNB %d][UE %d] UE rv 0x%" PRIx64 " %d\n", mod_id, ue_index, 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); 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) { if (eNB_rrc_inst[mod_id].Info.UE_list[ue_index] != 0) {
/* Check if the initial id match */ /* Check if the initial id match */
if (eNB_rrc_inst[mod_id].Info.UE[ue_index].ue_initial_id == ue_initial_id) { if (eNB_rrc_inst[mod_id].Info.UE[ue_index].ue_initial_id == ue_initial_id) {
return ue_index; return ue_index;
}
} }
}
} }
return UE_INDEX_INVALID; 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_ ...@@ -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++) { for (ue_index = 0; ue_index < NUMBER_OF_UE_MAX; ue_index++) {
/* Check if this UE is in use */ /* Check if this UE is in use */
LOG_D(RRC, "[eNB %d][UE %d] UE rv 0x%" PRIx64 " %d\n", mod_id, ue_index, 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); 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) { if (eNB_rrc_inst[mod_id].Info.UE_list[ue_index] != 0) {
/* Check if the initial id match */ /* Check if the initial id match */
if (eNB_rrc_inst[mod_id].Info.UE[ue_index].eNB_ue_s1ap_id == eNB_ue_s1ap_id) { if (eNB_rrc_inst[mod_id].Info.UE[ue_index].eNB_ue_s1ap_id == eNB_ue_s1ap_id) {
return ue_index; return ue_index;
}
} }
}
} }
LOG_D(RRC, LOG_D(RRC,
"[eNB %d] return UE_INDEX_INVALID for eNB_ue_s1ap_id %u\n", "[eNB %d] return UE_INDEX_INVALID for eNB_ue_s1ap_id %u\n",
mod_id, mod_id,
eNB_ue_s1ap_id); eNB_ue_s1ap_id);
return UE_INDEX_INVALID; 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 ...@@ -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; uint8_t ue_index;
if (ue_initial_id == UE_INITIAL_ID_INVALID) { 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 */ /* 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); ue_index = get_UE_index_from_eNB_ue_s1ap_id (mod_id, eNB_ue_s1ap_id);
} }
else { else {
/* If "ue_initial_id" is set there is probably not yet an associated "eNB_ue_s1ap_id" with S1AP */ /* 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); ue_index = get_UE_index_from_initial_id (mod_id, ue_initial_id);
} }
return ue_index; return ue_index;
...@@ -188,11 +187,11 @@ static e_SecurityAlgorithmConfig__cipheringAlgorithm rrc_eNB_select_ciphering(ui ...@@ -188,11 +187,11 @@ static e_SecurityAlgorithmConfig__cipheringAlgorithm rrc_eNB_select_ciphering(ui
return SecurityAlgorithmConfig__cipheringAlgorithm_eea0; return SecurityAlgorithmConfig__cipheringAlgorithm_eea0;
if (algorithms & S1AP_ENCRYPTION_EEA2_MASK) { if (algorithms & S1AP_ENCRYPTION_EEA2_MASK) {
return SecurityAlgorithmConfig__cipheringAlgorithm_eea2; return SecurityAlgorithmConfig__cipheringAlgorithm_eea2;
} }
if (algorithms & S1AP_ENCRYPTION_EEA1_MASK) { if (algorithms & S1AP_ENCRYPTION_EEA1_MASK) {
return SecurityAlgorithmConfig__cipheringAlgorithm_eea1; return SecurityAlgorithmConfig__cipheringAlgorithm_eea1;
} }
return SecurityAlgorithmConfig__cipheringAlgorithm_eea0; return SecurityAlgorithmConfig__cipheringAlgorithm_eea0;
...@@ -206,11 +205,11 @@ static e_SecurityAlgorithmConfig__cipheringAlgorithm rrc_eNB_select_ciphering(ui ...@@ -206,11 +205,11 @@ static e_SecurityAlgorithmConfig__cipheringAlgorithm rrc_eNB_select_ciphering(ui
static e_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_integrity(uint16_t algorithms) { static e_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_integrity(uint16_t algorithms) {
if (algorithms & S1AP_INTEGRITY_EIA2_MASK) { if (algorithms & S1AP_INTEGRITY_EIA2_MASK) {
return SecurityAlgorithmConfig__integrityProtAlgorithm_eia2; return SecurityAlgorithmConfig__integrityProtAlgorithm_eia2;
} }
if (algorithms & S1AP_INTEGRITY_EIA1_MASK) { if (algorithms & S1AP_INTEGRITY_EIA1_MASK) {
return SecurityAlgorithmConfig__integrityProtAlgorithm_eia1; return SecurityAlgorithmConfig__integrityProtAlgorithm_eia1;
} }
return INTEGRITY_ALGORITHM_NONE; return INTEGRITY_ALGORITHM_NONE;
...@@ -242,14 +241,14 @@ static int rrc_eNB_process_security (uint8_t mod_id, uint8_t ue_index, security_ ...@@ -242,14 +241,14 @@ static int rrc_eNB_process_security (uint8_t mod_id, uint8_t ue_index, security_
/* Select relevant algorithms */ /* Select relevant algorithms */
cipheringAlgorithm = rrc_eNB_select_ciphering (eNB_rrc_inst[mod_id].Info.UE[ue_index].security_capabilities.encryption_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) { if (eNB_rrc_inst[mod_id].ciphering_algorithm[ue_index] != cipheringAlgorithm) {
eNB_rrc_inst[mod_id].ciphering_algorithm[ue_index] = cipheringAlgorithm; eNB_rrc_inst[mod_id].ciphering_algorithm[ue_index] = cipheringAlgorithm;
changed = TRUE; changed = TRUE;
} }
integrityProtAlgorithm = rrc_eNB_select_integrity (eNB_rrc_inst[mod_id].Info.UE[ue_index].security_capabilities.integrity_algorithms); 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) { if (eNB_rrc_inst[mod_id].integrity_algorithm[ue_index] != integrityProtAlgorithm) {
eNB_rrc_inst[mod_id].integrity_algorithm[ue_index] = integrityProtAlgorithm; eNB_rrc_inst[mod_id].integrity_algorithm[ue_index] = integrityProtAlgorithm;
changed = TRUE; changed = TRUE;
} }
LOG_I (RRC, "[eNB %d][UE %d] Selected security algorithms (%x): %x, %x, %s\n", 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 ...@@ -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 */ /* Derive the keys from kenb */
if (SRB_configList != NULL) { if (SRB_configList != NULL) {
derive_key_up_enc(eNB_rrc_inst[enb_mod_idP].ciphering_algorithm[ue_mod_idP], 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], 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], 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 #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 ...@@ -313,17 +312,17 @@ static void rrc_pdcp_config_security(uint8_t enb_mod_idP, uint8_t ue_mod_idP, ui
int i; int i;
msg("\nKeNB:"); msg("\nKeNB:");
for(i = 0; i < 32; i++) 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("\n");
msg("\nKRRCenc:"); msg("\nKRRCenc:");
for(i = 0; i < 32; i++) for(i = 0; i < 32; i++)
msg("%02x", kRRCenc[i]); msg("%02x", kRRCenc[i]);
msg("\n"); msg("\n");
msg("\nKRRCint:"); msg("\nKRRCint:");
for(i = 0; i < 32; i++) for(i = 0; i < 32; i++)
msg("%02x", kRRCint[i]); msg("%02x", kRRCint[i]);
msg("\n"); msg("\n");
} }
...@@ -808,6 +807,47 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ (MessageDef *msg_p, const char * ...@@ -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(&GTPV1U_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) { 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; uint32_t eNB_ue_s1ap_id;
......
...@@ -51,7 +51,6 @@ ...@@ -51,7 +51,6 @@
*\param ue_index Instance ID of UE in the eNB. *\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); 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) /*! \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. *\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_ ...@@ -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, void rrc_eNB_send_S1AP_NAS_FIRST_REQ(uint8_t Mod_id, uint8_t UE_index,
RRCConnectionSetupComplete_r8_IEs_t *rrcConnectionSetupComplete); 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 */ /* 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) /*! \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. *\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. *\param msg_p Message received by RRC.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment