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 <batuhan.duyuler@firecell.io> Co-authored-by: Luis Pereira <lpereira@allbesmart.pt> Co-authored-by: Robert Schmidt <robert.schmidt@openairinterface.org>
This commit is contained in:
committed by
Robert Schmidt
co-authored by
batuhanduyuler
Luis Pereira
Robert Schmidt
parent
8b4259c047
commit
c956de6f27
+18
-11
@@ -1236,7 +1236,7 @@ static void process_Periodical_Measurement_Report(gNB_RRC_UE_t *ue_ctxt, NR_Meas
|
|||||||
measurementReport->criticalExtensions.choice.measurementReport = NULL;
|
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;
|
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;
|
break;
|
||||||
|
|
||||||
case NR_EventTriggerConfig__eventId_PR_eventA3: {
|
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;
|
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++) {
|
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,
|
neighbourCellId,
|
||||||
neighbourCellRSRP);
|
neighbourCellRSRP);
|
||||||
|
|
||||||
const f1ap_served_cell_info_t *neighbour_cell_du_context = get_cell_information_by_phycellId(neighbourCellId);
|
const f1ap_served_cell_info_t *neigh_cell = 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 *serving_cell = get_cell_information_by_phycellId(servingCellId);
|
||||||
const nr_neighbour_gnb_configuration_t *neighbour =
|
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
|
// CU does not have f1 connection with neighbour cell context. So check does serving cell has this phyCellId as a
|
||||||
// neighbour.
|
// neighbour.
|
||||||
if (!neighbour_cell_du_context && neighbour) {
|
if (!neigh_cell && neighbour) {
|
||||||
// No F1 connection but static neighbour configuration is available
|
// No F1 connection but static neighbour configuration is available
|
||||||
const nr_a3_event_t *a3_event_configuration = get_a3_configuration(neighbour->physicalCellId);
|
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
|
// 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))) {
|
< (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);
|
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)
|
if (report_config->choice.reportConfigNR->reportType.present == NR_ReportConfigNR__reportType_PR_periodical)
|
||||||
return process_Periodical_Measurement_Report(UE, measurementReport);
|
return process_Periodical_Measurement_Report(UE, measurementReport);
|
||||||
|
|
||||||
if (report_config->choice.reportConfigNR->reportType.present != NR_ReportConfigNR__reportType_PR_eventTriggered) {
|
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 process_Event_Based_Measurement_Report(UE, report_config->choice.reportConfigNR, measurementReport);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
static int handle_rrcReestablishmentComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_RRCReestablishmentComplete_t *cplt)
|
||||||
|
|||||||
@@ -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);
|
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)
|
void dump_du_info(const gNB_RRC_INST *rrc, FILE *f)
|
||||||
{
|
{
|
||||||
fprintf(f, "%ld connected DUs \n", rrc->num_dus);
|
fprintf(f, "%ld connected DUs \n", rrc->num_dus);
|
||||||
|
|||||||
@@ -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_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);
|
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);
|
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);
|
void dump_du_info(const struct gNB_RRC_INST_s *rrc, FILE *f);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user