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;
|
||||
}
|
||||
|
||||
/** @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
|
||||
* @param[in,out] cell Neighbour cell configuration to populate
|
||||
* @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,
|
||||
.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
|
||||
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);
|
||||
@@ -2087,6 +2194,9 @@ static void fill_neighbour_cell_configuration(const uint8_t gnb_idx, gNB_RRC_INS
|
||||
if (nlist.numelt < 1)
|
||||
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));
|
||||
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_TRACKING_ARE_CODE "tracking_area_code"
|
||||
#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
|
||||
#define GNBNEIGHBOURCELLPARAMS_DESC { /* optname helpstr paramflags XXXptr def val type numelt */ \
|
||||
@@ -324,9 +329,82 @@ typedef enum {
|
||||
{GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE, \
|
||||
"neighbour cell tracking area (0..16777215)", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0, \
|
||||
.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
|
||||
|
||||
/* 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*/
|
||||
|
||||
#define GNB_CONFIG_STRING_MEASUREMENT_CONFIGURATION "nr_measurement_configuration"
|
||||
|
||||
@@ -312,6 +312,72 @@ typedef struct {
|
||||
bool is_default_a3_configuration_exists;
|
||||
} 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 {
|
||||
uint32_t gNB_ID;
|
||||
uint64_t nrcell_id;
|
||||
@@ -322,6 +388,10 @@ typedef struct {
|
||||
plmn_id_t plmn;
|
||||
uint32_t tac;
|
||||
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;
|
||||
|
||||
typedef struct neighbour_cell_configuration_s {
|
||||
@@ -540,6 +610,9 @@ typedef struct gNB_RRC_INST_s {
|
||||
|
||||
nr_mac_rrc_dl_if_t mac_rrc;
|
||||
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;
|
||||
nr_measurement_configuration_t measurementConfiguration;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user