From f5c90ead7e37fb618ae2624e41a534921ea0e0d7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt <robert.schmidt@openairinterface.org> Date: Mon, 21 Aug 2023 17:24:47 +0200 Subject: [PATCH] Free DU at CU on lost connection, store assoc ID - store the assoc ID of a UE at the RRC - if F1 receives an SCTP shutdown, it removes the endpoint - F1 will also send an "F1 Lost Connection" message to the RRC - it is not yet possible to reconnect a DU after it had already been connected at the CU, since the CU F1AP task will try to rebind GTP, which fails --- openair2/COMMON/f1ap_messages_def.h | 3 +++ openair2/COMMON/f1ap_messages_types.h | 6 +++++ openair2/F1AP/f1ap_common.c | 10 ++++++++ openair2/F1AP/f1ap_common.h | 1 + openair2/F1AP/f1ap_cu_interface_management.c | 1 + openair2/F1AP/f1ap_cu_task.c | 12 +++++++++ openair2/RRC/NR/nr_rrc_defs.h | 1 + openair2/RRC/NR/rrc_gNB.c | 26 +++++++++++++++++--- 8 files changed, 57 insertions(+), 3 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index 9cb63a0a06b..0689dd52ac3 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -32,6 +32,9 @@ MESSAGE_DEF(F1AP_SETUP_RESP , MESSAGE_PRIORITY_MED, f1ap_setup_resp_t MESSAGE_DEF(F1AP_SETUP_FAILURE , MESSAGE_PRIORITY_MED, f1ap_setup_failure_t , f1ap_setup_failure) MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_t , f1ap_gnb_cu_configuration_update) +/* F1AP -> RRC to inform about lost connection */ +MESSAGE_DEF(F1AP_LOST_CONNECTION, MESSAGE_PRIORITY_MED, f1ap_lost_connection_t, f1ap_lost_connection) + /* MAC -> F1AP messages */ MESSAGE_DEF(F1AP_INITIAL_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_initial_ul_rrc_message_t , f1ap_initial_ul_rrc_message) MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_rrc_message_t , f1ap_ul_rrc_message) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index b3875c01bff..b0ec1e1e356 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -39,6 +39,8 @@ #define F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update_failure #define F1AP_SETUP_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_setup_failure +#define F1AP_LOST_CONNECTION(mSGpTR) (mSGpTR)->ittiMsg.f1ap_lost_connection + #define F1AP_INITIAL_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_initial_ul_rrc_message #define F1AP_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ul_rrc_message #define F1AP_UE_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_req @@ -405,4 +407,8 @@ typedef struct f1ap_paging_ind_s { uint8_t paging_drx; } f1ap_paging_ind_t; +typedef struct f1ap_lost_connection_t { + int dummy; +} f1ap_lost_connection_t; + #endif /* F1AP_MESSAGES_TYPES_H_ */ diff --git a/openair2/F1AP/f1ap_common.c b/openair2/F1AP/f1ap_common.c index 91e7d85efed..3491adc48a0 100644 --- a/openair2/F1AP/f1ap_common.c +++ b/openair2/F1AP/f1ap_common.c @@ -63,3 +63,13 @@ void createF1inst(instance_t instanceP, f1ap_setup_req_t *req, f1ap_net_config_t f1_inst[0]->net_config = *nc; pthread_mutex_unlock(&f1_inst_mtx); } + +void destroyF1inst(instance_t instance) +{ + DevAssert(instance == 0); + pthread_mutex_lock(&f1_inst_mtx); + AssertFatal(f1_inst[0] != NULL, "Attempted to free uninitialized F1 instances\n"); + free(f1_inst[instance]); + f1_inst[instance] = NULL; + pthread_mutex_unlock(&f1_inst_mtx); +} diff --git a/openair2/F1AP/f1ap_common.h b/openair2/F1AP/f1ap_common.h index 1329ebdfce0..3e0cbb4c8a4 100644 --- a/openair2/F1AP/f1ap_common.h +++ b/openair2/F1AP/f1ap_common.h @@ -418,6 +418,7 @@ uint8_t F1AP_get_next_transaction_identifier(instance_t mod_idP, instance_t cu_m f1ap_cudu_inst_t *getCxt(instance_t instanceP); void createF1inst(instance_t instanceP, f1ap_setup_req_t *req, f1ap_net_config_t *nc); +void destroyF1inst(instance_t instance); //lts: C struct type is not homogeneous, so we need macros instead of functions #define addnRCGI(nRCGi, servedCelL) \ diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index ad3880c71ba..3ee88c33b50 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -94,6 +94,7 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, } MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_SETUP_REQ); + message_p->ittiMsgHeader.originInstance = assoc_id; f1ap_setup_req_t *req = &F1AP_SETUP_REQ(message_p); /* gNB_DU_id */ // this function exits if the ie is mandatory diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index 330d4f5422a..2d47398d51b 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -71,6 +71,18 @@ static void cu_task_handle_sctp_association_ind(instance_t instance, static void cu_task_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) { DevAssert(sctp_new_association_resp != NULL); + if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN) { + f1ap_cudu_inst_t *f1ap_cu_data = getCxt(instance); + AssertFatal(f1ap_cu_data != NULL, "illegal state: SCTP shutdown for non-existing F1AP endpoint\n"); + LOG_I(F1AP, "Received SCTP shutdown for assoc_id %d, removing endpoint\n", sctp_new_association_resp->assoc_id); + destroyF1inst(instance); + /* inform RRC that the DU is gone */ + MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_LOST_CONNECTION); + message_p->ittiMsgHeader.originInstance = sctp_new_association_resp->assoc_id; + itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p); + return; + } + if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { LOG_W(F1AP, "Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", sctp_new_association_resp->sctp_state, diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 465f968a4d1..362d2bcee5f 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -369,6 +369,7 @@ typedef struct cucp_cuup_if_s { } cucp_cuup_if_t; typedef struct nr_rrc_du_container_t { + int assoc_id; f1ap_setup_req_t *setup_req; NR_MIB_t *mib; NR_SIB1_t *sib1; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 505b22ab501..23fcbffe503 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1801,12 +1801,12 @@ static bool rrc_gNB_plmn_matches(const gNB_RRC_INST *rrc, const f1ap_served_cell && rrc->nr_cellid == info->nr_cellid; } -static void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req) +static void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, int assoc_id) { gNB_RRC_INST *rrc = RC.nrrrc[0]; DevAssert(rrc); - LOG_I(NR_RRC, "Received F1 Setup Request from gNB_DU %lu (%s)\n", req->gNB_DU_id, req->gNB_DU_name); + LOG_I(NR_RRC, "Received F1 Setup Request from gNB_DU %lu (%s) on assoc_id %d\n", req->gNB_DU_id, req->gNB_DU_name, assoc_id); // check: // - it is the first DU @@ -1876,6 +1876,7 @@ static void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req) // we accept the DU rrc->du = calloc(1, sizeof(*rrc->du)); AssertFatal(rrc->du != NULL, "out of memory\n"); + rrc->du->assoc_id = assoc_id; /* ITTI will free the setup request message via free(). So the memory * "inside" of the message will remain, but the "outside" container no, so @@ -2423,6 +2424,21 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp prepare_and_send_ue_context_modification_f1(ue_context_p, resp); } +static void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t *lc, int assoc_id) +{ + AssertFatal(rrc->du != NULL, "no DU connected, cannot received F1 lost connection\n"); + AssertFatal(rrc->du->assoc_id == assoc_id, + "previously connected DU (%d) does not match DU for which connection has been lost (%d)\n", + rrc->du->assoc_id, + assoc_id); + (void) lc; // unused for the moment + ASN_STRUCT_FREE(asn_DEF_NR_MIB, rrc->du->mib); + ASN_STRUCT_FREE(asn_DEF_NR_SIB1, rrc->du->sib1); + free(rrc->du); + rrc->du = NULL; + LOG_I(RRC, "dropping DU with assoc_id %d (UE connections remain, if any)\n", assoc_id); +} + static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults) { DevAssert(measresults->measResultServingMOList.list.count >= 1); @@ -2621,7 +2637,7 @@ void *rrc_gnb_task(void *args_p) { /* Messages from F1AP task */ case F1AP_SETUP_REQ: AssertFatal(!NODE_IS_DU(RC.nrrrc[instance]->node_type), "should not receive F1AP_SETUP_REQUEST in DU!\n"); - rrc_gNB_process_f1_setup_req(&F1AP_SETUP_REQ(msg_p)); + rrc_gNB_process_f1_setup_req(&F1AP_SETUP_REQ(msg_p), msg_p->ittiMsgHeader.originInstance); break; case F1AP_UE_CONTEXT_SETUP_RESP: @@ -2644,6 +2660,10 @@ void *rrc_gnb_task(void *args_p) { rrc_CU_process_ue_context_release_complete(msg_p); break; + case F1AP_LOST_CONNECTION: + rrc_CU_process_f1_lost_connection(RC.nrrrc[0], &F1AP_LOST_CONNECTION(msg_p), msg_p->ittiMsgHeader.originInstance); + break; + /* Messages from X2AP */ case X2AP_ENDC_SGNB_ADDITION_REQ: LOG_I(NR_RRC, "Received ENDC sgNB addition request from X2AP \n"); -- GitLab