RRC: add SIB3/SIB4 neighbour offsets and inter-frequency SIB4 config
Introduce typed SIB3/SIB4 neighbour and inter-frequency carrier configuration structures, wire them into the RRC neighbour and gNB instances, and centralise parsing and bounds checking of per-frequency SIB4 parameters from the gNB frequency list. Changes: - Define SIB3/SIB4 reselection and offset bound macros in gnb_config.c and apply them when parsing SIB4 frequency_config and per-carrier q_RxLevMin/t_ReselectionNR. - Add add_inter_freq and parse_inter_freq_list helpers in gnb_config.c to populate a shared inter_freqs seq_arr_t from gNB_CONFIG_STRING_GNB_LIST frequency_list entries, enforcing unique (ARFCN,SCS) combinations and logging duplicates. - Extend neighbour cell parameters in gnb_paramdef.h with SIB3 per- neighbour offset fields and define frequency_list/frequency_config option names, descriptor tables, and index constants for SIB4 inter- frequency configuration. - Introduce nr_neighbour_cell_neighbor_offset_t, nr_neighbour_cell_sib3_t, nr_neighbour_cell_sib4_freq_t, nr_neighbour_cell_sib4_t, and nr_inter_freq_cfg_t in nr_rrc_defs.h, and extend nr_neighbour_cell_t and gNB_RRC_INST with sib3/sib4 and inter_freqs members respectively. - udpated fill_neighbour_cell_configuration to use GET_PARAMS_LIST with params bound check
This commit is contained in:
@@ -2012,6 +2012,108 @@ static nr_neighbour_cell_t *get_neighbour_by_pci(seq_arr_t *neighbour_cells, int
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Parse gNB-level inter-frequency list (frequency_list) into a shared array.
|
||||||
|
* This parses gNBs.[gnb_idx].frequency_list once and validates per-frequency SIB4
|
||||||
|
* parameters. The resulting list can then be reused for all serving cells.
|
||||||
|
* @param[out] inter_freqs Sequence array of nr_inter_freq_cfg_t to populate
|
||||||
|
* @param[in] gnb_idx gNB index */
|
||||||
|
static bool eq_inter_freq_arfcn_scs(const void *vval, const void *vit)
|
||||||
|
{
|
||||||
|
const nr_inter_freq_cfg_t *key = (const nr_inter_freq_cfg_t *)vval;
|
||||||
|
const nr_inter_freq_cfg_t *cur = (const nr_inter_freq_cfg_t *)vit;
|
||||||
|
return key->arfcn == cur->arfcn && key->scs == cur->scs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Insert an inter-frequency config if (ARFCN,SCS) is unique in the list.
|
||||||
|
* Fails fast if a duplicate is found.
|
||||||
|
* @param[in,out] inter_freqs Existing inter-frequency list
|
||||||
|
* @param[in] f Candidate entry to insert (by value)
|
||||||
|
* @param[in] gnb_idx gNB index for logging
|
||||||
|
*/
|
||||||
|
static void add_inter_freq(seq_arr_t *inter_freqs, const nr_inter_freq_cfg_t *f, uint8_t gnb_idx)
|
||||||
|
{
|
||||||
|
const nr_inter_freq_cfg_t key = {.arfcn = f->arfcn, .scs = f->scs};
|
||||||
|
elm_arr_t dup = find_if(inter_freqs, (void *)&key, eq_inter_freq_arfcn_scs);
|
||||||
|
if (dup.found) {
|
||||||
|
AssertFatal(false, "gNB %d: duplicate inter-freq carrier ARFCN %d, SCS %d in frequency_list\n", gnb_idx, f->arfcn, f->scs);
|
||||||
|
}
|
||||||
|
|
||||||
|
seq_arr_push_back(inter_freqs, (void *)f, sizeof(*f));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_inter_freq_list(seq_arr_t *inter_freqs, const uint8_t gnb_idx)
|
||||||
|
{
|
||||||
|
seq_arr_init(inter_freqs, sizeof(nr_inter_freq_cfg_t));
|
||||||
|
|
||||||
|
char freq_path[MAX_OPTNAME_SIZE + 8];
|
||||||
|
snprintf(freq_path, sizeof(freq_path), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx);
|
||||||
|
GET_PARAMS_LIST(freq_list, freq_params, GNBFREQUENCYPARAMS_DESC, GNB_CONFIG_STRING_FREQUENCY_LIST, freq_path);
|
||||||
|
|
||||||
|
for (int i = 0; i < freq_list.numelt; ++i) {
|
||||||
|
const paramdef_t *freq_item = freq_list.paramarray[i];
|
||||||
|
nr_inter_freq_cfg_t f = {0};
|
||||||
|
f.arfcn = *gpd(freq_item, sizeofArray(freq_params), GNB_CONFIG_STRING_FREQUENCY_ABS_FREQ_SSB)->i64ptr;
|
||||||
|
f.scs = *gpd(freq_item, sizeofArray(freq_params), GNB_CONFIG_STRING_FREQUENCY_SCS)->uptr;
|
||||||
|
|
||||||
|
char cfg_path[MAX_OPTNAME_SIZE + 16];
|
||||||
|
snprintf(cfg_path,
|
||||||
|
sizeof(cfg_path),
|
||||||
|
"%s.[%i].%s.[%i]",
|
||||||
|
GNB_CONFIG_STRING_GNB_LIST,
|
||||||
|
gnb_idx,
|
||||||
|
GNB_CONFIG_STRING_FREQUENCY_LIST,
|
||||||
|
i);
|
||||||
|
GET_PARAMS(freq_cfg, GNBFREQUENCYCONFIGPARAMS_DESC, cfg_path);
|
||||||
|
|
||||||
|
nr_neighbour_cell_sib4_freq_t *p = &f.freq_cfg;
|
||||||
|
|
||||||
|
p->cellReselectionPriority = *freq_cfg[GNB_CONFIG_FREQUENCY_CELL_RESEL_PRIO_IDX].iptr;
|
||||||
|
p->threshX_HighP = *freq_cfg[GNB_CONFIG_FREQUENCY_THRESH_X_HIGH_P_IDX].iptr;
|
||||||
|
p->threshX_LowP = *freq_cfg[GNB_CONFIG_FREQUENCY_THRESH_X_LOW_P_IDX].iptr;
|
||||||
|
p->threshX_HighQ = *freq_cfg[GNB_CONFIG_FREQUENCY_THRESH_X_HIGH_Q_IDX].iptr;
|
||||||
|
p->threshX_LowQ = *freq_cfg[GNB_CONFIG_FREQUENCY_THRESH_X_LOW_Q_IDX].iptr;
|
||||||
|
p->q_OffsetFreq = *freq_cfg[GNB_CONFIG_FREQUENCY_Q_OFFSET_FREQ_IDX].iptr;
|
||||||
|
f.q_RxLevMin = *freq_cfg[GNB_CONFIG_FREQUENCY_Q_RXLEVMIN_IDX].iptr;
|
||||||
|
f.t_ReselectionNR = *freq_cfg[GNB_CONFIG_FREQUENCY_T_RESEL_NR_IDX].uptr;
|
||||||
|
|
||||||
|
/* Add inter-frequency configuration to the list. */
|
||||||
|
add_inter_freq(inter_freqs, &f, gnb_idx);
|
||||||
|
|
||||||
|
LOG_I(GNB_APP,
|
||||||
|
"gNB %d: SIB4 inter-freq ARFCN %d, SCS %d, prio=%d, ThreshX_HighP=%d, ThreshX_LowP=%d, ThreshX_HighQ=%d, "
|
||||||
|
"ThreshX_LowQ=%d, q_OffsetFreq=%d\n",
|
||||||
|
gnb_idx,
|
||||||
|
f.arfcn,
|
||||||
|
f.scs,
|
||||||
|
f.freq_cfg.cellReselectionPriority,
|
||||||
|
f.freq_cfg.threshX_HighP,
|
||||||
|
f.freq_cfg.threshX_LowP,
|
||||||
|
f.freq_cfg.threshX_HighQ,
|
||||||
|
f.freq_cfg.threshX_LowQ,
|
||||||
|
f.freq_cfg.q_OffsetFreq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_sib3_offsets(nr_neighbour_cell_t *n, const paramdef_t *cell_params, int n_cell_params)
|
||||||
|
{
|
||||||
|
nr_neighbour_cell_neighbor_offset_t *sib3_off = &n->sib3.offset;
|
||||||
|
|
||||||
|
/* SIB3 per-neighbour offsets */
|
||||||
|
sib3_off->q_OffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_OFFSET_CELL)->iptr;
|
||||||
|
sib3_off->q_RxLevMinOffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_RXLEVMIN_OFFSET_CELL)->iptr;
|
||||||
|
sib3_off->q_QualMinOffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_QUALMIN_OFFSET_CELL)->iptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_sib4_offsets(nr_neighbour_cell_t *n, const paramdef_t *cell_params, int n_cell_params)
|
||||||
|
{
|
||||||
|
nr_neighbour_cell_neighbor_offset_t *sib4_off = &n->sib4.offset;
|
||||||
|
|
||||||
|
/* SIB4 per-neighbour offsets */
|
||||||
|
sib4_off->q_OffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_OFFSET_CELL)->iptr;
|
||||||
|
sib4_off->q_RxLevMinOffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_RXLEVMIN_OFFSET_CELL)->iptr;
|
||||||
|
sib4_off->q_QualMinOffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_QUALMIN_OFFSET_CELL)->iptr;
|
||||||
|
}
|
||||||
|
|
||||||
/** @brief Parse and add neighbour cells for a given cell configuration
|
/** @brief Parse and add neighbour cells for a given cell configuration
|
||||||
* @param[in,out] cell Neighbour cell configuration to populate
|
* @param[in,out] cell Neighbour cell configuration to populate
|
||||||
* @param[in] list Parameter list describing neighbour cells
|
* @param[in] list Parameter list describing neighbour cells
|
||||||
@@ -2036,6 +2138,11 @@ static void parse_neighbour_cells_list(neighbour_cell_configuration_t *cell,
|
|||||||
.absoluteFrequencySSB = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB)->i64ptr,
|
.absoluteFrequencySSB = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB)->i64ptr,
|
||||||
.tac = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE)->uptr};
|
.tac = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE)->uptr};
|
||||||
|
|
||||||
|
set_sib3_offsets(&n, cell_params, n_cell_params);
|
||||||
|
set_sib4_offsets(&n, cell_params, n_cell_params);
|
||||||
|
/* SIB4 per-frequency reselection parameters (q_OffsetFreq, thresholds, priority)
|
||||||
|
* are populated in parse_inter_freq_list() per-frequency, not per neighbour here. */
|
||||||
|
|
||||||
char p[CONFIG_MAXOPTLENGTH]; // plmn path
|
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);
|
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);
|
GET_PARAMS(NeighbourPlmn, GNBPLMNPARAMS_DESC, p);
|
||||||
@@ -2087,6 +2194,9 @@ static void fill_neighbour_cell_configuration(const uint8_t gnb_idx, gNB_RRC_INS
|
|||||||
if (nlist.numelt < 1)
|
if (nlist.numelt < 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Parse gNB-level inter-frequency configuration once and reuse it for all cells. */
|
||||||
|
parse_inter_freq_list(&rrc->inter_freqs, gnb_idx);
|
||||||
|
|
||||||
rrc->neighbour_cell_configuration = malloc_or_fail(sizeof(seq_arr_t));
|
rrc->neighbour_cell_configuration = malloc_or_fail(sizeof(seq_arr_t));
|
||||||
seq_arr_init(rrc->neighbour_cell_configuration, sizeof(neighbour_cell_configuration_t));
|
seq_arr_init(rrc->neighbour_cell_configuration, sizeof(neighbour_cell_configuration_t));
|
||||||
|
|
||||||
|
|||||||
@@ -300,6 +300,11 @@ typedef enum {
|
|||||||
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_BAND "band"
|
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_BAND "band"
|
||||||
#define GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE "tracking_area_code"
|
#define GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE "tracking_area_code"
|
||||||
#define GNB_CONFIG_STRING_NEIGHBOUR_PLMN "plmn"
|
#define GNB_CONFIG_STRING_NEIGHBOUR_PLMN "plmn"
|
||||||
|
/* SIB3 fields (intra-frequency) - per-neighbor */
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_OFFSET_CELL "q_OffsetCell"
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_RXLEVMIN_OFFSET_CELL "q_RxLevMinOffsetCell"
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_QUALMIN_OFFSET_CELL "q_QualMinOffsetCell"
|
||||||
|
/* SIB4 per-frequency fields are configured in frequency_list.frequency_config */
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#define GNBNEIGHBOURCELLPARAMS_DESC { /* optname helpstr paramflags XXXptr def val type numelt */ \
|
#define GNBNEIGHBOURCELLPARAMS_DESC { /* optname helpstr paramflags XXXptr def val type numelt */ \
|
||||||
@@ -324,9 +329,82 @@ typedef enum {
|
|||||||
{GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE, \
|
{GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE, \
|
||||||
"neighbour cell tracking area (0..16777215)", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0, \
|
"neighbour cell tracking area (0..16777215)", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0, \
|
||||||
.chkPptr = &(checkedparam_t){.s2 = {config_check_uintrange, {0, 16777215}}}}, \
|
.chkPptr = &(checkedparam_t){.s2 = {config_check_uintrange, {0, 16777215}}}}, \
|
||||||
|
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_OFFSET_CELL, \
|
||||||
|
"Q-OffsetCell for SIB3/SIB4 (Q-OffsetRange, default 0)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
|
||||||
|
.chkPptr = &(checkedparam_t){.s1 = {config_check_intval, \
|
||||||
|
{-24, -22, -20, -18, -16, -14, -12, -10, -8, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24}, 31}}}, \
|
||||||
|
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_RXLEVMIN_OFFSET_CELL, \
|
||||||
|
"Q-RxLevMinOffsetCell for SIB3/SIB4 (1..8 or -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
|
||||||
|
.chkPptr = &(checkedparam_t){.s1 = {config_check_intval, {-1, 1, 2, 3, 4, 5, 6, 7, 8}, 9}}}, \
|
||||||
|
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_QUALMIN_OFFSET_CELL, \
|
||||||
|
"Q-QualMinOffsetCell for SIB3/SIB4 (1..8 or -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
|
||||||
|
.chkPptr = &(checkedparam_t){.s1 = {config_check_intval, {-1, 1, 2, 3, 4, 5, 6, 7, 8}, 9}}}, \
|
||||||
}
|
}
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
/* Per-frequency neighbour configuration (frequency_list) */
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_LIST "frequency_list"
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_ABS_FREQ_SSB "absoluteFrequencySSB"
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_SCS "subcarrierSpacing"
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_BAND "band"
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_CONFIG "frequency_config"
|
||||||
|
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_CELL_RESEL_PRIO "cellReselectionPriority"
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_THRESH_X_HIGH_P "threshX_HighP"
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_THRESH_X_LOW_P "threshX_LowP"
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_THRESH_X_HIGH_Q "threshX_HighQ"
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_THRESH_X_LOW_Q "threshX_LowQ"
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_Q_OFFSET_FREQ "q_OffsetFreq"
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_Q_RXLEVMIN "q_RxLevMin"
|
||||||
|
#define GNB_CONFIG_STRING_FREQUENCY_T_RESEL_NR "t_ReselectionNR"
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
#define GNBFREQUENCYPARAMS_DESC { \
|
||||||
|
/* optname helpstr paramflags XXXptr def val type numelt */ \
|
||||||
|
{GNB_CONFIG_STRING_FREQUENCY_ABS_FREQ_SSB, "inter-frequency abs freq ssb", PARAMFLAG_MANDATORY, .i64ptr=NULL, .defint64val=0, TYPE_INT64, 0}, \
|
||||||
|
{GNB_CONFIG_STRING_FREQUENCY_SCS, "inter-frequency scs", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
|
||||||
|
{GNB_CONFIG_STRING_FREQUENCY_BAND, "inter-frequency band", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=78, TYPE_UINT, 0}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GNBFREQUENCYCONFIGPARAMS_DESC { \
|
||||||
|
{GNB_CONFIG_STRING_FREQUENCY_CELL_RESEL_PRIO, \
|
||||||
|
"SIB4 cellReselectionPriority (0..7, -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
|
||||||
|
.chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-1, 7}}}}, \
|
||||||
|
{GNB_CONFIG_STRING_FREQUENCY_THRESH_X_HIGH_P, \
|
||||||
|
"SIB4 threshX-HighP (0..31)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
|
||||||
|
.chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 31}}}}, \
|
||||||
|
{GNB_CONFIG_STRING_FREQUENCY_THRESH_X_LOW_P, \
|
||||||
|
"SIB4 threshX-LowP (0..31)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
|
||||||
|
.chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 31}}}}, \
|
||||||
|
{GNB_CONFIG_STRING_FREQUENCY_THRESH_X_HIGH_Q, \
|
||||||
|
"SIB4 threshX-HighQ (0..31, -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
|
||||||
|
.chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-1, 31}}}}, \
|
||||||
|
{GNB_CONFIG_STRING_FREQUENCY_THRESH_X_LOW_Q, \
|
||||||
|
"SIB4 threshX-LowQ (0..31, -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
|
||||||
|
.chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-1, 31}}}}, \
|
||||||
|
{GNB_CONFIG_STRING_FREQUENCY_Q_OFFSET_FREQ, \
|
||||||
|
"SIB4 q-OffsetFreq (Q-OffsetRange values, default 0)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
|
||||||
|
.chkPptr = &(checkedparam_t){.s1 = {config_check_intval, {-24, -22, -20, -18, -16, -14, -12, -10, \
|
||||||
|
-8, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24}, 31}}}, \
|
||||||
|
{GNB_CONFIG_STRING_FREQUENCY_Q_RXLEVMIN, \
|
||||||
|
"SIB4 per-carrier Q-RxLevMin (-70..-22, default -22)", 0, .iptr=NULL, .defintval=-22, TYPE_INT, 0, \
|
||||||
|
.chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-70, -22}}}}, \
|
||||||
|
{GNB_CONFIG_STRING_FREQUENCY_T_RESEL_NR, \
|
||||||
|
"SIB4 per-carrier t-ReselectionNR (0..7, default 0)", 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0, \
|
||||||
|
.chkPptr = &(checkedparam_t){.s2 = {config_check_uintrange, {0, 7}}}}, \
|
||||||
|
}
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
/* Indexes into GNBFREQUENCYCONFIGPARAMS_DESC */
|
||||||
|
#define GNB_CONFIG_FREQUENCY_CELL_RESEL_PRIO_IDX 0
|
||||||
|
#define GNB_CONFIG_FREQUENCY_THRESH_X_HIGH_P_IDX 1
|
||||||
|
#define GNB_CONFIG_FREQUENCY_THRESH_X_LOW_P_IDX 2
|
||||||
|
#define GNB_CONFIG_FREQUENCY_THRESH_X_HIGH_Q_IDX 3
|
||||||
|
#define GNB_CONFIG_FREQUENCY_THRESH_X_LOW_Q_IDX 4
|
||||||
|
#define GNB_CONFIG_FREQUENCY_Q_OFFSET_FREQ_IDX 5
|
||||||
|
#define GNB_CONFIG_FREQUENCY_Q_RXLEVMIN_IDX 6
|
||||||
|
#define GNB_CONFIG_FREQUENCY_T_RESEL_NR_IDX 7
|
||||||
|
|
||||||
/* New Measurement Configurations*/
|
/* New Measurement Configurations*/
|
||||||
|
|
||||||
#define GNB_CONFIG_STRING_MEASUREMENT_CONFIGURATION "nr_measurement_configuration"
|
#define GNB_CONFIG_STRING_MEASUREMENT_CONFIGURATION "nr_measurement_configuration"
|
||||||
|
|||||||
@@ -312,6 +312,72 @@ typedef struct {
|
|||||||
bool is_default_a3_configuration_exists;
|
bool is_default_a3_configuration_exists;
|
||||||
} nr_measurement_configuration_t;
|
} nr_measurement_configuration_t;
|
||||||
|
|
||||||
|
/** @brief Per-neighbor cell-specific offsets (TS 38.331), shared by SIB3 and SIB4
|
||||||
|
* Maps to ASN.1 IntraFreqNeighCellInfo and InterFreqNeighCellInfo
|
||||||
|
* (SIB3.IntraFreqNeighCellList, SIB4.InterFreqCarrierFreqInfo.neighCellList) */
|
||||||
|
typedef struct {
|
||||||
|
// q-OffsetCell: (Q-OffsetRange values -24,-22,-20,-18,-16,-14,-12,-10,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8,10,12,14,16,18,20,22,24 dB)
|
||||||
|
// per-neighbor cell ranking
|
||||||
|
int q_OffsetCell;
|
||||||
|
// q-RxLevMinOffsetCell: Q-OffsetCellSmall (1..8): Per-neighbor RSRP minimum offset
|
||||||
|
int q_RxLevMinOffsetCell;
|
||||||
|
// q-QualMinOffsetCell: Q-OffsetCellSmall (1..8): Per-neighbor RSRQ minimum offset
|
||||||
|
int q_QualMinOffsetCell;
|
||||||
|
} nr_neighbour_cell_neighbor_offset_t;
|
||||||
|
|
||||||
|
/** @brief SIB3 (intra-frequency) neighbor list parameters (TS 38.331)
|
||||||
|
* Per-neighbor fields for SIB3.IntraFreqNeighCellList.IntraFreqNeighCellInfo.
|
||||||
|
* SIB3 carries intra-freq neighbor offsets for ranking. */
|
||||||
|
typedef struct {
|
||||||
|
nr_neighbour_cell_neighbor_offset_t offset;
|
||||||
|
} nr_neighbour_cell_sib3_t;
|
||||||
|
|
||||||
|
/** @brief SIB4 inter-frequency carrier parameters (TS 38.331)
|
||||||
|
* Per-frequency fields for SIB4.InterFreqCarrierFreqList.InterFreqCarrierFreqInfo.
|
||||||
|
* Stored once per ARFCN; all neighbors on that frequency share this config. */
|
||||||
|
typedef struct {
|
||||||
|
// cellReselectionPriority (0..7): Absolute priority of this inter-freq carrier
|
||||||
|
int cellReselectionPriority;
|
||||||
|
// threshX-HighP (0..31): RSRP threshold for reselection to a higher-priority inter-freq
|
||||||
|
int threshX_HighP;
|
||||||
|
// threshX-LowP (0..31): RSRP threshold for reselection to a lower-priority inter-freq
|
||||||
|
int threshX_LowP;
|
||||||
|
// threshX-HighQ (0..31): RSRQ threshold for higher-priority inter-freq reselection
|
||||||
|
int threshX_HighQ;
|
||||||
|
// threshX-LowQ (0..31): RSRQ threshold for lower-priority inter-freq reselection
|
||||||
|
int threshX_LowQ;
|
||||||
|
// q-OffsetFreq (Q-OffsetRange values: -24,-22,-20,-18,-16,-14,-12,-10,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8,10,12,14,16,18,20,22,24 dB):
|
||||||
|
// Frequency-specific offset in inter-freq cell ranking formula
|
||||||
|
int q_OffsetFreq;
|
||||||
|
} nr_neighbour_cell_sib4_freq_t;
|
||||||
|
|
||||||
|
/** @brief SIB4 (inter-frequency) parameters per neighbor (TS 38.331)
|
||||||
|
* Combines per-frequency carrier info (InterFreqCarrierFreqInfo) and per-neighbor
|
||||||
|
* offsets (InterFreqNeighCellInfo). */
|
||||||
|
typedef struct {
|
||||||
|
// Per-frequency carrier (InterFreqCarrierFreqInfo)
|
||||||
|
nr_neighbour_cell_sib4_freq_t sib4_freq;
|
||||||
|
// Per-neighbor offsets (InterFreqNeighCellInfo)
|
||||||
|
nr_neighbour_cell_neighbor_offset_t offset;
|
||||||
|
} nr_neighbour_cell_sib4_t;
|
||||||
|
|
||||||
|
/** @brief Per-frequency SIB4 configuration (TS 38.331), keyed by ARFCN
|
||||||
|
* One entry per inter-freq carrier (absoluteFrequencySSB + subcarrierSpacing).
|
||||||
|
* freq_cfg holds InterFreqCarrierFreqInfo parameters. Analogous to one “carrier” slice of SIB4
|
||||||
|
* interFreqCarrierFreqList. */
|
||||||
|
typedef struct {
|
||||||
|
// absoluteFrequencySSB (ARFCN)
|
||||||
|
int arfcn;
|
||||||
|
// ssbSubcarrierSpacing
|
||||||
|
int scs;
|
||||||
|
// q-RxLevMin (-70..-22 dBm)
|
||||||
|
int q_RxLevMin;
|
||||||
|
// t-ReselectionNR (0..7)
|
||||||
|
int t_ReselectionNR;
|
||||||
|
// Inter-frequency carrier parameters (InterFreqCarrierFreqInfo)
|
||||||
|
nr_neighbour_cell_sib4_freq_t freq_cfg;
|
||||||
|
} nr_inter_freq_cfg_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t gNB_ID;
|
uint32_t gNB_ID;
|
||||||
uint64_t nrcell_id;
|
uint64_t nrcell_id;
|
||||||
@@ -322,6 +388,10 @@ typedef struct {
|
|||||||
plmn_id_t plmn;
|
plmn_id_t plmn;
|
||||||
uint32_t tac;
|
uint32_t tac;
|
||||||
bool isIntraFrequencyNeighbour;
|
bool isIntraFrequencyNeighbour;
|
||||||
|
// SIB3 (intra-frequency neighbor cell-specific offsets)
|
||||||
|
nr_neighbour_cell_sib3_t sib3;
|
||||||
|
// SIB4 (inter-frequency neighbor cell-specific parameters)
|
||||||
|
nr_neighbour_cell_sib4_t sib4;
|
||||||
} nr_neighbour_cell_t;
|
} nr_neighbour_cell_t;
|
||||||
|
|
||||||
typedef struct neighbour_cell_configuration_s {
|
typedef struct neighbour_cell_configuration_s {
|
||||||
@@ -540,6 +610,9 @@ typedef struct gNB_RRC_INST_s {
|
|||||||
|
|
||||||
nr_mac_rrc_dl_if_t mac_rrc;
|
nr_mac_rrc_dl_if_t mac_rrc;
|
||||||
cucp_cuup_if_t cucp_cuup;
|
cucp_cuup_if_t cucp_cuup;
|
||||||
|
// Per-frequency SIB4 configurations, indexed by ARFCN
|
||||||
|
seq_arr_t inter_freqs; /* array of nr_inter_freq_cfg_t */
|
||||||
|
// Per-cell neighbour configurations, indexed by cell_id
|
||||||
seq_arr_t *neighbour_cell_configuration;
|
seq_arr_t *neighbour_cell_configuration;
|
||||||
nr_measurement_configuration_t measurementConfiguration;
|
nr_measurement_configuration_t measurementConfiguration;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user