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:
@@ -2012,94 +2012,81 @@ static nr_neighbour_cell_t *get_neighbour_by_pci(seq_arr_t *neighbour_cells, int
|
|||||||
return NULL;
|
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];
|
cell->neighbour_cells = malloc_or_fail(sizeof(seq_arr_t));
|
||||||
snprintf(gnbpath, sizeof(gnbpath), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx);
|
seq_arr_init(cell->neighbour_cells, sizeof(nr_neighbour_cell_t));
|
||||||
|
|
||||||
GET_PARAMS_LIST(neighbour_list_param_list,
|
for (int l = 0; l < list->numelt; ++l) {
|
||||||
neighbour_list_params,
|
const paramdef_t *cell_params = list->paramarray[l];
|
||||||
GNB_NEIGHBOUR_LIST_PARAM_LIST,
|
nr_neighbour_cell_t n = {.gNB_ID = *cell_params[GNB_CONFIG_N_CELL_GNB_ID_IDX].uptr,
|
||||||
GNB_CONFIG_STRING_NEIGHBOUR_LIST,
|
.nrcell_id = (uint64_t)*cell_params[GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr,
|
||||||
gnbpath);
|
.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)
|
char p[CONFIG_MAXOPTLENGTH]; // plmn path
|
||||||
return;
|
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));
|
LOG_I(GNB_APP,
|
||||||
seq_arr_init(rrc->neighbour_cell_configuration, sizeof(neighbour_cell_configuration_t));
|
"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) {
|
if (get_neighbour_by_pci(cell->neighbour_cells, n.physicalCellId) != NULL) {
|
||||||
neighbour_cell_configuration_t cell = {0};
|
LOG_E(GNB_APP, "Cell %ld: duplicate PCI %d in neighbour list (NCI=%ld)\n", cell->nr_cell_id, n.physicalCellId, n.nrcell_id);
|
||||||
cell.nr_cell_id = (uint64_t)*neighbour_list_param_list.paramarray[elm][0].u64ptr;
|
AssertFatal(false, "PCI must be unique within a cell's neighbour list\n");
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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);
|
void *base = seq_arr_front(rrc->neighbour_cell_configuration);
|
||||||
size_t nmemb = seq_arr_size(rrc->neighbour_cell_configuration);
|
size_t nmemb = seq_arr_size(rrc->neighbour_cell_configuration);
|
||||||
size_t element_size = sizeof(neighbour_cell_configuration_t);
|
size_t element_size = sizeof(neighbour_cell_configuration_t);
|
||||||
|
|
||||||
qsort(base, nmemb, element_size, sort_neighbour_cell_config_by_cell_id);
|
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)
|
static void fill_measurement_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
|
||||||
{
|
{
|
||||||
char measurement_path[MAX_OPTNAME_SIZE + 8];
|
char measurement_path[MAX_OPTNAME_SIZE + 8];
|
||||||
|
|||||||
@@ -31,19 +31,25 @@ uint16_t set_snssai_config(nssai_t *nssai, const int max_num_ssi, uint8_t k, uin
|
|||||||
return num_ssi;
|
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)
|
uint8_t set_plmn_config(plmn_id_t *p, uint8_t idx)
|
||||||
{
|
{
|
||||||
char gnbpath[MAX_OPTNAME_SIZE * 2 + 8];
|
char gnbpath[MAX_OPTNAME_SIZE * 2 + 8];
|
||||||
snprintf(gnbpath, sizeof(gnbpath), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, idx);
|
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);
|
GET_PARAMS_LIST(PLMNParamList, PLMNParams, GNBPLMNPARAMS_DESC, GNB_CONFIG_STRING_PLMN_LIST, gnbpath, PLMNPARAMS_CHECK);
|
||||||
uint8_t num_plmn = PLMNParamList.numelt;
|
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);
|
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) {
|
for (int l = 0; l < num_plmn; ++l) {
|
||||||
plmn_id_t *plmn = &p[l];
|
p[l] = extract_plmn_from_params(PLMNParamList.paramarray[l], n_plmn_params);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
return num_plmn;
|
return num_plmn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "common/5g_platform_types.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);
|
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);
|
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user