From c956de6f27368aba45ececd8ab1c9581051740e2 Mon Sep 17 00:00:00 2001 From: Roberto Magueta Date: Tue, 3 Sep 2024 10:53:16 +0200 Subject: [PATCH] Trigger F1 Handover on A3 event When receiving a measurement report including an A3 event, trigger handover towards the indicated cell. Note that currently, we are still limited to one Cell by DU, hence looking up a cell comes down to looking up a DU, as is done here. Co-authored-by: batuhanduyuler Co-authored-by: Luis Pereira Co-authored-by: Robert Schmidt --- openair2/RRC/NR/rrc_gNB.c | 29 ++++++++++++++++++----------- openair2/RRC/NR/rrc_gNB_du.c | 12 ++++++++++++ openair2/RRC/NR/rrc_gNB_du.h | 1 + 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 6e0906b63c..0f9fce815b 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1236,7 +1236,7 @@ static void process_Periodical_Measurement_Report(gNB_RRC_UE_t *ue_ctxt, NR_Meas measurementReport->criticalExtensions.choice.measurementReport = NULL; } -static void process_Event_Based_Measurement_Report(NR_ReportConfigNR_t *report, NR_MeasurementReport_t *measurementReport) +static void process_Event_Based_Measurement_Report(gNB_RRC_UE_t *ue, NR_ReportConfigNR_t *report, NR_MeasurementReport_t *measurementReport) { NR_EventTriggerConfig_t *event_triggered = report->reportType.choice.eventTriggered; @@ -1250,7 +1250,7 @@ static void process_Event_Based_Measurement_Report(NR_ReportConfigNR_t *report, break; case NR_EventTriggerConfig__eventId_PR_eventA3: { - LOG_I(NR_RRC, "HO LOG: Event A3 Report - Neighbour Becomes Better than Serving!\n"); + LOG_W(NR_RRC, "HO LOG: Event A3 Report - Neighbour Becomes Better than Serving!\n"); const NR_MeasResults_t *measResults = &measurementReport->criticalExtensions.choice.measurementReport->measResults; for (int serving_cell_idx = 0; serving_cell_idx < measResults->measResultServingMOList.list.count; serving_cell_idx++) { @@ -1289,13 +1289,13 @@ static void process_Event_Based_Measurement_Report(NR_ReportConfigNR_t *report, neighbourCellId, neighbourCellRSRP); - const f1ap_served_cell_info_t *neighbour_cell_du_context = get_cell_information_by_phycellId(neighbourCellId); - const f1ap_served_cell_info_t *serving_cell_du_context = get_cell_information_by_phycellId(servingCellId); + const f1ap_served_cell_info_t *neigh_cell = get_cell_information_by_phycellId(neighbourCellId); + const f1ap_served_cell_info_t *serving_cell = get_cell_information_by_phycellId(servingCellId); const nr_neighbour_gnb_configuration_t *neighbour = - get_neighbour_cell_information(serving_cell_du_context->nr_cellid, neighbourCellId); + get_neighbour_cell_information(serving_cell->nr_cellid, neighbourCellId); // CU does not have f1 connection with neighbour cell context. So check does serving cell has this phyCellId as a // neighbour. - if (!neighbour_cell_du_context && neighbour) { + if (!neigh_cell && neighbour) { // No F1 connection but static neighbour configuration is available const nr_a3_event_t *a3_event_configuration = get_a3_configuration(neighbour->physicalCellId); // Additional check - This part can be modified according to additional cell specific Handover Margin @@ -1304,6 +1304,15 @@ static void process_Event_Based_Measurement_Report(NR_ReportConfigNR_t *report, < (neighbourCellRSRP - servingCellRSRP))) { LOG_D(NR_RRC, "HO LOG: Trigger N2 HO for the neighbour gnb: %u cell: %lu\n", neighbour->gNB_ID, neighbour->nrcell_id); } + } else if (neigh_cell && neighbour) { + /* we know the cell and are connected to the DU! */ + gNB_RRC_INST *rrc = RC.nrrrc[0]; + nr_rrc_du_container_t *source_du = get_du_by_cell_id(rrc, serving_cell->nr_cellid); + DevAssert(source_du); + nr_rrc_du_container_t *target_du = get_du_by_cell_id(rrc, neigh_cell->nr_cellid); + nr_rrc_trigger_f1_ho(rrc, ue, source_du, target_du); + } else { + LOG_W(NR_RRC, "UE %d: received A3 event for stronger neighbor PCI %d, but no such neighbour in configuration\n", ue->rrc_ue_id, neighbourCellId); } } @@ -1365,12 +1374,10 @@ static void rrc_gNB_process_MeasurementReport(gNB_RRC_UE_t *UE, NR_MeasurementRe if (report_config->choice.reportConfigNR->reportType.present == NR_ReportConfigNR__reportType_PR_periodical) return process_Periodical_Measurement_Report(UE, measurementReport); - if (report_config->choice.reportConfigNR->reportType.present != NR_ReportConfigNR__reportType_PR_eventTriggered) { - LOG_D(NR_RRC, "Incoming Report Type: %d is not supported! \n", report_config->choice.reportConfigNR->reportType.present); - return; - } + if (report_config->choice.reportConfigNR->reportType.present == NR_ReportConfigNR__reportType_PR_eventTriggered) + return process_Event_Based_Measurement_Report(UE, report_config->choice.reportConfigNR, measurementReport); - process_Event_Based_Measurement_Report(report_config->choice.reportConfigNR, measurementReport); + LOG_E(NR_RRC, "Incoming Report Type: %d is not supported! \n", report_config->choice.reportConfigNR->reportType.present); } static int handle_rrcReestablishmentComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_RRCReestablishmentComplete_t *cplt) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index bc2ade3253..4e065e530c 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -567,6 +567,18 @@ nr_rrc_du_container_t *get_du_by_assoc_id(gNB_RRC_INST *rrc, sctp_assoc_t assoc_ return RB_FIND(rrc_du_tree, &rrc->dus, &e); } +/* \brief find DU by cell ID. Note: currently the CU is limited to one cell per + * DU, hence here, DU == cell. Modify this to look up a specific cell. */ +nr_rrc_du_container_t *get_du_by_cell_id(gNB_RRC_INST *rrc, uint64_t cell_id) +{ + nr_rrc_du_container_t *du = NULL; + RB_FOREACH(du, rrc_du_tree, &rrc->dus) { + if (cell_id == du->setup_req->cell[0].info.nr_cellid) + return du; + } + return NULL; +} + void dump_du_info(const gNB_RRC_INST *rrc, FILE *f) { fprintf(f, "%ld connected DUs \n", rrc->num_dus); diff --git a/openair2/RRC/NR/rrc_gNB_du.h b/openair2/RRC/NR/rrc_gNB_du.h index 55a0d7c2c8..bd3c4f6443 100644 --- a/openair2/RRC/NR/rrc_gNB_du.h +++ b/openair2/RRC/NR/rrc_gNB_du.h @@ -41,6 +41,7 @@ void rrc_gNB_process_f1_du_configuration_update(struct f1ap_gnb_du_configuration struct nr_rrc_du_container_t *get_du_for_ue(struct gNB_RRC_INST_s *rrc, uint32_t ue_id); struct nr_rrc_du_container_t *get_du_by_assoc_id(struct gNB_RRC_INST_s *rrc, sctp_assoc_t assoc_id); const struct f1ap_served_cell_info_t *get_cell_information_by_phycellId(int phyCellId); +struct nr_rrc_du_container_t *get_du_by_cell_id(struct gNB_RRC_INST_s *rrc, uint64_t cell_id); void dump_du_info(const struct gNB_RRC_INST_s *rrc, FILE *f);