Preparation of Neighbour Configuration & Measurement Configuration | Parsing the configuration
- neighbour_config.conf file includes neighbour and measurement related parameters
Neighbour List:
- nr_cellid: the identity of existing cell who has neighbour
- neighbour_cell_configuration(list): includes the identity parameters
of the neighbour cell such:
- gNBID (incase of N2 Handover / to be identified from AMF)
- nr_cell_id (target gNB needs to consider)
- physical_cellId (needed for measurement reporting)
- absoluteFrequencySSB (needed for measurement reporting)
- subcarrierSpacing (needed for measurement reporting)
- plmn / tracking area code (incase of N2 Handover / needed for AMF
to identify / allow HO)
NR Measurement Configuration
- Periodical
- enable (default is 0, 1 enables the reporting)
- includeBeamMeasurements, maxNrOfRS_IndexesToReport (configurable
reporting parameters)
- A2
- enable (default is 0, 1 enables the reporting)
- threshold , timeToTrigger (configurable reporting parameters)
- A3
- cell_id (the nr_cellid of neighbour cell. So this A3 parameters
will be used for the neighbour
- [-1] means default. so it can be applied to any neighbour if
there is no specific config
- Neighbour specific A3 Threshold can be used or default can be
selected depending to the neighbour planning
- The neighbour-config.conf specifies, apply default A3 for
neighbours 3 and 4 | apply specific one for neighbour 2
- offset, hysteresis, timeToTrigger (configurable reporting parameters)
the neighbour_config.conf can be included in the gNB.conf file. Example
is given: gnb.sa.band78.106prb.rfsim.neighbour.conf
A sequence array container is used for neighbour cell configuration. RRC
structure has this container. A Measurement configuration structure is
defined. This structure has Periodical / A2 Event structures and also a
sequence container for A3 Event List.
These structures are filled during the initialization. While F1 Setup
Response is coming from DU to CU, the intra frequency / inter frequency
neighbour decision is given for the existing cell. Also new neighbours
could be added here if needed.
This commit is contained in:
committed by
Robert Schmidt
parent
e5afdcdd43
commit
cec6b8925a
@@ -37,6 +37,7 @@
|
||||
|
||||
#include "collection/tree.h"
|
||||
#include "collection/linear_alloc.h"
|
||||
#include "common/utils/ds/seq_arr.h"
|
||||
#include "nr_rrc_common.h"
|
||||
#include "ds/byte_array.h"
|
||||
|
||||
@@ -359,6 +360,46 @@ typedef struct {
|
||||
int do_drb_integrity;
|
||||
} nr_security_configuration_t;
|
||||
|
||||
typedef struct {
|
||||
long maxReportCells;
|
||||
bool includeBeamMeasurements;
|
||||
} nr_per_event_t;
|
||||
|
||||
typedef struct {
|
||||
long threshold_RSRP;
|
||||
long timeToTrigger;
|
||||
} nr_a2_event_t;
|
||||
|
||||
typedef struct {
|
||||
int cell_id;
|
||||
long a3_offset;
|
||||
long hysteresis;
|
||||
long timeToTrigger;
|
||||
} nr_a3_event_t;
|
||||
|
||||
typedef struct {
|
||||
nr_per_event_t *per_event;
|
||||
nr_a2_event_t *a2_event;
|
||||
seq_arr_t *a3_event_list;
|
||||
bool is_default_a3_configuration_exists;
|
||||
} nr_measurement_configuration_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t gNB_ID;
|
||||
uint64_t nrcell_id;
|
||||
int physicalCellId;
|
||||
int absoluteFrequencySSB;
|
||||
int subcarrierSpacing;
|
||||
plmn_identity_t plmn;
|
||||
uint32_t tac;
|
||||
bool isIntraFrequencyNeighbour;
|
||||
} nr_neighbour_gnb_configuration_t;
|
||||
|
||||
typedef struct neighbour_cell_configuration_s {
|
||||
int nr_cell_id;
|
||||
seq_arr_t *neighbour_cells;
|
||||
} neighbour_cell_configuration_t;
|
||||
|
||||
typedef struct nr_mac_rrc_dl_if_s {
|
||||
f1_setup_response_func_t f1_setup_response;
|
||||
f1_setup_failure_func_t f1_setup_failure;
|
||||
@@ -423,6 +464,8 @@ typedef struct gNB_RRC_INST_s {
|
||||
|
||||
nr_mac_rrc_dl_if_t mac_rrc;
|
||||
cucp_cuup_if_t cucp_cuup;
|
||||
seq_arr_t *neighbour_cell_configuration;
|
||||
nr_measurement_configuration_t measurementConfiguration;
|
||||
|
||||
RB_HEAD(rrc_du_tree, nr_rrc_du_container_t) dus; // DUs, indexed by assoc_id
|
||||
size_t num_dus;
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "openair2/F1AP/f1ap_common.h"
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "common/utils/ds/seq_arr.h"
|
||||
#include "common/utils/alg/foreach.h"
|
||||
|
||||
int get_dl_band(const struct f1ap_served_cell_info_t *cell_info)
|
||||
{
|
||||
@@ -121,6 +123,80 @@ static NR_MeasurementTimingConfiguration_t *extract_mtc(uint8_t *buf, int buf_le
|
||||
return mtc;
|
||||
}
|
||||
|
||||
static int nr_cell_id_match(const void *key, const void *element)
|
||||
{
|
||||
const int *key_id = (const int *)key;
|
||||
const neighbour_cell_configuration_t *config_element = (const neighbour_cell_configuration_t *)element;
|
||||
|
||||
if (*key_id < config_element->nr_cell_id) {
|
||||
return -1;
|
||||
} else if (*key_id == config_element->nr_cell_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static neighbour_cell_configuration_t *get_cell_neighbour_list(const gNB_RRC_INST *rrc, const f1ap_served_cell_info_t *cell_info)
|
||||
{
|
||||
void *base = seq_arr_front(rrc->neighbour_cell_configuration);
|
||||
size_t nmemb = seq_arr_size(rrc->neighbour_cell_configuration);
|
||||
size_t size = sizeof(neighbour_cell_configuration_t);
|
||||
|
||||
void *it = bsearch((void *)&cell_info->nr_cellid, base, nmemb, size, nr_cell_id_match);
|
||||
|
||||
return (neighbour_cell_configuration_t *)it;
|
||||
}
|
||||
|
||||
const struct f1ap_served_cell_info_t *get_cell_information_by_phycellId(int phyCellId)
|
||||
{
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
nr_rrc_du_container_t *it = NULL;
|
||||
RB_FOREACH (it, rrc_du_tree, &rrc->dus) {
|
||||
for (int cellIdx = 0; cellIdx < it->setup_req->num_cells_available; cellIdx++) {
|
||||
const f1ap_served_cell_info_t *cell_info = &(it->setup_req->cell[cellIdx].info);
|
||||
if (cell_info->nr_pci == phyCellId) {
|
||||
LOG_D(NR_RRC, "HO LOG: Found cell with phyCellId %d\n", phyCellId);
|
||||
return cell_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void is_intra_frequency_neighbour(void *ssb_arfcn, void *neighbour_cell)
|
||||
{
|
||||
uint32_t *ssb_arfcn_ptr = (uint32_t *)ssb_arfcn;
|
||||
nr_neighbour_gnb_configuration_t *neighbour_cell_ptr = (nr_neighbour_gnb_configuration_t *)neighbour_cell;
|
||||
|
||||
if (*ssb_arfcn_ptr == neighbour_cell_ptr->absoluteFrequencySSB) {
|
||||
LOG_D(NR_RRC, "HO LOG: found intra frequency neighbour %lu!\n", neighbour_cell_ptr->nrcell_id);
|
||||
neighbour_cell_ptr->isIntraFrequencyNeighbour = true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Labels neighbour cells if they are intra frequency to prepare meas config only for intra frequency ho
|
||||
* @param[in] rrc Pointer to RRC instance
|
||||
* @param[in] cell_info Pointer to cell information
|
||||
*/
|
||||
static void label_intra_frequency_neighbours(gNB_RRC_INST *rrc,
|
||||
const nr_rrc_du_container_t *du,
|
||||
const f1ap_served_cell_info_t *cell_info)
|
||||
{
|
||||
if (!rrc->neighbour_cell_configuration)
|
||||
return;
|
||||
|
||||
neighbour_cell_configuration_t *neighbour_cell_config = get_cell_neighbour_list(rrc, cell_info);
|
||||
if (!neighbour_cell_config)
|
||||
return;
|
||||
|
||||
LOG_D(NR_RRC, "HO LOG: Cell: %lu has neighbour cell configuration!\n", cell_info->nr_cellid);
|
||||
uint32_t ssb_arfcn = get_ssb_arfcn(du);
|
||||
|
||||
seq_arr_t *cell_neighbour_list = neighbour_cell_config->neighbour_cells;
|
||||
for_each(cell_neighbour_list, (void *)&ssb_arfcn, is_intra_frequency_neighbour);
|
||||
}
|
||||
|
||||
void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
{
|
||||
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
|
||||
@@ -229,6 +305,9 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
.num_SI = 0,
|
||||
};
|
||||
|
||||
if (du->mib != NULL && du->sib1 != NULL)
|
||||
label_intra_frequency_neighbours(rrc, du, cell_info);
|
||||
|
||||
f1ap_setup_resp_t resp = {.transaction_id = req->transaction_id,
|
||||
.num_cells_to_activate = 1,
|
||||
.cells_to_activate[0] = cell};
|
||||
@@ -350,6 +429,10 @@ void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update
|
||||
LOG_I(RRC, "update system information of DU %ld\n", du->setup_req->gNB_DU_id);
|
||||
}
|
||||
}
|
||||
if (du->mib != NULL && du->sib1 != NULL) {
|
||||
const f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info;
|
||||
label_intra_frequency_neighbours(rrc, du, cell_info);
|
||||
}
|
||||
}
|
||||
|
||||
if (conf_up->num_cells_to_delete > 0) {
|
||||
|
||||
@@ -32,6 +32,7 @@ struct f1ap_lost_connection_t;
|
||||
struct gNB_RRC_INST_s;
|
||||
struct nr_rrc_du_container_t;
|
||||
struct f1ap_gnb_du_configuration_update_s;
|
||||
struct f1ap_served_cell_info_t;
|
||||
|
||||
void rrc_gNB_process_f1_setup_req(struct f1ap_setup_req_s *req, sctp_assoc_t assoc_id);
|
||||
void rrc_CU_process_f1_lost_connection(struct gNB_RRC_INST_s *rrc, struct f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id);
|
||||
@@ -39,6 +40,7 @@ void rrc_gNB_process_f1_du_configuration_update(struct f1ap_gnb_du_configuration
|
||||
|
||||
struct nr_rrc_du_container_t *get_du_for_ue(struct gNB_RRC_INST_s *rrc, uint32_t ue_id);
|
||||
struct nr_rrc_du_container_t *get_du_by_assoc_id(struct gNB_RRC_INST_s *rrc, sctp_assoc_t assoc_id);
|
||||
const struct f1ap_served_cell_info_t *get_cell_information_by_phycellId(int phyCellId);
|
||||
|
||||
void dump_du_info(const struct gNB_RRC_INST_s *rrc, FILE *f);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user