Request release for UEs if DU disconnects
38.473 section 8.2.3.1 says that upon F1 Setup Request, UE associated signalling should be erased. In this commit, we trigger a release of all UEs that were still connected to a DU when we received the SCTP shutdown, i.e., when the DU disconnects.
This commit is contained in:
@@ -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,
|
||||
|
||||
+14
-26
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user