From 185690cb94cac5071cbcbf383dc4aa97d7525a24 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 11 Feb 2026 17:28:47 +0100 Subject: [PATCH] Refactor (RRC): inline neighbour cell arrays and constify access Inline neighbour cell arrays into the RRC neighbour configuration and update RRC/DU helpers to use const-aware access and shared iteration helpers when walking neighbour lists and building measurement configs. Changes: - Change neighbour_cells in neighbour_cell_configuration_t from a seq_arr_t * to an embedded seq_arr_t field. - Initialize and populate the embedded neighbour_cells directly in parse_neighbour_cells_list in gnb_config.c, dropping dynamic allocation of the neighbour list container. - Refactor get_neighbour_cell_by_pci and nr_rrc_get_measconfig in rrc_gNB.c to access the embedded neighbour_cells via const pointers, introduce a local meas_cfg and a3_event_list, and iterate neighbour cells with FOR_EACH_SEQ_ARR. - Treat neighbour cell configuration entries as const in rrc_gNB_du.c (get_cell_neighbour_list, label_intra_frequency_neighbours, valid_du_in_neighbour_configs) and iterate neighbour lists with FOR_EACH_SEQ_ARR instead of index-based loops. --- openair2/GNB_APP/gnb_config.c | 7 +++---- openair2/RRC/NR/nr_rrc_defs.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 27 +++++++++++++-------------- openair2/RRC/NR/rrc_gNB_du.c | 16 +++++++--------- 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 49ff67a8de..213584a44d 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -2018,8 +2018,7 @@ static nr_neighbour_cell_t *get_neighbour_by_pci(seq_arr_t *neighbour_cells, int * @param[in] n_path Base path for neighbour configuration in the config tree */ static void parse_neighbour_cells_list(neighbour_cell_configuration_t *cell, const paramlist_def_t *list, const char *n_path) { - cell->neighbour_cells = malloc_or_fail(sizeof(seq_arr_t)); - seq_arr_init(cell->neighbour_cells, sizeof(nr_neighbour_cell_t)); + seq_arr_init(&cell->neighbour_cells, sizeof(nr_neighbour_cell_t)); /* Parse each neighbour cell in the list */ for (int l = 0; l < list->numelt; ++l) { @@ -2051,12 +2050,12 @@ static void parse_neighbour_cells_list(neighbour_cell_configuration_t *cell, con n.tac); /* Check for duplicate PCI in the neighbour list */ - if (get_neighbour_by_pci(cell->neighbour_cells, n.physicalCellId) != NULL) { + if (get_neighbour_by_pci(&cell->neighbour_cells, n.physicalCellId) != NULL) { LOG_E(GNB_APP, "Cell %ld: duplicate PCI %d in neighbour list (NCI=%ld)\n", cell->nr_cell_id, n.physicalCellId, n.nrcell_id); AssertFatal(false, "PCI must be unique within a cell's neighbour list\n"); } - seq_arr_push_back(cell->neighbour_cells, &n, sizeof(n)); + seq_arr_push_back(&cell->neighbour_cells, &n, sizeof(n)); } } diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 606eb86327..3b07ec6a6c 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -326,7 +326,7 @@ typedef struct { typedef struct neighbour_cell_configuration_s { uint64_t nr_cell_id; - seq_arr_t *neighbour_cells; + seq_arr_t neighbour_cells; } neighbour_cell_configuration_t; typedef struct nr_mac_rrc_dl_if_s { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 096dc98eea..4c47e6a23b 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -263,10 +263,8 @@ static bool eq_pci(const void *vval, const void *vit) const nr_neighbour_cell_t *get_neighbour_cell_by_pci(const neighbour_cell_configuration_t *cell, int pci) { - seq_arr_t *head = cell->neighbour_cells; - DevAssert(head != NULL); - LOG_D(NR_RRC, "Number of neighbour cells: %ld\n", head->size); - elm_arr_t e = find_if(head, &pci, eq_pci); + DevAssert(cell); + elm_arr_t e = find_if((seq_arr_t *)&cell->neighbour_cells, &pci, eq_pci); if (e.found) { const nr_neighbour_cell_t *neighbour = (const nr_neighbour_cell_t *)e.it; LOG_D(NR_RRC, "Found matching neighbour cell with PCI %d and Cell ID %ld\n", neighbour->physicalCellId, neighbour->nrcell_id); @@ -772,23 +770,23 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell const NR_MeasTimingList_t *mtlist = cell->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming; const NR_MeasTiming_t *mt = mtlist->list.array[0]; const neighbour_cell_configuration_t *neighbour_config = get_neighbour_cell_config(rrc, cell->info.cell_id); - seq_arr_t *neighbour_cells = NULL; - if (neighbour_config) - neighbour_cells = neighbour_config->neighbour_cells; + const seq_arr_t *neighbour_cells = neighbour_config ? &neighbour_config->neighbour_cells : NULL; int *neigh_a3_id = NULL; if (neighbour_cells && neighbour_cells->size) neigh_a3_id = calloc_or_fail(neighbour_cells->size, sizeof(int)); - if (neighbour_cells && rrc->measurementConfiguration.a3_event_list && rrc->measurementConfiguration.a3_event_list->size > 0) { + const nr_measurement_configuration_t *meas_cfg = &rrc->measurementConfiguration; + const seq_arr_t *a3_event_list = meas_cfg->a3_event_list; + if (neighbour_cells && a3_event_list && a3_event_list->size > 0) { /* Loop through neighbours and find related A3 configuration If no related A3 but there is default add the default one. If default one added once as a report, no need to add it again && duplication. */ LOG_D(NR_RRC, "Preparing A3 Event Measurement Configuration!\n"); bool default_a3_added = false; // To ensure that the default configuration is only added once - for (int i = 0; i < neighbour_cells->size; i++) { - nr_neighbour_cell_t *neighbourCell = (nr_neighbour_cell_t *)seq_arr_at(neighbour_cells, i); + int i = 0; + FOR_EACH_SEQ_ARR(nr_neighbour_cell_t *, neighbourCell, neighbour_cells) { seq_arr_push_back(&neigh_seq, neighbourCell, sizeof(nr_neighbour_cell_t)); const nr_a3_event_t *a3Event = get_a3_configuration((gNB_RRC_INST *)rrc, neighbourCell->physicalCellId); if (!a3Event) { @@ -814,12 +812,13 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell } NR_ReportConfigId_t reportConfigId = neigh_a3_id[i]; seq_arr_push_back(&rc_A3_seq, prepare_a3_event_report(a3Event, reportConfigId), sizeof(NR_ReportConfigToAddMod_t)); + i++; } } - if (rrc->measurementConfiguration.per_event) - rc_PER = prepare_periodic_event_report(rrc->measurementConfiguration.per_event); - if (rrc->measurementConfiguration.a2_event) - rc_A2 = prepare_a2_event_report(rrc->measurementConfiguration.a2_event); + if (meas_cfg->per_event) + rc_PER = prepare_periodic_event_report(meas_cfg->per_event); + if (meas_cfg->a2_event) + rc_A2 = prepare_a2_event_report(meas_cfg->a2_event); NR_MeasConfig_t *result = get_MeasConfig(mt, band, cell->info.pci, rc_PER, rc_A2, &rc_A3_seq, &neigh_seq, neigh_a3_id); diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index ec139e684d..71da3f3d1b 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -152,7 +152,7 @@ static int nr_cell_id_match(const void *key, const void *element) return 1; } -static neighbour_cell_configuration_t *get_cell_neighbour_list(const gNB_RRC_INST *rrc, const nr_rrc_cell_container_t *cell) +static const neighbour_cell_configuration_t *get_cell_neighbour_list(const gNB_RRC_INST *rrc, const nr_rrc_cell_container_t *cell) { void *base = seq_arr_front(rrc->neighbour_cell_configuration); size_t nmemb = seq_arr_size(rrc->neighbour_cell_configuration); @@ -160,7 +160,7 @@ static neighbour_cell_configuration_t *get_cell_neighbour_list(const gNB_RRC_INS void *it = bsearch((void *)&cell->info.cell_id, base, nmemb, size, nr_cell_id_match); - return (neighbour_cell_configuration_t *)it; + return (const neighbour_cell_configuration_t *)it; } static void is_intra_frequency_neighbour(void *ssb_arfcn, void *neighbour_cell) @@ -183,7 +183,7 @@ static void label_intra_frequency_neighbours(gNB_RRC_INST *rrc, const nr_rrc_cel if (!rrc->neighbour_cell_configuration) return; - neighbour_cell_configuration_t *neighbour_cell_config = get_cell_neighbour_list(rrc, cell); + const neighbour_cell_configuration_t *neighbour_cell_config = get_cell_neighbour_list(rrc, cell); if (!neighbour_cell_config) return; @@ -194,8 +194,8 @@ static void label_intra_frequency_neighbours(gNB_RRC_INST *rrc, const nr_rrc_cel cell->info.pci, ssb_arfcn); - seq_arr_t *cell_neighbour_list = neighbour_cell_config->neighbour_cells; - for_each(cell_neighbour_list, (void *)&ssb_arfcn, is_intra_frequency_neighbour); + const seq_arr_t *cell_neighbour_list = &neighbour_cell_config->neighbour_cells; + for_each((seq_arr_t *)cell_neighbour_list, (void *)&ssb_arfcn, is_intra_frequency_neighbour); } static bool valid_du_in_neighbour_configs(const seq_arr_t *neighbour_cell_configuration, const f1ap_served_cell_info_t *cell) @@ -206,10 +206,8 @@ static bool valid_du_in_neighbour_configs(const seq_arr_t *neighbour_cell_config int ssb_arfcn = ssb_arfcn_mtc(mtc); ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc); - for (int c = 0; c < neighbour_cell_configuration->size; c++) { - const neighbour_cell_configuration_t *neighbour_config = seq_arr_at(neighbour_cell_configuration, c); - for (int ni = 0; ni < neighbour_config->neighbour_cells->size; ni++) { - const nr_neighbour_cell_t *nc = seq_arr_at(neighbour_config->neighbour_cells, ni); + FOR_EACH_SEQ_ARR(const neighbour_cell_configuration_t *, neighbour_config, neighbour_cell_configuration) { + FOR_EACH_SEQ_ARR(const nr_neighbour_cell_t *, nc, &neighbour_config->neighbour_cells) { if (nc->nrcell_id != cell->nr_cellid) continue; // current cell is in the nc config, check that config matches