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:
batuhan duyuler
2024-06-04 07:54:00 +02:00
committed by Robert Schmidt
parent e5afdcdd43
commit cec6b8925a
7 changed files with 765 additions and 2 deletions
+43
View File
@@ -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;
+83
View File
@@ -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) {
+2
View File
@@ -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);