diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index b3397ad518..c016e4c899 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -1152,3 +1152,17 @@ int do_NR_HandoverPreparationInformation(const uint8_t *uecap_buf, int uecap_buf ASN_STRUCT_FREE(asn_DEF_NR_HandoverPreparationInformation, hpi); return (enc_rval.encoded + 7) / 8; } + +int do_NR_MeasConfig(const NR_MeasConfig_t *measconfig, uint8_t *buf, int buf_size) +{ + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MeasConfig, NULL, measconfig, buf, buf_size); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + return (enc_rval.encoded + 7) / 8; +} + +int do_NR_MeasurementTimingConfiguration(const NR_MeasurementTimingConfiguration_t *mtc, uint8_t *buf, int buf_size) +{ + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MeasurementTimingConfiguration, NULL, mtc, buf, buf_size); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + return (enc_rval.encoded + 7) / 8; +} diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 8918384090..432db0e5cd 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -50,6 +50,7 @@ #include "NR_ReestablishmentCause.h" #include "NR_SRB-ToAddModList.h" #include "NR_SecurityConfig.h" +#include "NR_MeasurementTimingConfiguration.h" #include "ds/seq_arr.h" #include "ds/byte_array.h" #include "rrc_messages_types.h" @@ -120,6 +121,10 @@ int do_RRCSetupComplete(uint8_t *buffer, int do_NR_HandoverPreparationInformation(const uint8_t *uecap_buf, int uecap_buf_size, uint8_t *buf, int buf_size); +int do_NR_MeasConfig(const NR_MeasConfig_t *measconfig, uint8_t *buf, int buf_size); + +int do_NR_MeasurementTimingConfiguration(const NR_MeasurementTimingConfiguration_t *mtc, uint8_t *buf, int buf_size); + int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_t fiveG_S_TMSI_part1); int do_NR_RRCReconfigurationComplete_for_nsa(uint8_t *buffer, size_t buffer_size, NR_RRC_TransactionIdentifier_t Transaction_id); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index eeb18e8698..991b19af50 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -557,14 +557,11 @@ void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params) FREE_AND_ZERO_BYTE_ARRAY(params.dedicated_NAS_msg_list[i]); } -/** @brief Prepare the instance of RRCReconfigurationParams to be pass to RRC encoding */ -nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish) +static NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *UE) { - uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); - nr_rrc_du_container_t *du = get_du_for_ue(rrc, UE->rrc_ue_id); + nr_rrc_du_container_t *du = get_du_for_ue((gNB_RRC_INST *)rrc, UE->rrc_ue_id); DevAssert(du != NULL); f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; - NR_MeasConfig_t *measconfig = NULL; NR_ReportConfigToAddMod_t *rc_PER = NULL; NR_ReportConfigToAddMod_t *rc_A2 = NULL; seq_arr_t *rc_A3_seq = NULL; @@ -578,9 +575,7 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC if (neighbour_config) neighbour_cells = neighbour_config->neighbour_cells; - if (neighbour_cells - && rrc->measurementConfiguration.a3_event_list - && rrc->measurementConfiguration.a3_event_list->size > 0) { + if (neighbour_cells && rrc->measurementConfiguration.a3_event_list && rrc->measurementConfiguration.a3_event_list->size > 0) { /* Loop through neighbours and find related A3 configuration If no related A3 but there is default add the default one. If default one added once as a report, no need to add it again && duplication. @@ -591,7 +586,7 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC bool is_default_a3_added = false; for (int i = 0; i < neighbour_cells->size; i++) { nr_neighbour_cell_t *neighbourCell = (nr_neighbour_cell_t *)seq_arr_at(neighbour_cells, i); - const nr_a3_event_t *a3Event = get_a3_configuration(rrc, neighbourCell->physicalCellId); + const nr_a3_event_t *a3Event = get_a3_configuration((gNB_RRC_INST *)rrc, neighbourCell->physicalCellId); if (!a3Event || is_default_a3_added) continue; if (a3Event->pci == -1) @@ -603,14 +598,15 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC rc_PER = prepare_periodic_event_report(rrc->measurementConfiguration.per_event); if (rrc->measurementConfiguration.a2_event) rc_A2 = prepare_a2_event_report(rrc->measurementConfiguration.a2_event); - - measconfig = get_MeasConfig(mt, band, scs, rc_PER, rc_A2, rc_A3_seq, neighbour_cells); + return get_MeasConfig(mt, band, scs, rc_PER, rc_A2, rc_A3_seq, neighbour_cells); } + return NULL; +} - if (UE->measConfig) - free_MeasConfig(UE->measConfig); - - UE->measConfig = measconfig; +/** @brief Prepare the instance of RRCReconfigurationParams to be pass to RRC encoding */ +nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish) +{ + uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); // Re-establish PDCP for SRB2 only NR_SRB_ToAddModList_t *SRBs = createSRBlist(UE, srb_reest_bitmap); @@ -1155,6 +1151,7 @@ static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc, UE->nr_cellid = msg->nr_cellid; UE->masterCellGroup = cellGroupConfig; UE->ongoing_reconfiguration = false; + UE->measConfig = nr_rrc_get_measconfig(rrc, UE); activate_srb(UE, 1); rrc_gNB_generate_RRCSetup(0, msg->crnti, ue_context_p, msg->du2cu_rrc_container, msg->du2cu_rrc_container_length); } @@ -2091,6 +2088,17 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance uper_decode_complete(NULL, &asn_DEF_NR_CellGroupConfig, (void **)&cellGroupConfig, (uint8_t *)cgc->buf, cgc->len); AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n"); + if (resp->du_to_cu_rrc_info.meas_gap_config) { + NR_MeasGapConfig_t *measGapConfig = NULL; + asn_dec_rval_t dec_rval_mgc = uper_decode_complete(NULL, + &asn_DEF_NR_MeasGapConfig, + (void **)&measGapConfig, + (uint8_t *)resp->du_to_cu_rrc_info.meas_gap_config->buf, + resp->du_to_cu_rrc_info.meas_gap_config->len); + AssertFatal(dec_rval_mgc.code == RC_OK && dec_rval_mgc.consumed > 0, "measGapConfig decode error\n"); + UE->measConfig->measGapConfig = measGapConfig; + } + if (UE->masterCellGroup) { ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); LOG_I(RRC, "UE %04x replacing existing CellGroupConfig with new one received from DU\n", UE->rnti); @@ -3039,6 +3047,28 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, *cu2du.ue_cap = copy_byte_array(ue_p->ue_cap_buffer); } + nr_rrc_du_container_t *du = get_du_for_ue((gNB_RRC_INST *)rrc, ue_p->rrc_ue_id); + byte_array_t *meas_timing_config = NULL; + if (du->mtc && ue_p->measConfig && ue_p->measConfig->measObjectToAddModList) { + NR_MeasObjectToAddModList_t *mo_list = ue_p->measConfig->measObjectToAddModList; + NR_ARFCN_ValueNR_t ssbFrequency0; + for (int i = 0; i < mo_list->list.count; i++) { + NR_MeasObjectToAddMod_t *mo = mo_list->list.array[i]; + if (mo->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) { + NR_MeasObjectNR_t *monr = mo->measObject.choice.measObjectNR; + if (i == 0) { + ssbFrequency0 = *monr->ssbFrequency; + } else if (ssbFrequency0 != *monr->ssbFrequency) { + meas_timing_config = calloc_or_fail(1, sizeof(*meas_timing_config)); + meas_timing_config->buf = calloc_or_fail(1, NR_RRC_BUF_SIZE); + meas_timing_config->len = do_NR_MeasurementTimingConfiguration(du->mtc, meas_timing_config->buf, NR_RRC_BUF_SIZE); + cu2du.meas_timing_config = meas_timing_config; + break; + } + } + } + } + int nb_srb = 1; f1ap_srb_to_setup_t *srbs = calloc_or_fail(nb_srb, sizeof(*srbs)); srbs[0].id = 2;