Commit 607f192c authored by batuhan duyuler's avatar batuhan duyuler

Neigbourcell Configuration - Measurement Configuration for Inter gNB - N2 Handover

- NeighbourCell and Measurement Configurations are prepared.

NeighbourCell Configuration includes:
	- neighbour_gNB_ID (This is needed for AMF to identify gNB exists in it's context
	- neighbour_nr_cell_id (This is needed for target gNB)
	- neighbour_physical_cellId (This is needed for UE in the meas report)
	- neighbour_absoluteFrequencySSB (This is needed for UE in meas report)
	- neighbour_subcarrierSpacing (This is needed for UE in meas report)
	- neighbour_mnc (This is needed for AMF)
	- neighbour_mcc (This is needed for AMF)
	- neighbour_mnc_length (This is needed for AMF)
	- neighbour_tracking_area_code (This is needed for AMF)

NR Measurement Event Configuration Includes:
	- enableA2 & enableA3 (gNB activates the event reporting according to these vars)
	- thresholdA2 & A2_TTT (configurable reporting parameters)
	- thresholdA3 & A3_Hysteresis & A3_TTT (configurable reporting parameters)

- These parameters are read in the configuration parsing part and written under RRC structure
- Event Based Measurement Configuration is prepared according to enableA3 parameter.
- Measurement Configuration of UE is cloned under UE Context. When a measurement report comes,
looping through the UE's meas config and matching the measIDs. With this measID, report configs
extracted and processing in different ways.
parent c599e172
This diff is collapsed.
......@@ -1607,8 +1607,46 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
char gnbpath[MAX_OPTNAME_SIZE + 8];
sprintf(gnbpath,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k);
paramdef_t NeighbourCellParams[] = GNBNEIGHBOURCELLPARAMS_DESC;
paramlist_def_t NeighbourCellParamList = {GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST, NULL, 0};
config_getlist(config_get_if(), &NeighbourCellParamList, NeighbourCellParams, sizeofArray(NeighbourCellParams), gnbpath);
LOG_I(NR_MAC, "HO LOG: Neighbour Cell ELM NUM: %d\n", NeighbourCellParamList.numelt);
for (uint8_t l = 0; l < NeighbourCellParamList.numelt; ++l) {
rrc->neighbourConfiguration[l].neighbour_gNB_ID = *(NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_GNB_ID_IDX].uptr);
rrc->neighbourConfiguration[l].neighbour_nrcell_id = (uint64_t) *(NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr);
rrc->neighbourConfiguration[l].physicalCellId = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX].uptr;
rrc->neighbourConfiguration[l].subcarrierSpacing = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_SCS_IDX].uptr;
rrc->neighbourConfiguration[l].absoluteFrequencySSB = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX].i64ptr;
rrc->neighbourConfiguration[l].neighbour_mcc = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_MCC_IDX].uptr;
rrc->neighbourConfiguration[l].neighbour_mnc = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_MNC_IDX].uptr;
rrc->neighbourConfiguration[l].neighbour_mnc_digit_length = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_MNC_DIGIT_LENGTH_IDX].uptr;
rrc->neighbourConfiguration[l].neighbour_tac = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_TAC_IDX].uptr;
}
rrc->number_of_neighbours = NeighbourCellParamList.numelt;
if (rrc->number_of_neighbours > 0) {
paramdef_t MeasurementEventParams[] = MEASUREMENT_EVENTS_GLOBALPARAMS_DESC;
paramlist_def_t MeasurementEventParamList = {GNB_CONFIG_STRING_MEASUREMENT_EVENTS, NULL, 0};
config_getlist(config_get_if(), &MeasurementEventParamList, MeasurementEventParams, sizeofArray(MeasurementEventParams), gnbpath);
rrc->measurementConfiguration.enableA2 = (*MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A2_IDX].i64ptr);
if (rrc->measurementConfiguration.enableA2) {
rrc->measurementConfiguration.a2_threshold = *MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A2_THRESHOLD_IDX].i64ptr;
rrc->measurementConfiguration.a2_time_to_trigger = *MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A2_TIME_TO_TRIGGER_IDX].i64ptr;
}
rrc->measurementConfiguration.enableA3 = (*MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A3_IDX].i64ptr);
if (rrc->measurementConfiguration.enableA3) {
rrc->measurementConfiguration.a3_offset = *MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A3_OFFSET_IDX].i64ptr;
rrc->measurementConfiguration.a3_hysteresis = *MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A3_HYSTERESIS_IDX].i64ptr;
rrc->measurementConfiguration.a3_time_to_trigger = *MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A3_TIME_TO_TRIGGER_IDX].i64ptr;
}
}
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
......
......@@ -229,6 +229,73 @@ typedef enum {
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
/* Neighbour Cell Configurations*/
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST "neighbour_cell_configuration"
#define GNB_CONFIG_STRING_NEIGHBOUR_GNB_ID "neighbour_gNB_ID"
#define GNB_CONFIG_STRING_NEIGHBOUR_NR_CELLID "neighbour_nr_cellid"
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID "neighbour_physical_cellId"
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB "neighbour_absoluteFrequencySSB"
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_SCS "neighbour_subcarrierSpacing"
#define GNB_CONFIG_STRING_NEIGHBOUR_MOBILE_COUNTRY_CODE "neighbour_mcc"
#define GNB_CONFIG_STRING_NEIGHBOUR_MOBILE_NETWORK_CODE "neighbour_mnc"
#define GNB_CONFIG_STRING_NEIGHBOUR_MNC_DIGIT_LENGTH "neighbour_mnc_length"
#define GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE "neighbour_tracking_area_code"
#define GNB_CONFIG_N_CELL_GNB_ID_IDX 0
#define GNB_CONFIG_N_CELL_NR_CELLID_IDX 1
#define GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX 2
#define GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX 3
#define GNB_CONFIG_N_CELL_SCS_IDX 4
#define GNB_CONFIG_N_CELL_MCC_IDX 5
#define GNB_CONFIG_N_CELL_MNC_IDX 6
#define GNB_CONFIG_N_CELL_MNC_DIGIT_LENGTH_IDX 7
#define GNB_CONFIG_N_CELL_TAC_IDX 8
#define GNBNEIGHBOURCELLPARAMS_DESC { \
/* optname helpstr paramflags XXXptr def val type numelt */ \
{GNB_CONFIG_STRING_GNB_ID, NULL, 0, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \
{GNB_CONFIG_STRING_NRCELLID, NULL, 0, .u64ptr=NULL, .defint64val=1, TYPE_UINT64, 0}, \
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID, "neighbour cell physical id", 0, .uptr=NULL, .defuintval=1000, TYPE_UINT, 0}, \
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB, "neighbour cell abs freq ssb", 0, .i64ptr=NULL, .defint64val=621312, TYPE_INT64, 0}, \
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_SCS, "neighbour cell scs", 0, .uptr=NULL, .defuintval=1, TYPE_UINT, 0}, \
{GNB_CONFIG_STRING_NEIGHBOUR_MOBILE_COUNTRY_CODE, "mobile country code", 0, .uptr=NULL, .defuintval=1000, TYPE_UINT, 0}, \
{GNB_CONFIG_STRING_NEIGHBOUR_MOBILE_NETWORK_CODE, "mobile network code", 0, .uptr=NULL, .defuintval=1000, TYPE_UINT, 0}, \
{GNB_CONFIG_STRING_NEIGHBOUR_MNC_DIGIT_LENGTH, "length of the MNC (2 or 3)", 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
{GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE, NULL, 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
}
/* Measurement Event Configurations*/
#define GNB_CONFIG_STRING_MEASUREMENT_EVENTS "nr_measurement_event_configuration"
#define MEASUREMENT_EVENTS_ENABLE_A2 "enableA2"
#define MEASUREMENT_EVENTS_ENABLE_A3 "enableA3"
#define MEASUREMENT_EVENTS_ENABLE_A2_THRESHOLD "thresholdA2"
#define MEASUREMENT_EVENTS_ENABLE_A2_TIME_TO_TRIGGER "A2_timeToTrigger"
#define MEASUREMENT_EVENTS_ENABLE_A3_OFFSET "A3_offset"
#define MEASUREMENT_EVENTS_ENABLE_A3_HYSTERESIS "A3_hysteresis"
#define MEASUREMENT_EVENTS_ENABLE_A3_TIME_TO_TRIGGER "A3_timeToTrigger"
#define MEASUREMENT_EVENTS_GLOBALPARAMS_DESC { \
{MEASUREMENT_EVENTS_ENABLE_A2, "enabling a2 event", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
{MEASUREMENT_EVENTS_ENABLE_A3, "enabling a3 event", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
{MEASUREMENT_EVENTS_ENABLE_A2_THRESHOLD, "a2 threshold", 0, .i64ptr=NULL, .defint64val=30, TYPE_INT64, 0}, \
{MEASUREMENT_EVENTS_ENABLE_A2_TIME_TO_TRIGGER, "a2 time to trigger", 0, .i64ptr=NULL, .defint64val=1, TYPE_INT64, 0}, \
{MEASUREMENT_EVENTS_ENABLE_A3_OFFSET, "a3 offset", 0, .i64ptr=NULL, .defint64val=10, TYPE_INT64, 0}, \
{MEASUREMENT_EVENTS_ENABLE_A3_HYSTERESIS, "a3 hysteresis", 0, .i64ptr=NULL, .defint64val=0, TYPE_INT64, 0}, \
{MEASUREMENT_EVENTS_ENABLE_A3_TIME_TO_TRIGGER, "a3 time to trigger", 0, .i64ptr=NULL, .defint64val=1, TYPE_INT64, 0}, \
}
#define MEASUREMENT_EVENTS_ENABLE_A2_IDX 0
#define MEASUREMENT_EVENTS_ENABLE_A3_IDX 1
#define MEASUREMENT_EVENTS_ENABLE_A2_THRESHOLD_IDX 2
#define MEASUREMENT_EVENTS_ENABLE_A2_TIME_TO_TRIGGER_IDX 3
#define MEASUREMENT_EVENTS_ENABLE_A3_OFFSET_IDX 4
#define MEASUREMENT_EVENTS_ENABLE_A3_HYSTERESIS_IDX 5
#define MEASUREMENT_EVENTS_ENABLE_A3_TIME_TO_TRIGGER_IDX 6
/* PLMN ID configuration */
#define GNB_CONFIG_STRING_PLMN_LIST "plmn_list"
......
......@@ -1183,6 +1183,149 @@ NR_MeasConfig_t *get_defaultMeasConfig(uint32_t ssb_arfcn, int band, int scs)
return mc;
}
NR_MeasConfig_t *get_EventBasedMeasConfig(uint32_t ssb_arfcn, int band, int scs, const nr_measurement_event_configuration_t* measurementConfiguration, nr_neighbour_gnb_configuration_t* neighbourConfiguration, const int numberOfNeighbours){
bool intraFrequencyNeighbourExists = false;
LOG_D(NR_RRC, "HO LOG: Supports only Intra Frequency Meas with SCS:%d ABS ARFCN: %d\n", scs, ssb_arfcn);
for (uint8_t nCell = 0; nCell < numberOfNeighbours; nCell++){
nr_neighbour_gnb_configuration_t* neighbourCell = &neighbourConfiguration[nCell];
if (ssb_arfcn == neighbourCell->absoluteFrequencySSB && scs == neighbourCell->subcarrierSpacing) {
LOG_D(NR_RRC, "HO LOG: Intra Frequency Neighbour is Found!\n");
intraFrequencyNeighbourExists = true;
neighbourCell->intraFrequencyNeighbour = true;
}
}
if (!intraFrequencyNeighbourExists){
LOG_E(NR_RRC, "HO LOG: Currently Inter Frequency Measurements are not supported!\n");
return NULL;
}
NR_MeasConfig_t *mc = calloc(1, sizeof(*mc));
mc->measObjectToAddModList = calloc(1, sizeof(*mc->measObjectToAddModList));
mc->reportConfigToAddModList = calloc(1, sizeof(*mc->reportConfigToAddModList));
//A3 Configuration
NR_MeasObjectToAddMod_t *mo1 = calloc(1, sizeof(*mo1));
mo1->measObjectId = 1;
mo1->measObject.present = NR_MeasObjectToAddMod__measObject_PR_measObjectNR;
NR_MeasObjectNR_t *monr1 = calloc(1, sizeof(*monr1));
asn1cCallocOne(monr1->ssbFrequency, ssb_arfcn);
asn1cCallocOne(monr1->ssbSubcarrierSpacing, scs);
monr1->referenceSignalConfig.ssb_ConfigMobility = calloc(1, sizeof(*monr1->referenceSignalConfig.ssb_ConfigMobility));
monr1->referenceSignalConfig.ssb_ConfigMobility->deriveSSB_IndexFromCell = true;
monr1->absThreshSS_BlocksConsolidation = calloc(1, sizeof(*monr1->absThreshSS_BlocksConsolidation));
asn1cCallocOne(monr1->absThreshSS_BlocksConsolidation->thresholdRSRP, 36);
asn1cCallocOne(monr1->nrofSS_BlocksToAverage, 8);
monr1->smtc1 = calloc(1, sizeof(*monr1->smtc1));
monr1->smtc1->periodicityAndOffset.present = NR_SSB_MTC__periodicityAndOffset_PR_sf20;
monr1->smtc1->periodicityAndOffset.choice.sf20 = 2;
monr1->smtc1->duration = NR_SSB_MTC__duration_sf2;
monr1->quantityConfigIndex = 1;
monr1->ext1 = calloc(1, sizeof(*monr1->ext1));
asn1cCallocOne(monr1->ext1->freqBandIndicatorNR, band);
for (uint8_t nCell = 0; nCell < numberOfNeighbours; nCell++){
const nr_neighbour_gnb_configuration_t* neighbourCell = &neighbourConfiguration[nCell];
if (!neighbourCell->intraFrequencyNeighbour)
continue;
LOG_D(NR_RRC, "HO LOG: Preparing Meas Config for neighbour Cell with the ID: %d\n", neighbourCell->physicalCellId);
if (monr1->cellsToAddModList == NULL) {
monr1->cellsToAddModList = calloc(1, sizeof(*monr1->cellsToAddModList));
}
NR_CellsToAddMod_t *cell = calloc(1, sizeof(*cell));
cell->physCellId = neighbourCell->physicalCellId;
ASN_SEQUENCE_ADD(&monr1->cellsToAddModList->list, cell);
}
const int numIntraFreqNeighbours = monr1->cellsToAddModList->list.count;
mo1->measObject.choice.measObjectNR = monr1;
asn1cSeqAdd(&mc->measObjectToAddModList->list, mo1);
NR_ReportConfigToAddMod_t *rc_A3 = calloc(1, sizeof(*rc_A3));
rc_A3->reportConfigId = 1;
rc_A3->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR;
NR_EventTriggerConfig_t *etrc_A3 = calloc(1, sizeof(*etrc_A3));
etrc_A3->eventId.present = NR_EventTriggerConfig__eventId_PR_eventA3;
etrc_A3->eventId.choice.eventA3 = calloc(1, sizeof(*etrc_A3->eventId.choice.eventA3));
etrc_A3->eventId.choice.eventA3->a3_Offset.present = NR_MeasTriggerQuantityOffset_PR_rsrp;
etrc_A3->eventId.choice.eventA3->a3_Offset.choice.rsrp = measurementConfiguration->a3_offset;
etrc_A3->eventId.choice.eventA3->reportOnLeave = true;
etrc_A3->eventId.choice.eventA3->hysteresis = measurementConfiguration->a3_hysteresis;
etrc_A3->eventId.choice.eventA3->timeToTrigger = measurementConfiguration->a3_time_to_trigger;
etrc_A3->rsType = NR_NR_RS_Type_ssb;
etrc_A3->reportInterval = NR_ReportInterval_ms1024;
etrc_A3->reportAmount = NR_EventTriggerConfig__reportAmount_r4;
etrc_A3->reportQuantityCell.rsrp = true;
etrc_A3->reportQuantityCell.rsrq = false;
etrc_A3->reportQuantityCell.sinr = true;
asn1cCallocOne(etrc_A3->maxNrofRS_IndexesToReport, 4);
etrc_A3->maxReportCells = numIntraFreqNeighbours;
etrc_A3->includeBeamMeasurements = false;
NR_ReportConfigNR_t *rcnr_A3 = calloc(1, sizeof(*rcnr_A3));
rcnr_A3->reportType.present = NR_ReportConfigNR__reportType_PR_eventTriggered;
rcnr_A3->reportType.choice.eventTriggered = etrc_A3;
rc_A3->reportConfig.choice.reportConfigNR = rcnr_A3;
asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_A3);
mc->measIdToAddModList = calloc(1, sizeof(*mc->measIdToAddModList));
NR_MeasIdToAddMod_t *measid_A3 = calloc(1, sizeof(*measid_A3));
measid_A3->measId = 1;
measid_A3->measObjectId = 1;
measid_A3->reportConfigId = 1;
asn1cSeqAdd(&mc->measIdToAddModList->list, measid_A3);
// A2 Report Configuration
if (measurementConfiguration->enableA2) {
LOG_D(NR_RRC, "HO LOG: Preparing A2 Event Measurement Configuration!\n");
NR_ReportConfigToAddMod_t *rc_A2 = calloc(1, sizeof(*rc_A2));
rc_A2->reportConfigId = 2;
rc_A2->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR;
NR_EventTriggerConfig_t *etrc_A2 = calloc(1, sizeof(*etrc_A2));
etrc_A2->eventId.present = NR_EventTriggerConfig__eventId_PR_eventA2;
etrc_A2->eventId.choice.eventA2 = calloc(1, sizeof(*etrc_A2->eventId.choice.eventA2));
etrc_A2->eventId.choice.eventA2->a2_Threshold.present = NR_MeasTriggerQuantity_PR_rsrp;
etrc_A2->eventId.choice.eventA2->a2_Threshold.choice.rsrp = measurementConfiguration->a2_threshold;
etrc_A2->eventId.choice.eventA2->reportOnLeave = false;
etrc_A2->eventId.choice.eventA2->hysteresis = 0;
etrc_A2->eventId.choice.eventA2->timeToTrigger = measurementConfiguration->a2_time_to_trigger;
etrc_A2->rsType = NR_NR_RS_Type_ssb;
etrc_A2->reportInterval = NR_ReportInterval_ms480;
etrc_A2->reportAmount = NR_EventTriggerConfig__reportAmount_r4;
etrc_A2->reportQuantityCell.rsrp = true;
etrc_A2->reportQuantityCell.rsrq = false;
etrc_A2->reportQuantityCell.sinr = false;
asn1cCallocOne(etrc_A2->maxNrofRS_IndexesToReport, 4);
etrc_A2->maxReportCells = 1;
etrc_A2->includeBeamMeasurements = false;
NR_ReportConfigNR_t *rcnr_A2 = calloc(1, sizeof(*rcnr_A2));
rcnr_A2->reportType.present = NR_ReportConfigNR__reportType_PR_eventTriggered;
rcnr_A2->reportType.choice.eventTriggered = etrc_A2;
rc_A2->reportConfig.choice.reportConfigNR = rcnr_A2;
asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_A2);
NR_MeasIdToAddMod_t *measid_A2 = calloc(1, sizeof(*measid_A2));
measid_A2->measId = 2;
measid_A2->measObjectId = 1;
measid_A2->reportConfigId = 2;
asn1cSeqAdd(&mc->measIdToAddModList->list, measid_A2);
}
mc->quantityConfig = calloc(1, sizeof(*mc->quantityConfig));
mc->quantityConfig->quantityConfigNR_List = calloc(1, sizeof(*mc->quantityConfig->quantityConfigNR_List));
NR_QuantityConfigNR_t *qcnr3 = calloc(1, sizeof(*qcnr3));
asn1cCallocOne(qcnr3->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6);
asn1cCallocOne(qcnr3->quantityConfigCell.csi_RS_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6);
asn1cSeqAdd(&mc->quantityConfig->quantityConfigNR_List->list, qcnr3);
return mc;
}
void free_defaultMeasConfig(NR_MeasConfig_t *mc)
{
ASN_STRUCT_FREE(asn_DEF_NR_MeasConfig, mc);
......
......@@ -143,6 +143,7 @@ int do_RRCReestablishment(rrc_gNB_ue_context_t *const ue_context_pP,
int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier);
NR_MeasConfig_t *get_defaultMeasConfig(uint32_t absFreqSSB, int band, int scs);
NR_MeasConfig_t *get_EventBasedMeasConfig(uint32_t ssb_arfcn, int band, int scs, const nr_measurement_event_configuration_t* measurementConfiguration, nr_neighbour_gnb_configuration_t* neighbourConfiguration, const int numberOfNeighbours);
void free_defaultMeasConfig(NR_MeasConfig_t *mc);
uint8_t do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi);
......
......@@ -96,6 +96,8 @@
#define NR_UE_MODULE_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!!
#define NR_UE_INDEX_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!! used to be -1
#define MAX_NUMBER_OF_NEIGHBOUR_GNBS 6
typedef enum {
NR_RRC_OK=0,
NR_RRC_ConnSetup_failed,
......@@ -343,6 +345,30 @@ typedef struct {
int do_drb_integrity;
} nr_security_configuration_t;
typedef struct {
uint32_t neighbour_gNB_ID;
uint64_t neighbour_nrcell_id;
int physicalCellId;
int absoluteFrequencySSB;
int subcarrierSpacing;
uint16_t neighbour_mcc;
uint16_t neighbour_mnc;
uint8_t neighbour_mnc_digit_length;
uint32_t neighbour_tac;
bool intraFrequencyNeighbour;
} nr_neighbour_gnb_configuration_t;
typedef struct {
int enableA2;
int enableA3;
int a2_threshold;
int a2_time_to_trigger;
int a3_offset;
int a3_hysteresis;
int a3_time_to_trigger;
} nr_measurement_event_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;
......@@ -405,6 +431,9 @@ typedef struct gNB_RRC_INST_s {
nr_mac_rrc_dl_if_t mac_rrc;
cucp_cuup_if_t cucp_cuup;
nr_neighbour_gnb_configuration_t neighbourConfiguration[MAX_NUMBER_OF_NEIGHBOUR_GNBS];
nr_measurement_event_configuration_t measurementConfiguration;
uint8_t number_of_neighbours;
RB_HEAD(rrc_du_tree, nr_rrc_du_container_t) dus; // DUs, indexed by assoc_id
size_t num_dus;
......
......@@ -510,6 +510,16 @@ static void rrc_gNB_process_RRCSetupComplete(const protocol_ctxt_t *const ctxt_p
#endif
}
static void clone_MeasConfig(const NR_MeasConfig_t *orig, rrc_gNB_ue_context_t *ue_context_pP)
{
uint8_t buf[16636];
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MeasConfig, NULL, orig, buf, sizeof(buf));
AssertFatal(enc_rval.encoded > 0, "could not clone Meas Config: problem while encoding\n");
asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_MeasConfig, (void **)&ue_context_pP->ue_context.measConfig, buf, enc_rval.encoded, 0, 0);
AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded,
"could not clone NR_MeasConfig_t: problem while decodung\n");
}
//-----------------------------------------------------------------------------
static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP)
//-----------------------------------------------------------------------------
......@@ -555,11 +565,26 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co
/* we cannot calculate the default measurement config without MIB&SIB1, as
* we don't know the DU's SSB ARFCN */
uint32_t ssb_arfcn = get_ssb_arfcn(cell_info, du->mib, du->sib1);
measconfig = get_defaultMeasConfig(ssb_arfcn, band, scs);
if (rrc->measurementConfiguration.enableA3 && rrc->number_of_neighbours > 0) {
LOG_D(NR_RRC, "HO LOG: Event Based Measurement is Selected!\n");
measconfig = get_EventBasedMeasConfig(ssb_arfcn, band, scs, &(rrc->measurementConfiguration), rrc->neighbourConfiguration, rrc->number_of_neighbours);
} else{
measconfig = get_defaultMeasConfig(ssb_arfcn, band, scs);
}
}
if (ue_p->measConfig != NULL) {
free(ue_p->measConfig);
ue_p->measConfig = NULL;
}
if (measconfig != NULL)
clone_MeasConfig(measconfig, ue_context_pP);
NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false);
NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false);
uint8_t buffer[RRC_BUF_SIZE] = {0};
int size = do_RRCReconfiguration(ue_p,
buffer,
......@@ -1204,22 +1229,120 @@ fallback_rrc_setup:
static void rrc_gNB_process_MeasurementReport(rrc_gNB_ue_context_t *ue_context, NR_MeasurementReport_t *measurementReport)
{
LOG_D(NR_RRC, "Process Measurement Report\n");
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_MeasurementReport, (void *)measurementReport);
DevAssert(measurementReport->criticalExtensions.present == NR_MeasurementReport__criticalExtensions_PR_measurementReport
&& measurementReport->criticalExtensions.choice.measurementReport != NULL);
gNB_RRC_UE_t *ue_ctxt = &ue_context->ue_context;
ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, ue_ctxt->measResults);
ue_ctxt->measResults = NULL;
gNB_RRC_UE_t *ue_ctxt = &ue_context->ue_context;
NR_MeasConfig_t *meas_config = ue_ctxt->measConfig;
if (meas_config == NULL) {
LOG_E(NR_RRC, "%s: %i - meas_config = %p\n", __FUNCTION__, __LINE__, meas_config);
return;
}
// xer_fprint(stdout, &asn_DEF_NR_MeasurementReport, (void *)measurementReport);
// xer_fprint(stdout, &asn_DEF_NR_MeasConfig, (void*)ue_ctxt->measConfig);
NR_MeasurementReport_IEs_t *measurementReport_IEs = measurementReport->criticalExtensions.choice.measurementReport;
const NR_MeasId_t measId = measurementReport_IEs->measResults.measId;
NR_MeasIdToAddMod_t *meas_id_s = NULL;
for (int meas_idx = 0; meas_idx < meas_config->measIdToAddModList->list.count; meas_idx++) {
if (measId == meas_config->measIdToAddModList->list.array[meas_idx]->measId) {
meas_id_s = meas_config->measIdToAddModList->list.array[meas_idx];
break;
}
}
if (meas_id_s == NULL){
LOG_E(NR_RRC, "Incoming Meas ID with id: %d Can not Found!\n", (int)measId);
return;
}
LOG_D(NR_RRC, "HO LOG: Meas Id is found: %d\n", (int)meas_id_s->measId);
struct NR_ReportConfigToAddMod__reportConfig *report_config = NULL;
for (int rep_id = 0; rep_id < meas_config->reportConfigToAddModList->list.count; rep_id++) {
if (meas_id_s->reportConfigId == meas_config->reportConfigToAddModList->list.array[rep_id]->reportConfigId) {
report_config = &meas_config->reportConfigToAddModList->list.array[rep_id]->reportConfig;
}
}
if (report_config == NULL) {
LOG_E(NR_RRC, "There is no related report configuration for this measId!\n");
return;
}
if (report_config->choice.reportConfigNR->reportType.present == NR_ReportConfigNR__reportType_PR_periodical){
LOG_I(NR_RRC, "Periodical Event Report! Do Nothing for now...\n");
ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, ue_ctxt->measResults);
ue_ctxt->measResults = NULL;
const NR_MeasId_t id = measurementReport->criticalExtensions.choice.measurementReport->measResults.measId;
AssertFatal(id, "unexpected MeasResult for MeasurementId %ld received\n", id);
asn1cCallocOne(ue_ctxt->measResults, measurementReport->criticalExtensions.choice.measurementReport->measResults);
/* we "keep" the measurement report, so set to 0 */
free(measurementReport->criticalExtensions.choice.measurementReport);
measurementReport->criticalExtensions.choice.measurementReport = NULL;
return;
}
if (report_config->choice.reportConfigNR->reportType.present != NR_ReportConfigNR__reportType_PR_eventTriggered){
LOG_D(NR_RRC, "Incoming Report Type: %d is not supported! \n", report_config->choice.reportConfigNR->reportType.present);
return;
}
NR_EventTriggerConfig_t *event_triggered = report_config->choice.reportConfigNR->reportType.choice.eventTriggered;
LOG_I(NR_RRC, "HO LOG: Incoming Report Id: %d\n", (int)measId);
int servingCellRSRP = 0;
int neighbourCellRSRP = 0;
switch (event_triggered->eventId.present) {
case NR_EventTriggerConfig__eventId_PR_eventA2:
LOG_I(NR_RRC, "\nHO LOG: Event A2 (Serving becomes worse than threshold)\n");
break;
case NR_EventTriggerConfig__eventId_PR_eventA3:
{
LOG_I(NR_RRC, "\nHO LOG: Event A3 Report - Neighbour Becomes Better than Serving!\n");
for (int serving_cell_idx = 0; serving_cell_idx < measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultServingMOList.list.count; serving_cell_idx++) {
const NR_MeasResultServMO_t* meas_result_serv_MO = measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultServingMOList.list.array[serving_cell_idx];
if (meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsSSB_Cell) {
servingCellRSRP = *(meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsSSB_Cell->rsrp) - 157;
} else {
servingCellRSRP = *(meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsCSI_RS_Cell->rsrp) - 157;
}
LOG_D(NR_RRC, "Serving Cell RSRP: %d\n", servingCellRSRP);
}
//Only Meas Result NR is supported at the moment
if (measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultNeighCells == NULL)
break;
if (measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultNeighCells->present != NR_MeasResults__measResultNeighCells_PR_measResultListNR)
break;
const NR_MeasId_t id = measurementReport->criticalExtensions.choice.measurementReport->measResults.measId;
AssertFatal(id, "unexpected MeasResult for MeasurementId %ld received\n", id);
asn1cCallocOne(ue_ctxt->measResults, measurementReport->criticalExtensions.choice.measurementReport->measResults);
/* we "keep" the measurement report, so set to 0 */
free(measurementReport->criticalExtensions.choice.measurementReport);
measurementReport->criticalExtensions.choice.measurementReport = NULL;
for (int neigh_meas_idx = 0; neigh_meas_idx < measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultNeighCells->choice.measResultListNR->list.count; neigh_meas_idx++){
const NR_MeasResultNR_t* meas_result_neigh_cell = (measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultNeighCells->choice.measResultListNR->list.array[neigh_meas_idx]);
const int neighbourCellId = *(meas_result_neigh_cell->physCellId);
if (meas_result_neigh_cell->measResult.cellResults.resultsSSB_Cell) {
neighbourCellRSRP = *(meas_result_neigh_cell->measResult.cellResults.resultsSSB_Cell->rsrp) - 157;
} else {
neighbourCellRSRP = *(meas_result_neigh_cell->measResult.cellResults.resultsCSI_RS_Cell->rsrp) - 157;
}
LOG_I(NR_RRC, "HO LOG: Measurement Report has came for the neighbour: %d with RSRP: %d\n", neighbourCellId, neighbourCellRSRP);
}
}
break;
default:
LOG_D(NR_RRC, "NR_EventTriggerConfig__eventId_PR_NOTHING or Other event report\n");
break;
}
}
static int handle_rrcReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP,
......
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