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.
This commit is contained in:
Guido Casati
2026-04-10 10:22:50 +02:00
parent 442b3045d6
commit 185690cb94
4 changed files with 24 additions and 28 deletions
+3 -4
View File
@@ -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));
}
}
+1 -1
View File
@@ -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 {
+13 -14
View File
@@ -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);
+7 -9
View File
@@ -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