Refactor (gNB Config): reuse PLMN helper and neighbour config parsing

Refactor gNB configuration code to share PLMN extraction logic and to
split neighbour-cell configuration into smaller helpers with safer
allocation and clearer list handling.

Changes:
- Add `extract_plmn_from_params()` in `gnb_config_common.c` and declare
  it in `gnb_config_common.h` to centralize PLMN extraction from
  `paramdef_t`.
- Update `set_plmn_config()` to use `extract_plmn_from_params()` when
  filling the PLMN array instead of duplicating field assignments.
- Refactor `fill_neighbour_cell_configuration()` in `gnb_config.c` to
  delegate per-cell neighbour parsing to
  `parse_neighbour_cells_list()` and sorting to
  `sort_neighbour_configuration()`, simplifying the main loop.
- Use `extract_plmn_from_params()` when parsing neighbour PLMNs in
  `parse_neighbour_cells_list()` and log each neighbour with its PLMN,
  PCI, and other radio parameters before adding it to the sequence.
- Switch allocation of `rrc->neighbour_cell_configuration` in
  `fill_neighbour_cell_configuration()` from `malloc` to
  `malloc_or_fail()` to enforce consistent handling of allocation
  failures.
This commit is contained in:
Guido Casati
2026-04-10 10:22:50 +02:00
parent 425ea41ba5
commit afb3005a7c
3 changed files with 75 additions and 80 deletions
+62 -75
View File
@@ -2012,94 +2012,81 @@ static nr_neighbour_cell_t *get_neighbour_by_pci(seq_arr_t *neighbour_cells, int
return NULL;
}
static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
static void parse_neighbour_cells_list(neighbour_cell_configuration_t *cell, const paramlist_def_t *list, const char *n_path)
{
char gnbpath[MAX_OPTNAME_SIZE + 8];
snprintf(gnbpath, sizeof(gnbpath), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx);
cell->neighbour_cells = malloc_or_fail(sizeof(seq_arr_t));
seq_arr_init(cell->neighbour_cells, sizeof(nr_neighbour_cell_t));
GET_PARAMS_LIST(neighbour_list_param_list,
neighbour_list_params,
GNB_NEIGHBOUR_LIST_PARAM_LIST,
GNB_CONFIG_STRING_NEIGHBOUR_LIST,
gnbpath);
for (int l = 0; l < list->numelt; ++l) {
const paramdef_t *cell_params = list->paramarray[l];
nr_neighbour_cell_t n = {.gNB_ID = *cell_params[GNB_CONFIG_N_CELL_GNB_ID_IDX].uptr,
.nrcell_id = (uint64_t)*cell_params[GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr,
.physicalCellId = *cell_params[GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX].uptr,
.subcarrierSpacing = *cell_params[GNB_CONFIG_N_CELL_SCS_IDX].uptr,
.band = *cell_params[GNB_CONFIG_N_CELL_BAND_IDX].uptr,
.absoluteFrequencySSB = *cell_params[GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX].i64ptr,
.tac = *cell_params[GNB_CONFIG_N_CELL_TAC_IDX].uptr};
if (neighbour_list_param_list.numelt < 1)
return;
char p[CONFIG_MAXOPTLENGTH]; // plmn path
snprintf(p, sizeof(p), "%s.%s.[%i].%s", n_path, GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST, l, GNB_CONFIG_STRING_NEIGHBOUR_PLMN);
GET_PARAMS(NeighbourPlmn, GNBPLMNPARAMS_DESC, p);
n.plmn = extract_plmn_from_params(NeighbourPlmn, sizeofArray(NeighbourPlmn));
rrc->neighbour_cell_configuration = malloc(sizeof(seq_arr_t));
seq_arr_init(rrc->neighbour_cell_configuration, sizeof(neighbour_cell_configuration_t));
LOG_I(GNB_APP,
"Neighbour[%d]: cellId %ld, PLMN %03u.%0*u, gNB %d, PCI %d, SCS %d, SSB ARFCN %u, TAC %u\n",
l,
n.nrcell_id,
n.plmn.mcc,
n.plmn.mnc_digit_length,
n.plmn.mnc,
n.gNB_ID,
n.physicalCellId,
n.subcarrierSpacing,
n.absoluteFrequencySSB,
n.tac);
for (int elm = 0; elm < neighbour_list_param_list.numelt; ++elm) {
neighbour_cell_configuration_t cell = {0};
cell.nr_cell_id = (uint64_t)*neighbour_list_param_list.paramarray[elm][0].u64ptr;
char neighbourpath[MAX_OPTNAME_SIZE + 8];
snprintf(neighbourpath, sizeof(neighbourpath), "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx, GNB_CONFIG_STRING_NEIGHBOUR_LIST, elm);
GET_PARAMS_LIST(NeighbourCellParamList,
NeighbourCellParams,
GNBNEIGHBOURCELLPARAMS_DESC,
GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST,
neighbourpath);
LOG_I(GNB_APP, "Cell %ld has %d neighbours\n", cell.nr_cell_id, NeighbourCellParamList.numelt);
if (NeighbourCellParamList.numelt < 1)
continue;
cell.neighbour_cells = malloc_or_fail(sizeof(seq_arr_t));
seq_arr_init(cell.neighbour_cells, sizeof(nr_neighbour_cell_t));
for (int l = 0; l < NeighbourCellParamList.numelt; ++l) {
nr_neighbour_cell_t n = {0};
n.gNB_ID = *(NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_GNB_ID_IDX].uptr);
n.nrcell_id = (uint64_t) * (NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr);
n.physicalCellId = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX].uptr;
n.subcarrierSpacing = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_SCS_IDX].uptr;
n.band = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_BAND_IDX].uptr;
n.absoluteFrequencySSB = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX].i64ptr;
n.tac = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_TAC_IDX].uptr;
char neighbour_plmn_path[CONFIG_MAXOPTLENGTH];
snprintf(neighbour_plmn_path,
sizeof(neighbour_plmn_path),
"%s.%s.[%i].%s",
neighbourpath,
GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST,
l,
GNB_CONFIG_STRING_NEIGHBOUR_PLMN);
GET_PARAMS(NeighbourPlmn, GNBPLMNPARAMS_DESC, neighbour_plmn_path);
n.plmn.mcc = *NeighbourPlmn[GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
n.plmn.mnc = *NeighbourPlmn[GNB_MOBILE_NETWORK_CODE_IDX].uptr;
n.plmn.mnc_digit_length = *NeighbourPlmn[GNB_MNC_DIGIT_LENGTH].uptr;
if (get_neighbour_by_pci(cell.neighbour_cells, n.physicalCellId) != NULL) {
LOG_E(GNB_APP,
"Cell %ld: duplicate PCI %d in neighbour list (nrcell_id %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));
LOG_I(GNB_APP,
" [%d] neighbor ID %d cellId %ld PCI %d SCS %d SSB ARFCN %u TAC %u PLMN %03u.%0*u\n",
l,
n.gNB_ID,
n.nrcell_id,
n.physicalCellId,
n.subcarrierSpacing,
n.absoluteFrequencySSB,
n.tac,
n.plmn.mcc,
n.plmn.mnc_digit_length,
n.plmn.mnc);
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(rrc->neighbour_cell_configuration, &cell, sizeof(cell));
seq_arr_push_back(cell->neighbour_cells, &n, sizeof(n));
}
}
static void sort_neighbour_configuration(gNB_RRC_INST *rrc)
{
void *base = seq_arr_front(rrc->neighbour_cell_configuration);
size_t nmemb = seq_arr_size(rrc->neighbour_cell_configuration);
size_t element_size = sizeof(neighbour_cell_configuration_t);
qsort(base, nmemb, element_size, sort_neighbour_cell_config_by_cell_id);
}
static void fill_neighbour_cell_configuration(const uint8_t gnb_idx, gNB_RRC_INST *rrc)
{
char path[MAX_OPTNAME_SIZE + 8];
snprintf(path, sizeof(path), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx);
GET_PARAMS_LIST(nlist, nparams, GNB_NEIGHBOUR_LIST_PARAM_LIST, GNB_CONFIG_STRING_NEIGHBOUR_LIST, path);
if (nlist.numelt < 1)
return;
rrc->neighbour_cell_configuration = malloc_or_fail(sizeof(seq_arr_t));
seq_arr_init(rrc->neighbour_cell_configuration, sizeof(neighbour_cell_configuration_t));
for (int elm = 0; elm < nlist.numelt; ++elm) {
neighbour_cell_configuration_t cell = {.nr_cell_id = *nlist.paramarray[elm][0].u64ptr};
snprintf(path, sizeof(path), "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx, GNB_CONFIG_STRING_NEIGHBOUR_LIST, elm);
GET_PARAMS_LIST(ncell_list, ncell_params, GNBNEIGHBOURCELLPARAMS_DESC, GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST, path);
if (ncell_list.numelt < 1)
continue;
parse_neighbour_cells_list(&cell, &ncell_list, path);
seq_arr_push_back(rrc->neighbour_cell_configuration, &cell, sizeof(cell));
}
sort_neighbour_configuration(rrc);
}
static void fill_measurement_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
{
char measurement_path[MAX_OPTNAME_SIZE + 8];
+11 -5
View File
@@ -31,19 +31,25 @@ uint16_t set_snssai_config(nssai_t *nssai, const int max_num_ssi, uint8_t k, uin
return num_ssi;
}
plmn_id_t extract_plmn_from_params(const paramdef_t *params, int n_params)
{
plmn_id_t plmn = {.mcc = *gpd(params, n_params, GNB_CONFIG_STRING_MOBILE_COUNTRY_CODE)->uptr,
.mnc = *gpd(params, n_params, GNB_CONFIG_STRING_MOBILE_NETWORK_CODE)->uptr,
.mnc_digit_length = *gpd(params, n_params, GNB_CONFIG_STRING_MNC_DIGIT_LENGTH)->uptr};
AssertFatal((plmn.mnc_digit_length == 2) || (plmn.mnc_digit_length == 3), "BAD MNC DIGIT LENGTH %d", plmn.mnc_digit_length);
return plmn;
}
uint8_t set_plmn_config(plmn_id_t *p, uint8_t idx)
{
char gnbpath[MAX_OPTNAME_SIZE * 2 + 8];
snprintf(gnbpath, sizeof(gnbpath), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, idx);
GET_PARAMS_LIST(PLMNParamList, PLMNParams, GNBPLMNPARAMS_DESC, GNB_CONFIG_STRING_PLMN_LIST, gnbpath, PLMNPARAMS_CHECK);
uint8_t num_plmn = PLMNParamList.numelt;
const int n_plmn_params = sizeofArray(PLMNParams);
AssertFatal(num_plmn >= 1 && num_plmn <= 6, "The number of PLMN IDs must be in [1,6], but is %d\n", num_plmn);
for (int l = 0; l < num_plmn; ++l) {
plmn_id_t *plmn = &p[l];
plmn->mcc = *PLMNParamList.paramarray[l][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
plmn->mnc = *PLMNParamList.paramarray[l][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
plmn->mnc_digit_length = *PLMNParamList.paramarray[l][GNB_MNC_DIGIT_LENGTH].u8ptr;
AssertFatal((plmn->mnc_digit_length == 2) || (plmn->mnc_digit_length == 3), "BAD MNC DIGIT LENGTH %d", plmn->mnc_digit_length);
p[l] = extract_plmn_from_params(PLMNParamList.paramarray[l], n_plmn_params);
}
return num_plmn;
}
+2
View File
@@ -4,6 +4,8 @@
#include <assert.h>
#include "common/5g_platform_types.h"
#include "common/config/config_paramdesc.h"
uint16_t set_snssai_config(nssai_t *nssai, const int max_num_ssi, uint8_t k, uint8_t l);
uint8_t set_plmn_config(plmn_id_t *p, uint8_t idx);
plmn_id_t extract_plmn_from_params(const paramdef_t *params, int n_params);