diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index e034005ceb..885e119cbf 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -63,6 +63,7 @@ void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc,NR_UE_CapabilityRAT_ContainerLi void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m); void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti); +void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p); void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_ServingCellConfig_t *servingcellconfigdedicated, diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index d26ece970c..1c4b5dfd06 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1940,6 +1940,19 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE) ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, UE->measResults); } +void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p) +{ + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + /* we call nr_pdcp_remove_UE() in the handler of E1 bearer release, but if we + * are in E1, we also need to free the UE in the CU-CP, so call it twice to + * cover all cases */ + nr_pdcp_remove_UE(UE->rrc_ue_id); + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id); + LOG_I(NR_RRC, "removed UE CU UE ID %u/RNTI %04x \n", UE->rrc_ue_id, UE->rnti); + rrc_delete_ue_data(UE); + rrc_gNB_remove_ue_context(rrc, ue_context_p); +} + static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p) { const int instance = 0; @@ -1950,16 +1963,8 @@ static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p) LOG_E(RRC, "could not find UE context for CU UE ID %u, aborting transaction\n", complete->gNB_CU_ue_id); return; } - gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - /* we call nr_pdcp_remove_UE() in the handler of E1 bearer release, but if we - * are in E1, we also need to free the UE in the CU-CP, so call it twice to - * cover all cases */ - nr_pdcp_remove_UE(UE->rrc_ue_id); - rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance, UE->rrc_ue_id); - LOG_I(NR_RRC, "removed UE CU UE ID %u/RNTI %04x \n", UE->rrc_ue_id, UE->rnti); - rrc_delete_ue_data(UE); - rrc_gNB_remove_ue_context(rrc, ue_context_p); + rrc_remove_ue(RC.nrrrc[0], ue_context_p); } static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, instance_t instance) @@ -2672,23 +2677,6 @@ rrc_gNB_generate_RRCRelease( }; deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd, .assoc_id = ue_data.du_assoc_id}; nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data); - - /* a UE might not be associated to a CU-UP if it never requested a PDU - * session (intentionally, or because of erros) */ - if (ue_associated_to_cuup(rrc, UE)) { - sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE); - e1ap_bearer_release_cmd_t cmd = { - .gNB_cu_cp_ue_id = UE->rrc_ue_id, - .gNB_cu_up_ue_id = UE->rrc_ue_id, - }; - rrc->cucp_cuup.bearer_context_release(assoc_id, &cmd); - } - -#ifdef E2_AGENT - signal_rrc_state_changed_to(UE, RC_SM_RRC_IDLE); -#endif - - /* UE will be freed after UE context release complete */ } int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint32_t tmsi, uint8_t paging_drx) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 2fafec982a..e198ab0748 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -73,6 +73,10 @@ #include "conversions.h" #include "RRC/NR/rrc_gNB_radio_bearers.h" +#ifdef E2_AGENT +#include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" +#endif + #include "uper_encoder.h" extern RAN_CONTEXT_t RC; @@ -1178,7 +1182,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t in itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p); return (-1); } else { - /* TODO release context. */ + /* Send the response */ MessageDef *msg_resp_p; msg_resp_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_RESP); @@ -1195,7 +1199,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t in */ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance) { - //----------------------------------------------------------------------------- + gNB_RRC_INST *rrc = RC.nrrrc[0]; uint32_t gNB_ue_ngap_id = 0; protocol_ctxt_t ctxt; gNB_ue_ngap_id = NGAP_UE_CONTEXT_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id; @@ -1214,9 +1218,34 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_ } gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, UE->rrc_ue_id, 0, 0); - ctxt.eNB_index = 0; - rrc_gNB_generate_RRCRelease(&ctxt, ue_context_p); +#ifdef E2_AGENT + signal_rrc_state_changed_to(UE, RC_SM_RRC_IDLE); +#endif + + /* a UE might not be associated to a CU-UP if it never requested a PDU + * session (intentionally, or because of erros) */ + if (ue_associated_to_cuup(rrc, UE)) { + sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE); + e1ap_bearer_release_cmd_t cmd = { + .gNB_cu_cp_ue_id = UE->rrc_ue_id, + .gNB_cu_up_ue_id = UE->rrc_ue_id, + }; + rrc->cucp_cuup.bearer_context_release(assoc_id, &cmd); + } + + /* special case: the DU might be offline, in which case the f1_ue_data exists + * but is set to 0 */ + if (cu_exists_f1_ue_data(UE->rrc_ue_id) && cu_get_f1_ue_data(UE->rrc_ue_id).du_assoc_id != 0) { + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, UE->rrc_ue_id, 0, 0); + ctxt.eNB_index = 0; + rrc_gNB_generate_RRCRelease(&ctxt, ue_context_p); + + /* UE will be freed after UE context release complete */ + } else { + // the DU is offline already + rrc_remove_ue(rrc, ue_context_p); + } + return 0; } diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index dc78d534e4..cb2de0bf4c 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -20,6 +20,7 @@ */ #include "rrc_gNB_du.h" +#include "rrc_gNB_NGAP.h" #include "common/ran_context.h" #include "nr_rrc_defs.h" #include "rrc_gNB_UE_context.h" @@ -211,10 +212,14 @@ static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id) f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_id); if (ue_data.du_assoc_id == assoc_id) { /* this UE belongs to the DU that disconnected, set du_assoc_id to 0, - * meaning DU is offline */ + * meaning DU is offline, then trigger release request */ cu_remove_f1_ue_data(ue_id); - f1_ue_data_t new = {.secondary_ue = ue_data.secondary_ue, .du_assoc_id = 0 }; - cu_add_f1_ue_data(ue_id, &new); + ue_data.du_assoc_id = 0; + cu_add_f1_ue_data(ue_id, &ue_data); + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(0, + ue_context_p, + NGAP_CAUSE_RADIO_NETWORK, + NGAP_CAUSE_RADIO_NETWORK_RADIO_CONNECTION_WITH_UE_LOST); count++; } }