Commit c53b28f5 authored by Guido Casati's avatar Guido Casati

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
parent 9afa9404
...@@ -2012,6 +2012,108 @@ static nr_neighbour_cell_t *get_neighbour_by_pci(seq_arr_t *neighbour_cells, int ...@@ -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, ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment