/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /* \file rrc_UE.c * \brief RRC procedures * \author R. Knopp, K.H. HSU * \date 2018 * \version 0.1 * \company Eurecom / NTUST * \email: knopp@eurecom.fr, kai-hsiang.hsu@eurecom.fr * \note * \warning */ #define RRC_UE #define RRC_UE_C #include "asn1_conversions.h" #include "NR_DL-DCCH-Message.h" //asn_DEF_NR_DL_DCCH_Message #include "NR_DL-CCCH-Message.h" //asn_DEF_NR_DL_CCCH_Message #include "NR_BCCH-BCH-Message.h" //asn_DEF_NR_BCCH_BCH_Message #include "NR_BCCH-DL-SCH-Message.h" //asn_DEF_NR_BCCH_DL_SCH_Message #include "NR_CellGroupConfig.h" //asn_DEF_NR_CellGroupConfig #include "NR_BWP-Downlink.h" //asn_DEF_NR_BWP_Downlink #include "NR_RRCReconfiguration.h" #include "NR_MeasConfig.h" #include "NR_UL-DCCH-Message.h" #include "rrc_list.h" #include "rrc_defs.h" #include "rrc_proto.h" #include "rrc_vars.h" #include "LAYER2/NR_MAC_UE/mac_proto.h" #include "intertask_interface.h" #include "executables/softmodem-common.h" #include "plmn_data.h" #include "pdcp.h" #include "UTIL/OSA/osa_defs.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #ifndef CELLULAR #include "RRC/NR/MESSAGES/asn1_msg.h" #endif #include "RRC/NAS/nas_config.h" #include "RRC/NAS/rb_config.h" #include "SIMULATION/TOOLS/sim.h" // for taus #if ITTI_SIM #include "nr_nas_msg_sim.h" #endif /* NAS Attach request with IMSI */ static const char nr_nas_attach_req_imsi[] = { 0x07, 0x41, /* EPS Mobile identity = IMSI */ 0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87, 0xF9, /* End of EPS Mobile Identity */ 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03, 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2, 0x01, 0x27, 0x11, }; extern void pdcp_config_set_security( const protocol_ctxt_t *const ctxt_pP, pdcp_t *const pdcp_pP, const rb_id_t rb_idP, const uint16_t lc_idP, const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kRRCint, uint8_t *const kUPenc ); void nr_rrc_ue_process_ueCapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, NR_UECapabilityEnquiry_t *UECapabilityEnquiry, uint8_t gNB_index ); void nr_sa_rrc_ue_process_radioBearerConfig( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index, NR_RadioBearerConfig_t *const radioBearerConfig ); uint8_t do_NR_RRCReconfigurationComplete( const protocol_ctxt_t *const ctxt_pP, uint8_t *buffer, const uint8_t Transaction_id ); mui_t nr_rrc_mui=0; static Rrc_State_NR_t nr_rrc_get_state (module_id_t ue_mod_idP) { return NR_UE_rrc_inst[ue_mod_idP].nrRrcState; } static Rrc_Sub_State_NR_t nr_rrc_get_sub_state (module_id_t ue_mod_idP) { return NR_UE_rrc_inst[ue_mod_idP].nrRrcSubState; } static int nr_rrc_set_state (module_id_t ue_mod_idP, Rrc_State_NR_t state) { AssertFatal ((RRC_STATE_FIRST_NR <= state) && (state <= RRC_STATE_LAST_NR), "Invalid state %d!\n", state); if (NR_UE_rrc_inst[ue_mod_idP].nrRrcState != state) { NR_UE_rrc_inst[ue_mod_idP].nrRrcState = state; return (1); } return (0); } static int nr_rrc_set_sub_state( module_id_t ue_mod_idP, Rrc_Sub_State_NR_t subState ) { if (AMF_MODE_ENABLED) { switch (NR_UE_rrc_inst[ue_mod_idP].nrRrcState) { case RRC_STATE_INACTIVE_NR: AssertFatal ((RRC_SUB_STATE_INACTIVE_FIRST_NR <= subState) && (subState <= RRC_SUB_STATE_INACTIVE_LAST_NR), "Invalid nr sub state %d for state %d!\n", subState, NR_UE_rrc_inst[ue_mod_idP].nrRrcState); break; case RRC_STATE_IDLE_NR: AssertFatal ((RRC_SUB_STATE_IDLE_FIRST_NR <= subState) && (subState <= RRC_SUB_STATE_IDLE_LAST_NR), "Invalid nr sub state %d for state %d!\n", subState, NR_UE_rrc_inst[ue_mod_idP].nrRrcState); break; case RRC_STATE_CONNECTED_NR: AssertFatal ((RRC_SUB_STATE_CONNECTED_FIRST_NR <= subState) && (subState <= RRC_SUB_STATE_CONNECTED_LAST_NR), "Invalid nr sub state %d for state %d!\n", subState, NR_UE_rrc_inst[ue_mod_idP].nrRrcState); break; } } if (NR_UE_rrc_inst[ue_mod_idP].nrRrcSubState != subState) { NR_UE_rrc_inst[ue_mod_idP].nrRrcSubState = subState; return (1); } return (0); } extern boolean_t nr_rrc_pdcp_config_asn1_req( const protocol_ctxt_t *const ctxt_pP, NR_SRB_ToAddModList_t *const srb2add_list, NR_DRB_ToAddModList_t *const drb2add_list, NR_DRB_ToReleaseList_t *const drb2release_list, const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kRRCint, uint8_t *const kUPenc #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 #endif ,rb_id_t *const defaultDRB, struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, const NR_SRB_ToAddModList_t * const srb2add_listP, const NR_DRB_ToAddModList_t * const drb2add_listP, const NR_DRB_ToReleaseList_t * const drb2release_listP, const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); // from LTE-RRC DL-DCCH RRCConnectionReconfiguration nr-secondary-cell-group-config (encoded) int8_t nr_rrc_ue_decode_secondary_cellgroup_config( const module_id_t module_id, const uint8_t *buffer, const uint32_t size ){ NR_CellGroupConfig_t *cell_group_config = NULL; uint32_t i; asn_dec_rval_t dec_rval = uper_decode_complete( NULL, &asn_DEF_NR_CellGroupConfig, (void **)&cell_group_config, (uint8_t *)buffer, size ); if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { printf("NR_CellGroupConfig decode error\n"); for (i=0; i<size; i++){ printf("%02x ",buffer[i]); } printf("\n"); // free the memory SEQUENCE_free( &asn_DEF_NR_CellGroupConfig, (void *)cell_group_config, 1 ); return -1; } if(NR_UE_rrc_inst[module_id].cell_group_config == NULL){ NR_UE_rrc_inst[module_id].cell_group_config = cell_group_config; nr_rrc_ue_process_scg_config(module_id,cell_group_config); }else{ nr_rrc_ue_process_scg_config(module_id,cell_group_config); SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)cell_group_config, 0); } //nr_rrc_mac_config_req_ue( 0,0,0,NULL, cell_group_config->mac_CellGroupConfig, cell_group_config->physicalCellGroupConfig, cell_group_config->spCellConfig ); return 0; } int8_t nr_rrc_ue_process_RadioBearerConfig(NR_RadioBearerConfig_t *RadioBearerConfig){ xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)RadioBearerConfig); // Configure PDCP return 0; } // from LTE-RRC DL-DCCH RRCConnectionReconfiguration nr-secondary-cell-group-config (decoded) // RRCReconfiguration int8_t nr_rrc_ue_process_rrcReconfiguration(const module_id_t module_id, NR_RRCReconfiguration_t *rrcReconfiguration){ switch(rrcReconfiguration->criticalExtensions.present){ case NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration: if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig != NULL){ if(NR_UE_rrc_inst[module_id].radio_bearer_config == NULL){ NR_UE_rrc_inst[module_id].radio_bearer_config = rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig; }else{ nr_rrc_ue_process_RadioBearerConfig(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig); } } if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup != NULL){ NR_CellGroupConfig_t *cellGroupConfig = NULL; uper_decode(NULL, &asn_DEF_NR_CellGroupConfig, //might be added prefix later (void **)&cellGroupConfig, (uint8_t *)rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->buf, rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->size, 0, 0); xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)cellGroupConfig); if(NR_UE_rrc_inst[module_id].cell_group_config == NULL){ // first time receive the configuration, just use the memory allocated from uper_decoder. TODO this is not good implementation, need to maintain RRC_INST own structure every time. NR_UE_rrc_inst[module_id].cell_group_config = cellGroupConfig; nr_rrc_ue_process_scg_config(module_id,cellGroupConfig); }else{ // after first time, update it and free the memory after. SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)NR_UE_rrc_inst[module_id].cell_group_config, 0); NR_UE_rrc_inst[module_id].cell_group_config = cellGroupConfig; nr_rrc_ue_process_scg_config(module_id,cellGroupConfig); } } if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->measConfig != NULL){ if(NR_UE_rrc_inst[module_id].meas_config == NULL){ NR_UE_rrc_inst[module_id].meas_config = rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->measConfig; }else{ // if some element need to be updated nr_rrc_ue_process_meas_config(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->measConfig); } } if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->lateNonCriticalExtension != NULL){ // unuse now } if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->nonCriticalExtension != NULL){ // unuse now } break; case NR_RRCReconfiguration__criticalExtensions_PR_NOTHING: case NR_RRCReconfiguration__criticalExtensions_PR_criticalExtensionsFuture: default: break; } //nr_rrc_mac_config_req_ue(); return 0; } int8_t nr_rrc_ue_process_meas_config(NR_MeasConfig_t *meas_config){ return 0; } int8_t nr_rrc_ue_process_scg_config(const module_id_t module_id, NR_CellGroupConfig_t *cell_group_config){ int i; if(NR_UE_rrc_inst[module_id].cell_group_config==NULL){ // initial list if(cell_group_config->spCellConfig != NULL){ if(cell_group_config->spCellConfig->spCellConfigDedicated != NULL){ if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList != NULL){ for(i=0; i<cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; ++i){ RRC_LIST_MOD_ADD(NR_UE_rrc_inst[module_id].BWP_Downlink_list, cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[i], bwp_Id); } } } } }else{ // maintain list if(cell_group_config->spCellConfig != NULL){ if(cell_group_config->spCellConfig->spCellConfigDedicated != NULL){ // process element of list to be add by RRC message if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList != NULL){ for(i=0; i<cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; ++i){ RRC_LIST_MOD_ADD(NR_UE_rrc_inst[module_id].BWP_Downlink_list, cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[i], bwp_Id); } } // process element of list to be release by RRC message if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList != NULL){ for(i=0; i<cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList->list.count; ++i){ NR_BWP_Downlink_t *freeP = NULL; RRC_LIST_MOD_REL(NR_UE_rrc_inst[module_id].BWP_Downlink_list, bwp_Id, *cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList->list.array[i], freeP); if(freeP != NULL){ SEQUENCE_free(&asn_DEF_NR_BWP_Downlink, (void *)freeP, 0); } } } } } } return 0; } void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type, void *message,int msg_len) { module_id_t module_id=0; // TODO switch (nsa_message_type) { case nr_SecondaryCellGroupConfig_r15: { NR_RRCReconfiguration_t *RRCReconfiguration=NULL; asn_dec_rval_t dec_rval = uper_decode_complete( NULL, &asn_DEF_NR_RRCReconfiguration, (void **)&RRCReconfiguration, (uint8_t *)message, msg_len); if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { LOG_E(RRC,"NR_RRCReconfiguration decode error\n"); // free the memory SEQUENCE_free( &asn_DEF_NR_RRCReconfiguration, RRCReconfiguration, 1 ); return; } nr_rrc_ue_process_rrcReconfiguration(module_id,RRCReconfiguration); } break; case nr_RadioBearerConfigX_r15: { NR_RadioBearerConfig_t *RadioBearerConfig=NULL; asn_dec_rval_t dec_rval = uper_decode_complete( NULL, &asn_DEF_NR_RadioBearerConfig, (void **)&RadioBearerConfig, (uint8_t *)message, msg_len); if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { LOG_E(RRC,"NR_RadioBearerConfig decode error\n"); // free the memory SEQUENCE_free( &asn_DEF_NR_RadioBearerConfig, RadioBearerConfig, 1 ); return; } nr_rrc_ue_process_RadioBearerConfig(RadioBearerConfig); } break; default: AssertFatal(1==0,"Unknown message %d\n",nsa_message_type); break; } } NR_UE_RRC_INST_t* openair_rrc_top_init_ue_nr(char* rrc_config_path){ int nr_ue; if(NB_NR_UE_INST > 0){ NR_UE_rrc_inst = (NR_UE_RRC_INST_t *)malloc(NB_NR_UE_INST * sizeof(NR_UE_RRC_INST_t)); memset(NR_UE_rrc_inst, 0, NB_NR_UE_INST * sizeof(NR_UE_RRC_INST_t)); for(nr_ue=0;nr_ue<NB_NR_UE_INST;nr_ue++){ // fill UE-NR-Capability @ UE-CapabilityRAT-Container here. NR_UE_rrc_inst[nr_ue].selected_plmn_identity = 1; // TODO: Put the appropriate list of SIBs NR_UE_rrc_inst[nr_ue].requested_SI_List.buf = CALLOC(1,4); NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[0] = SIB2 | SIB3 | SIB5; // SIB2 - SIB9 NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[1] = 0; // SIB10 - SIB17 NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[2] = 0; // SIB18 - SIB25 NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[3] = 0; // SIB26 - SIB32 NR_UE_rrc_inst[nr_ue].requested_SI_List.size= 4; NR_UE_rrc_inst[nr_ue].requested_SI_List.bits_unused= 0; NR_UE_rrc_inst[nr_ue].ra_trigger = RA_NOT_RUNNING; // init RRC lists RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RLC_Bearer_Config_list, NR_maxLC_ID); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SchedulingRequest_list, NR_maxNrofSR_ConfigPerCellGroup); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TAG_list, NR_maxNrofTAGs); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TDD_UL_DL_SlotConfig_list, NR_maxNrofSlots); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].BWP_Downlink_list, NR_maxNrofBWPs); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ControlResourceSet_list[0], 3); // for init-dl-bwp RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ControlResourceSet_list[1], 3); // for dl-bwp id=0 RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ControlResourceSet_list[2], 3); // for dl-bwp id=1 RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ControlResourceSet_list[3], 3); // for dl-bwp id=2 RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ControlResourceSet_list[4], 3); // for dl-bwp id=3 RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SearchSpace_list[0], 10); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SearchSpace_list[1], 10); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SearchSpace_list[2], 10); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SearchSpace_list[3], 10); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SearchSpace_list[4], 10); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SlotFormatCombinationsPerCell_list[0], NR_maxNrofAggregatedCellsPerCellGroup); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SlotFormatCombinationsPerCell_list[1], NR_maxNrofAggregatedCellsPerCellGroup); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SlotFormatCombinationsPerCell_list[2], NR_maxNrofAggregatedCellsPerCellGroup); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SlotFormatCombinationsPerCell_list[3], NR_maxNrofAggregatedCellsPerCellGroup); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SlotFormatCombinationsPerCell_list[4], NR_maxNrofAggregatedCellsPerCellGroup); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TCI_State_list[0], NR_maxNrofTCI_States); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TCI_State_list[1], NR_maxNrofTCI_States); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TCI_State_list[2], NR_maxNrofTCI_States); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TCI_State_list[3], NR_maxNrofTCI_States); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TCI_State_list[4], NR_maxNrofTCI_States); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RateMatchPattern_list[0], NR_maxNrofRateMatchPatterns); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RateMatchPattern_list[1], NR_maxNrofRateMatchPatterns); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RateMatchPattern_list[2], NR_maxNrofRateMatchPatterns); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RateMatchPattern_list[3], NR_maxNrofRateMatchPatterns); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RateMatchPattern_list[4], NR_maxNrofRateMatchPatterns); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ZP_CSI_RS_Resource_list[0], NR_maxNrofZP_CSI_RS_Resources); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ZP_CSI_RS_Resource_list[1], NR_maxNrofZP_CSI_RS_Resources); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ZP_CSI_RS_Resource_list[2], NR_maxNrofZP_CSI_RS_Resources); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ZP_CSI_RS_Resource_list[3], NR_maxNrofZP_CSI_RS_Resources); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ZP_CSI_RS_Resource_list[4], NR_maxNrofZP_CSI_RS_Resources); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].Aperidic_ZP_CSI_RS_ResourceSet_list[0], NR_maxNrofZP_CSI_RS_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].Aperidic_ZP_CSI_RS_ResourceSet_list[1], NR_maxNrofZP_CSI_RS_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].Aperidic_ZP_CSI_RS_ResourceSet_list[2], NR_maxNrofZP_CSI_RS_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].Aperidic_ZP_CSI_RS_ResourceSet_list[3], NR_maxNrofZP_CSI_RS_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].Aperidic_ZP_CSI_RS_ResourceSet_list[4], NR_maxNrofZP_CSI_RS_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SP_ZP_CSI_RS_ResourceSet_list[0], NR_maxNrofZP_CSI_RS_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SP_ZP_CSI_RS_ResourceSet_list[1], NR_maxNrofZP_CSI_RS_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SP_ZP_CSI_RS_ResourceSet_list[2], NR_maxNrofZP_CSI_RS_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SP_ZP_CSI_RS_ResourceSet_list[3], NR_maxNrofZP_CSI_RS_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SP_ZP_CSI_RS_ResourceSet_list[4], NR_maxNrofZP_CSI_RS_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].NZP_CSI_RS_Resource_list, NR_maxNrofNZP_CSI_RS_Resources); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].NZP_CSI_RS_ResourceSet_list, NR_maxNrofNZP_CSI_RS_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_IM_Resource_list, NR_maxNrofCSI_IM_Resources); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_IM_ResourceSet_list, NR_maxNrofCSI_IM_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_SSB_ResourceSet_list, NR_maxNrofCSI_SSB_ResourceSets); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_ResourceConfig_list, NR_maxNrofCSI_ResourceConfigurations); RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_ReportConfig_list, NR_maxNrofCSI_ReportConfigurations); } if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra==1 || get_softmodem_params()->sa == 1) { // read in files for RRCReconfiguration and RBconfig FILE *fd; char filename[1024]; if (rrc_config_path) sprintf(filename,"%s/reconfig.raw",rrc_config_path); else sprintf(filename,"reconfig.raw"); fd = fopen(filename,"r"); char buffer[1024]; AssertFatal(fd, "cannot read file %s: errno %d, %s\n", filename, errno, strerror(errno)); int msg_len=fread(buffer,1,1024,fd); fclose(fd); process_nsa_message(NR_UE_rrc_inst, nr_SecondaryCellGroupConfig_r15, buffer,msg_len); if (rrc_config_path) sprintf(filename,"%s/rbconfig.raw",rrc_config_path); else sprintf(filename,"rbconfig.raw"); fd = fopen(filename,"r"); AssertFatal(fd, "cannot read file %s: errno %d, %s\n", filename, errno, strerror(errno)); msg_len=fread(buffer,1,1024,fd); fclose(fd); process_nsa_message(NR_UE_rrc_inst, nr_RadioBearerConfigX_r15, buffer,msg_len); } }else{ NR_UE_rrc_inst = NULL; } return NR_UE_rrc_inst; } int8_t nr_ue_process_rlc_bearer_list(NR_CellGroupConfig_t *cell_group_config){ return 0; } int8_t nr_ue_process_secondary_cell_list(NR_CellGroupConfig_t *cell_group_config){ return 0; } int8_t nr_ue_process_mac_cell_group_config(NR_MAC_CellGroupConfig_t *mac_cell_group_config){ return 0; } int8_t nr_ue_process_physical_cell_group_config(NR_PhysicalCellGroupConfig_t *phy_cell_group_config){ return 0; } int8_t nr_ue_process_spcell_config(NR_SpCellConfig_t *spcell_config){ return 0; } /*brief decode BCCH-BCH (MIB) message*/ int8_t nr_rrc_ue_decode_NR_BCCH_BCH_Message( const module_id_t module_id, const uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len ){ int i; NR_BCCH_BCH_Message_t *bcch_message = NULL; NR_MIB_t *mib = NR_UE_rrc_inst[module_id].mib; if(mib != NULL){ SEQUENCE_free( &asn_DEF_NR_BCCH_BCH_Message, (void *)mib, 1 ); } //for(i=0; i<buffer_len; ++i){ // printf("[RRC] MIB PDU : %d\n", bufferP[i]); //} asn_dec_rval_t dec_rval = uper_decode_complete( NULL, &asn_DEF_NR_BCCH_BCH_Message, (void **)&bcch_message, (const void *)bufferP, buffer_len ); if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) { printf("NR_BCCH_BCH decode error\n"); for (i=0; i<buffer_len; i++){ printf("%02x ",bufferP[i]); } printf("\n"); // free the memory SEQUENCE_free( &asn_DEF_NR_BCCH_BCH_Message, (void *)bcch_message, 1 ); return -1; } else { // link to rrc instance mib = bcch_message->message.choice.mib; //memcpy( (void *)mib, // (void *)&bcch_message->message.choice.mib, // sizeof(NR_MIB_t) ); nr_rrc_mac_config_req_ue( 0, 0, 0, mib, NULL); } return 0; } const char siWindowLength[10][5] = {"5s", "10s", "20s", "40s", "80s", "160s", "320s", "640s", "1280s","ERR"};// {"1ms","2ms","5ms","10ms","15ms","20ms","40ms","80ms","ERR"}; const short siWindowLength_int[9] = {5,10,20,40,80,160,320,640,1280};//{1,2,5,10,15,20,40,80}; const char SIBType[12][6] = {"SIB3","SIB4","SIB5","SIB6","SIB7","SIB8","SIB9","SIB10","SIB11","SIB12","SIB13","Spare"}; const char SIBPeriod[8][6] = {"rf8","rf16","rf32","rf64","rf128","rf256","rf512","ERR"}; int siPeriod_int[7] = {80,160,320,640,1280,2560,5120}; const char *nr_SIBreserved( long value ) { if (value < 0 || value > 1) return "ERR"; if (value) return "notReserved"; return "reserved"; } void nr_dump_sib2( NR_SIB2_t *sib2 ){ //cellReselectionInfoCommon //nrofSS_BlocksToAverage if( sib2->cellReselectionInfoCommon.nrofSS_BlocksToAverage) LOG_I( RRC, "cellReselectionInfoCommon.nrofSS_BlocksToAverage : %ld\n", *sib2->cellReselectionInfoCommon.nrofSS_BlocksToAverage ); else LOG_I( RRC, "cellReselectionInfoCommon->nrofSS_BlocksToAverage : not defined\n" ); //absThreshSS_BlocksConsolidation if( sib2->cellReselectionInfoCommon.absThreshSS_BlocksConsolidation){ LOG_I( RRC, "absThreshSS_BlocksConsolidation.thresholdRSRP : %ld\n", *sib2->cellReselectionInfoCommon.absThreshSS_BlocksConsolidation->thresholdRSRP ); LOG_I( RRC, "absThreshSS_BlocksConsolidation.thresholdRSRQ : %ld\n", *sib2->cellReselectionInfoCommon.absThreshSS_BlocksConsolidation->thresholdRSRQ ); LOG_I( RRC, "absThreshSS_BlocksConsolidation.thresholdSINR : %ld\n", *sib2->cellReselectionInfoCommon.absThreshSS_BlocksConsolidation->thresholdSINR ); } else LOG_I( RRC, "cellReselectionInfoCommon->absThreshSS_BlocksConsolidation : not defined\n" ); //q_Hyst LOG_I( RRC, "cellReselectionInfoCommon.q_Hyst : %ld\n", sib2->cellReselectionInfoCommon.q_Hyst ); //speedStateReselectionPars if( sib2->cellReselectionInfoCommon.speedStateReselectionPars){ LOG_I( RRC, "speedStateReselectionPars->mobilityStateParameters.t_Evaluation : %ld\n", sib2->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.t_Evaluation); LOG_I( RRC, "speedStateReselectionPars->mobilityStateParameters.t_HystNormal : %ld\n", sib2->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.t_HystNormal); LOG_I( RRC, "speedStateReselectionPars->mobilityStateParameters.n_CellChangeMedium : %ld\n", sib2->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.n_CellChangeMedium); LOG_I( RRC, "speedStateReselectionPars->mobilityStateParameters.n_CellChangeHigh : %ld\n", sib2->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.n_CellChangeHigh); LOG_I( RRC, "speedStateReselectionPars->q_HystSF.sf_Medium : %ld\n", sib2->cellReselectionInfoCommon.speedStateReselectionPars->q_HystSF.sf_Medium); LOG_I( RRC, "speedStateReselectionPars->q_HystSF.sf_High : %ld\n", sib2->cellReselectionInfoCommon.speedStateReselectionPars->q_HystSF.sf_High); } else LOG_I( RRC, "cellReselectionInfoCommon->speedStateReselectionPars : not defined\n" ); //cellReselectionServingFreqInfo if( sib2->cellReselectionServingFreqInfo.s_NonIntraSearchP) LOG_I( RRC, "cellReselectionServingFreqInfo.s_NonIntraSearchP : %ld\n", *sib2->cellReselectionServingFreqInfo.s_NonIntraSearchP ); else LOG_I( RRC, "cellReselectionServingFreqInfo->s_NonIntraSearchP : not defined\n" ); if( sib2->cellReselectionServingFreqInfo.s_NonIntraSearchQ) LOG_I( RRC, "cellReselectionServingFreqInfo.s_NonIntraSearchQ : %ld\n", *sib2->cellReselectionServingFreqInfo.s_NonIntraSearchQ ); else LOG_I( RRC, "cellReselectionServingFreqInfo->s_NonIntraSearchQ : not defined\n" ); LOG_I( RRC, "cellReselectionServingFreqInfo.threshServingLowP : %ld\n", sib2->cellReselectionServingFreqInfo.threshServingLowP ); if( sib2->cellReselectionServingFreqInfo.threshServingLowQ) LOG_I( RRC, "cellReselectionServingFreqInfo.threshServingLowQ : %ld\n", *sib2->cellReselectionServingFreqInfo.threshServingLowQ ); else LOG_I( RRC, "cellReselectionServingFreqInfo->threshServingLowQ : not defined\n" ); LOG_I( RRC, "cellReselectionServingFreqInfo.cellReselectionPriority : %ld\n", sib2->cellReselectionServingFreqInfo.cellReselectionPriority ); if( sib2->cellReselectionServingFreqInfo.cellReselectionSubPriority) LOG_I( RRC, "cellReselectionServingFreqInfo.cellReselectionSubPriority : %ld\n", *sib2->cellReselectionServingFreqInfo.cellReselectionSubPriority ); else LOG_I( RRC, "cellReselectionServingFreqInfo->cellReselectionSubPriority : not defined\n" ); //intraFreqCellReselectionInfo LOG_I( RRC, "intraFreqCellReselectionInfo.q_RxLevMin : %ld\n", sib2->intraFreqCellReselectionInfo.q_RxLevMin ); if( sib2->intraFreqCellReselectionInfo.q_RxLevMinSUL) LOG_I( RRC, "intraFreqCellReselectionInfo.q_RxLevMinSUL : %ld\n", *sib2->intraFreqCellReselectionInfo.q_RxLevMinSUL ); else LOG_I( RRC, "intraFreqCellReselectionInfo->q_RxLevMinSUL : not defined\n" ); if( sib2->intraFreqCellReselectionInfo.q_QualMin) LOG_I( RRC, "intraFreqCellReselectionInfo.q_QualMin : %ld\n", *sib2->intraFreqCellReselectionInfo.q_QualMin ); else LOG_I( RRC, "intraFreqCellReselectionInfo->q_QualMin : not defined\n" ); LOG_I( RRC, "intraFreqCellReselectionInfo.s_IntraSearchP : %ld\n", sib2->intraFreqCellReselectionInfo.s_IntraSearchP ); if( sib2->intraFreqCellReselectionInfo.s_IntraSearchQ) LOG_I( RRC, "intraFreqCellReselectionInfo.s_IntraSearchQ : %ld\n", *sib2->intraFreqCellReselectionInfo.s_IntraSearchQ ); else LOG_I( RRC, "intraFreqCellReselectionInfo->s_IntraSearchQ : not defined\n" ); LOG_I( RRC, "intraFreqCellReselectionInfo.t_ReselectionNR : %ld\n", sib2->intraFreqCellReselectionInfo.t_ReselectionNR ); if( sib2->intraFreqCellReselectionInfo.frequencyBandList) LOG_I( RRC, "intraFreqCellReselectionInfo.frequencyBandList : %p\n", sib2->intraFreqCellReselectionInfo.frequencyBandList ); else LOG_I( RRC, "intraFreqCellReselectionInfo->frequencyBandList : not defined\n" ); if( sib2->intraFreqCellReselectionInfo.frequencyBandListSUL) LOG_I( RRC, "intraFreqCellReselectionInfo.frequencyBandListSUL : %p\n", sib2->intraFreqCellReselectionInfo.frequencyBandListSUL ); else LOG_I( RRC, "intraFreqCellReselectionInfo->frequencyBandListSUL : not defined\n" ); if( sib2->intraFreqCellReselectionInfo.p_Max) LOG_I( RRC, "intraFreqCellReselectionInfo.p_Max : %ld\n", *sib2->intraFreqCellReselectionInfo.p_Max ); else LOG_I( RRC, "intraFreqCellReselectionInfo->p_Max : not defined\n" ); if( sib2->intraFreqCellReselectionInfo.smtc) LOG_I( RRC, "intraFreqCellReselectionInfo.smtc : %p\n", sib2->intraFreqCellReselectionInfo.smtc ); else LOG_I( RRC, "intraFreqCellReselectionInfo->smtc : not defined\n" ); if( sib2->intraFreqCellReselectionInfo.ss_RSSI_Measurement) LOG_I( RRC, "intraFreqCellReselectionInfo.ss_RSSI_Measurement : %p\n", sib2->intraFreqCellReselectionInfo.ss_RSSI_Measurement ); else LOG_I( RRC, "intraFreqCellReselectionInfo->ss_RSSI_Measurement : not defined\n" ); if( sib2->intraFreqCellReselectionInfo.ssb_ToMeasure) LOG_I( RRC, "intraFreqCellReselectionInfo.ssb_ToMeasure : %p\n", sib2->intraFreqCellReselectionInfo.ssb_ToMeasure ); else LOG_I( RRC, "intraFreqCellReselectionInfo->ssb_ToMeasure : not defined\n" ); LOG_I( RRC, "intraFreqCellReselectionInfo.deriveSSB_IndexFromCell : %d\n", sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell ); } void nr_dump_sib3( NR_SIB3_t *sib3 ) { //intraFreqNeighCellList if( sib3->intraFreqNeighCellList){ LOG_I( RRC, "intraFreqNeighCellList : %p\n", sib3->intraFreqNeighCellList ); const int n = sib3->intraFreqNeighCellList->list.count; for (int i = 0; i < n; ++i){ LOG_I( RRC, "intraFreqNeighCellList->physCellId : %ld\n", sib3->intraFreqNeighCellList->list.array[i]->physCellId ); LOG_I( RRC, "intraFreqNeighCellList->q_OffsetCell : %ld\n", sib3->intraFreqNeighCellList->list.array[i]->q_OffsetCell ); if( sib3->intraFreqNeighCellList->list.array[i]->q_RxLevMinOffsetCell) LOG_I( RRC, "intraFreqNeighCellList->q_RxLevMinOffsetCell : %ld\n", *sib3->intraFreqNeighCellList->list.array[i]->q_RxLevMinOffsetCell ); else LOG_I( RRC, "intraFreqNeighCellList->q_RxLevMinOffsetCell : not defined\n" ); if( sib3->intraFreqNeighCellList->list.array[i]->q_RxLevMinOffsetCellSUL) LOG_I( RRC, "intraFreqNeighCellList->q_RxLevMinOffsetCellSUL : %ld\n", *sib3->intraFreqNeighCellList->list.array[i]->q_RxLevMinOffsetCellSUL ); else LOG_I( RRC, "intraFreqNeighCellList->q_RxLevMinOffsetCellSUL : not defined\n" ); if( sib3->intraFreqNeighCellList->list.array[i]->q_QualMinOffsetCell) LOG_I( RRC, "intraFreqNeighCellList->q_QualMinOffsetCell : %ld\n", *sib3->intraFreqNeighCellList->list.array[i]->q_QualMinOffsetCell ); else LOG_I( RRC, "intraFreqNeighCellList->q_QualMinOffsetCell : not defined\n" ); } } else{ LOG_I( RRC, "intraFreqCellReselectionInfo : not defined\n" ); } //intraFreqBlackCellList if( sib3->intraFreqBlackCellList){ LOG_I( RRC, "intraFreqBlackCellList : %p\n", sib3->intraFreqBlackCellList ); const int n = sib3->intraFreqBlackCellList->list.count; for (int i = 0; i < n; ++i){ LOG_I( RRC, "intraFreqBlackCellList->start : %ld\n", sib3->intraFreqBlackCellList->list.array[i]->start ); if( sib3->intraFreqBlackCellList->list.array[i]->range) LOG_I( RRC, "intraFreqBlackCellList->range : %ld\n", *sib3->intraFreqBlackCellList->list.array[i]->range ); else LOG_I( RRC, "intraFreqBlackCellList->range : not defined\n" ); } } else{ LOG_I( RRC, "intraFreqBlackCellList : not defined\n" ); } //lateNonCriticalExtension if( sib3->lateNonCriticalExtension) LOG_I( RRC, "lateNonCriticalExtension : %p\n", sib3->lateNonCriticalExtension ); else LOG_I( RRC, "lateNonCriticalExtension : not defined\n" ); } int nr_decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index ) { NR_SystemInformation_t **si = &NR_UE_rrc_inst[ctxt_pP->module_id].si[gNB_index]; int new_sib = 0; NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN ); // Dump contents if ((*si)->criticalExtensions.present == NR_SystemInformation__criticalExtensions_PR_systemInformation || (*si)->criticalExtensions.present == NR_SystemInformation__criticalExtensions_PR_criticalExtensionsFuture_r16) { LOG_D( RRC, "[UE] (*si)->criticalExtensions.choice.NR_SystemInformation_t->sib_TypeAndInfo.list.count %d\n", (*si)->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.count ); } else { LOG_D( RRC, "[UE] Unknown criticalExtension version (not Rel16)\n" ); return -1; } for (int i=0; i<(*si)->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.count; i++) { SystemInformation_IEs__sib_TypeAndInfo__Member *typeandinfo; typeandinfo = (*si)->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.array[i]; switch(typeandinfo->present) { case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&2) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=2; //new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib2[gNB_index], &typeandinfo->choice.sib2, sizeof(NR_SIB2_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB2 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); nr_dump_sib2( NR_UE_rrc_inst[ctxt_pP->module_id].sib2[gNB_index] ); LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB2 params gNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n", ctxt_pP->frame, ctxt_pP->module_id, gNB_index, ctxt_pP->module_id ); //TODO rrc_mac_config_req_ue // After SI is received, prepare RRCConnectionRequest if (NR_UE_rrc_inst[ctxt_pP->module_id].MBMS_flag < 3) // see -Q option if (AMF_MODE_ENABLED) { nr_rrc_ue_generate_RRCSetupRequest( ctxt_pP->module_id, gNB_index ); } if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State == NR_RRC_IDLE) { LOG_I( RRC, "[UE %d] Received SIB1/SIB2/SIB3 Switching to RRC_SI_RECEIVED\n", ctxt_pP->module_id ); NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State = NR_RRC_SI_RECEIVED; #if ENABLE_RAL /* TODO { MessageDef *message_ral_p = NULL; rrc_ral_system_information_ind_t ral_si_ind; message_ral_p = itti_alloc_new_message (TASK_RRC_UE, 0, RRC_RAL_SYSTEM_INFORMATION_IND); memset(&ral_si_ind, 0, sizeof(rrc_ral_system_information_ind_t)); ral_si_ind.plmn_id.MCCdigit2 = '0'; ral_si_ind.plmn_id.MCCdigit1 = '2'; ral_si_ind.plmn_id.MNCdigit3 = '0'; ral_si_ind.plmn_id.MCCdigit3 = '8'; ral_si_ind.plmn_id.MNCdigit2 = '9'; ral_si_ind.plmn_id.MNCdigit1 = '9'; ral_si_ind.cell_id = 1; ral_si_ind.dbm = 0; //ral_si_ind.dbm = fifo_dump_emos_UE.PHY_measurements->rx_rssi_dBm[gNB_index]; // TO DO ral_si_ind.sinr = 0; //ral_si_ind.sinr = fifo_dump_emos_UE.PHY_measurements->subband_cqi_dB[gNB_index][phy_vars_ue->lte_frame_parms.nb_antennas_rx][0]; // TO DO ral_si_ind.link_data_rate = 0; memcpy (&message_ral_p->ittiMsg, (void *) &ral_si_ind, sizeof(rrc_ral_system_information_ind_t)); #warning "ue_mod_idP ? for instance ?" itti_send_msg_to_task (TASK_RAL_UE, UE_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), message_ral_p); }*/ #endif } } break; // case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2 case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib3: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&4) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=4; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib3[gNB_index], &typeandinfo->choice.sib3, sizeof(LTE_SystemInformationBlockType3_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB3 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); nr_dump_sib3( NR_UE_rrc_inst[ctxt_pP->module_id].sib3[gNB_index] ); } break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib4: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&8) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=8; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib4[gNB_index], typeandinfo->choice.sib4, sizeof(NR_SIB4_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB4 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); } break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib5: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&16) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=16; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib5[gNB_index], typeandinfo->choice.sib5, sizeof(NR_SIB5_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB5 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); //dump_sib5(NR_UE_rrc_inst[ctxt_pP->module_id].sib5[gNB_index]); } break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib6: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&32) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=32; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib6[gNB_index], typeandinfo->choice.sib6, sizeof(NR_SIB6_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB6 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); } break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib7: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&64) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=64; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib7[gNB_index], typeandinfo->choice.sib7, sizeof(NR_SIB7_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB7 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); } break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib8: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&128) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=128; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib8[gNB_index], typeandinfo->choice.sib8, sizeof(NR_SIB8_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB8 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); } break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib9: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&256) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=256; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib9[gNB_index], typeandinfo->choice.sib9, sizeof(NR_SIB9_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB9 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); } break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib10_v1610: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&512) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=512; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib10[gNB_index], typeandinfo->choice.sib10_v1610, sizeof(NR_SIB10_r16_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB10 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); } break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib11_v1610: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1024) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=1024; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib11[gNB_index], typeandinfo->choice.sib11_v1610, sizeof(NR_SIB11_r16_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB11 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); } break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib12_v1610: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&2048) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=2048; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib12[gNB_index], typeandinfo->choice.sib12_v1610, sizeof(NR_SIB12_r16_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB12 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); } break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib13_v1610: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&4096) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=4096; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib13[gNB_index], typeandinfo->choice.sib13_v1610, sizeof(NR_SIB13_r16_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB13 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); //dump_sib13( NR_UE_rrc_inst[ctxt_pP->module_id].sib13[gNB_index] ); // adding here function to store necessary parameters for using in decode_MCCH_Message + maybe transfer to PHY layer LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB13 params gNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n", ctxt_pP->frame, ctxt_pP->module_id, gNB_index, ctxt_pP->module_id); // TODO rrc_mac_config_req_ue } break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib14_v1610: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&8192) == 0) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=8192; new_sib=1; memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib12[gNB_index], typeandinfo->choice.sib14_v1610, sizeof(NR_SIB14_r16_t) ); LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB14 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); } break; default: break; } if (new_sib == 1) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt++; if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt == sib1->si_SchedulingInfo->schedulingInfoList.list.count) nr_rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_SIB_COMPLETE ); LOG_I(RRC,"SIStatus %x, SIcnt %d/%d\n", NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus, NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt, sib1->si_SchedulingInfo->schedulingInfoList.list.count); } } //if (new_sib == 1) { // NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt++; // if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt == sib1->schedulingInfoList.list.count) // rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_SIB_COMPLETE ); // LOG_I(RRC,"SIStatus %x, SIcnt %d/%d\n", // NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus, // NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt, // sib1->schedulingInfoList.list.count); //} VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_OUT); return 0; } int nr_decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index, const uint8_t rsrq, const uint8_t rsrp ) { NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_IN ); LOG_I( RRC, "[UE %d] : Dumping SIB 1\n", ctxt_pP->module_id ); const int n = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count; for (int i = 0; i < n; ++i) { NR_PLMN_Identity_t *PLMN_identity = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[i]->plmn_IdentityList.list.array[0]; int mccdigits = PLMN_identity->mcc->list.count; int mncdigits = PLMN_identity->mnc.list.count; int mcc; if (mccdigits == 2) { mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1]; } else { mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2]; } int mnc; if (mncdigits == 2) { mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1]; } else { mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2]; } LOG_I( RRC, "PLMN %d MCC %0*d, MNC %0*d\n", i + 1, mccdigits, mcc, mncdigits, mnc); // search internal table for provider name int plmn_ind = 0; while (plmn_data[plmn_ind].mcc > 0) { if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) { LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short ); break; } plmn_ind++; } } LOG_I( RRC, "TAC 0x%04x\n", ((sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->size == 2)?((sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->buf[0]<<8) + sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->buf[1]):0)); LOG_I( RRC, "cellReservedForOperatorUse : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse, nr_SIBreserved(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse) ); LOG_I( RRC, "cellAccessRelatedInfo.cellIdentity : raw:%"PRIu32" decoded:%02x.%02x.%02x.%02x\n", BIT_STRING_to_uint32( &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity ), sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[0], sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[1], sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[2], sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[3] >> sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.bits_unused); //LOG_I( RRC, "cellAccessRelatedInfo.cellBarred : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.cellBarred, SIBbarred(sib1->cellAccessRelatedInfo.cellBarred) ); //LOG_I( RRC, "cellAccessRelatedInfo.intraFreqReselection : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.intraFreqReselection, SIBallowed(sib1->cellAccessRelatedInfo.intraFreqReselection) ); //LOG_I( RRC, "cellAccessRelatedInfo.csg_Indication : %d\n", sib1->cellAccessRelatedInfo.csg_Indication ); //if (sib1->cellAccessRelatedInfo.csg_Identity) // LOG_I( RRC, "cellAccessRelatedInfo.csg_Identity : %"PRIu32"\n", BIT_STRING_to_uint32(sib1->cellAccessRelatedInfo.csg_Identity) ); //else // LOG_I( RRC, "cellAccessRelatedInfo.csg_Identity : not defined\n" ); LOG_I( RRC, "cellSelectionInfo.q_RxLevMin : %ld\n", sib1->cellSelectionInfo->q_RxLevMin ); if (sib1->cellSelectionInfo->q_RxLevMinOffset) LOG_I( RRC, "cellSelectionInfo.q_RxLevMinOffset : %ld\n", *sib1->cellSelectionInfo->q_RxLevMinOffset ); else LOG_I( RRC, "cellSelectionInfo.q_RxLevMinOffset : not defined\n" ); //if (sib1->p_Max) // LOG_I( RRC, "p_Max : %ld\n", *sib1->p_Max ); //else // LOG_I( RRC, "p_Max : not defined\n" ); //LOG_I( RRC, "freqBandIndicator : %ld\n", sib1->freqBandIndicator ); if (sib1->si_SchedulingInfo->schedulingInfoList.list.count > 0) { for (int i=0; i<sib1->si_SchedulingInfo->schedulingInfoList.list.count; i++) { LOG_I( RRC, "si_Periodicity[%d] : %s\n", i, SIBPeriod[min(sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->si_Periodicity,7)]); if (sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count > 0) { char temp[32 * sizeof(SIBType[0])] = {0}; // maxSIB==32 for (int j=0; j<sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count; j++) { sprintf( temp + j*sizeof(SIBType[0]), "%*s ", (int)sizeof(SIBType[0])-1, SIBType[min(sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.array[0]->type,11)] ); } LOG_I( RRC, "siSchedulingInfoSIBType[%d] : %s\n", i, temp ); } else { LOG_I( RRC, "mapping list %d is null\n", i ); } } } else { LOG_E( RRC, "siSchedulingInfoPeriod[0] : PROBLEM!!!\n" ); return -1; } if (sib1->servingCellConfigCommon->tdd_UL_DL_ConfigurationCommon) { //TODO } LOG_I( RRC, "siWindowLength : %s\n", siWindowLength[min(sib1->si_SchedulingInfo->si_WindowLength,8)] ); //LOG_I( RRC, "systemInfoValueTag : %ld\n", sib1->systemInfoValueTag ); NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIperiod = siPeriod_int[sib1->si_SchedulingInfo->schedulingInfoList.list.array[0]->si_Periodicity]; NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIwindowsize = siWindowLength_int[sib1->si_SchedulingInfo->si_WindowLength]; LOG_I( RRC, "[FRAME unknown][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB1 params gNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n", ctxt_pP->module_id, gNB_index, ctxt_pP->module_id ); //rrc_mac_config_req_ue LOG_I(RRC,"Setting SIStatus bit 0 to 1\n"); NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus = 1; //NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIB1systemInfoValueTag = sib1->systemInfoValueTag; if (AMF_MODE_ENABLED) { int cell_valid = 0; //if (sib1->cellAccessRelatedInfo.cellBarred == LTE_SystemInformationBlockType1__cellAccessRelatedInfo__cellBarred_notBarred) { /* Cell is not barred */ int plmn; int plmn_number; plmn_number = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count; /* Compare requested PLMN and PLMNs from SIB1*/ for (plmn = 0; plmn < plmn_number; plmn++) { NR_PLMN_Identity_t *plmn_Identity; plmn_Identity = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[plmn]->plmn_IdentityList.list.array[0]; if ( ( (plmn_Identity->mcc == NULL) || ( (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit1 == *(plmn_Identity->mcc->list.array[0])) && (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit2 == *(plmn_Identity->mcc->list.array[1])) && (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit3 == *(plmn_Identity->mcc->list.array[2])) ) ) && (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit1 == *(plmn_Identity->mnc.list.array[0])) && (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit2 == *(plmn_Identity->mnc.list.array[1])) && ( ((NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == 0xf) && (plmn_Identity->mnc.list.count == 2)) || (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == *(plmn_Identity->mnc.list.array[2])) ) ) { /* PLMN match, send a confirmation to NAS */ MessageDef *msg_p; msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, NAS_CELL_SELECTION_CNF); NAS_CELL_SELECTION_CNF (msg_p).errCode = AS_SUCCESS; NAS_CELL_SELECTION_CNF (msg_p).cellID = BIT_STRING_to_uint32(&sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity); NAS_CELL_SELECTION_CNF (msg_p).tac = BIT_STRING_to_uint16(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode); NAS_CELL_SELECTION_CNF (msg_p).rat = 0xFF; NAS_CELL_SELECTION_CNF (msg_p).rsrq = rsrq; NAS_CELL_SELECTION_CNF (msg_p).rsrp = rsrp; itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); cell_valid = 1; NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity = plmn + 1; break; } } //} if (cell_valid == 0) { /* Cell can not be used, ask PHY to try the next one */ MessageDef *msg_p; msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, PHY_FIND_NEXT_CELL_REQ); itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p); LOG_E(RRC, "Synched with a cell, but PLMN doesn't match our SIM " "(selected_plmn_identity %ld), the message PHY_FIND_NEXT_CELL_REQ " "is sent but lost in current UE implementation!\n", NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_OUT ); return 0; } int nr_decode_BCCH_DLSCH_Message( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index, uint8_t *const Sdu, const uint8_t Sdu_len, const uint8_t rsrq, const uint8_t rsrp ) { NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN ); if (((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 1) && // SIB1 received (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt == sib1->si_SchedulingInfo->schedulingInfoList.list.count)) { // to prevent memory bloating VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); return 0; } nr_rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_RECEIVING_SIB_NR ); if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_BCCH_DL_SCH_Message,(void *)bcch_message ); } asn_dec_rval_t dec_rval = uper_decode_complete( NULL, &asn_DEF_NR_BCCH_DL_SCH_Message, (void **)&bcch_message, (const void *)Sdu, Sdu_len ); if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { LOG_E( RRC, "[UE %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n", ctxt_pP->module_id, dec_rval.consumed ); log_dump(RRC, Sdu, Sdu_len, LOG_DUMP_CHAR," Received bytes:\n" ); // free the memory SEQUENCE_free( &asn_DEF_LTE_BCCH_DL_SCH_Message, (void *)bcch_message, 1 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); return -1; } if (bcch_message->message.present == NR_BCCH_DL_SCH_MessageType_PR_c1) { switch (bcch_message->message.choice.c1->present) { case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1: if ((ctxt_pP->frame % 2) == 0) { // even frame if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 0) { NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index]; memcpy( (void *)sib1, (void *)bcch_message->message.choice.c1->choice.systemInformationBlockType1, sizeof(NR_SIB1_t) ); LOG_D( RRC, "[UE %"PRIu8"] Decoding First SIB1\n", ctxt_pP->module_id ); nr_decode_SIB1( ctxt_pP, gNB_index, rsrq, rsrp ); } } break; case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 1) { // SIB1 with schedulingInfoList is available NR_SystemInformation_t *si = NR_UE_rrc_inst[ctxt_pP->module_id].si[gNB_index]; memcpy( si, bcch_message->message.choice.c1->choice.systemInformation, sizeof(NR_SystemInformation_t) ); LOG_I( RRC, "[UE %"PRIu8"] Decoding SI for frameP %"PRIu32"\n", ctxt_pP->module_id, ctxt_pP->frame ); nr_decode_SI( ctxt_pP, gNB_index ); //if (nfapi_mode == 3) //UE_mac_inst[ctxt_pP->module_id].SI_Decoded = 1; } break; case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING: default: break; } } if (nr_rrc_get_sub_state(ctxt_pP->module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE_NR) { //if ( (NR_UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data != NULL) || (!AMF_MODE_ENABLED)) { nr_rrc_ue_generate_RRCSetupRequest(ctxt_pP->module_id, 0); nr_rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_CONNECTING ); //} } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); return 0; } //----------------------------------------------------------------------------- void nr_rrc_ue_process_masterCellGroup( const protocol_ctxt_t *const ctxt_pP, uint8_t gNB_index, OCTET_STRING_t *masterCellGroup ) //----------------------------------------------------------------------------- { NR_CellGroupConfig_t *cellGroupConfig = (NR_CellGroupConfig_t *)masterCellGroup; if( cellGroupConfig->spCellConfig != NULL && cellGroupConfig->spCellConfig->reconfigurationWithSync != NULL){ //TODO (perform Reconfiguration with sync according to 5.3.5.5.2) //TODO (resume all suspended radio bearers and resume SCG transmission for all radio bearers, if suspended) } if( cellGroupConfig->rlc_BearerToReleaseList != NULL){ //TODO (perform RLC bearer release as specified in 5.3.5.5.3) } if( cellGroupConfig->rlc_BearerToAddModList != NULL){ //TODO (perform the RLC bearer addition/modification as specified in 5.3.5.5.4) } if( cellGroupConfig->mac_CellGroupConfig != NULL){ //TODO (configure the MAC entity of this cell group as specified in 5.3.5.5.5) } if( cellGroupConfig->sCellToReleaseList != NULL){ //TODO (perform SCell release as specified in 5.3.5.5.8) } if( cellGroupConfig->spCellConfig != NULL){ if (NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->spCellConfig) { memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->spCellConfig,cellGroupConfig->spCellConfig, sizeof(struct NR_SpCellConfig)); } else { NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->spCellConfig = cellGroupConfig->spCellConfig; } //TODO (configure the SpCell as specified in 5.3.5.5.7) } if( cellGroupConfig->sCellToAddModList != NULL){ //TODO (perform SCell addition/modification as specified in 5.3.5.5.9) } if( cellGroupConfig->ext2->bh_RLC_ChannelToReleaseList_r16 != NULL){ //TODO (perform the BH RLC channel addition/modification as specified in 5.3.5.5.11) } if( cellGroupConfig->ext2->bh_RLC_ChannelToAddModList_r16 != NULL){ //TODO (perform the BH RLC channel addition/modification as specified in 5.3.5.5.11) } } /*--------------------------------------------------*/ static void rrc_ue_generate_RRCSetupComplete( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index, const uint8_t Transaction_id, uint8_t sel_plmn_id){ uint8_t buffer[100]; uint8_t size; const char *nas_msg; int nas_msg_length; if (AMF_MODE_ENABLED) { #if ITTI_SIM as_nas_info_t initialNasMsg; generateRegistrationRequest(&initialNasMsg); nas_msg = (char*)initialNasMsg.data; nas_msg_length = initialNasMsg.length; #else nas_msg = (char *) NR_UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data; nas_msg_length = NR_UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.length; #endif } else { nas_msg = nr_nas_attach_req_imsi; nas_msg_length = sizeof(nr_nas_attach_req_imsi); } size = do_RRCSetupComplete(ctxt_pP->module_id,buffer,Transaction_id,sel_plmn_id,nas_msg_length,nas_msg); LOG_I(NR_RRC,"[UE %d][RAPROC] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCSetupComplete (bytes%d, gNB %d)\n", ctxt_pP->module_id,ctxt_pP->frame, size, gNB_index); LOG_D(RLC, "[FRAME %05d][RRC_UE][MOD %02d][][--- PDCP_DATA_REQ/%d Bytes (RRCConnectionSetupComplete to gNB %d MUI %d) --->][PDCP][MOD %02d][RB %02d]\n", ctxt_pP->frame, ctxt_pP->module_id+NB_RN_INST, size, gNB_index, nr_rrc_mui, ctxt_pP->module_id+NB_eNB_INST, DCCH); // ctxt_pP_local.rnti = ctxt_pP->rnti; rrc_data_req_ue( ctxt_pP, DCCH, nr_rrc_mui++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); #ifdef ITTI_SIM MessageDef *message_p; uint8_t *message_buffer; message_buffer = itti_malloc (TASK_RRC_UE_SIM, TASK_RRC_GNB_SIM, size); memcpy (message_buffer, buffer, size); message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, 0, UE_RRC_DCCH_DATA_IND); UE_RRC_DCCH_DATA_IND (message_p).rbid = 1; UE_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; UE_RRC_DCCH_DATA_IND (message_p).size = size; itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); #endif } int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB_INFO *const Srb_info, const uint8_t gNB_index ){ NR_DL_CCCH_Message_t *dl_ccch_msg=NULL; asn_dec_rval_t dec_rval; int rval=0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_IN); // LOG_D(RRC,"[UE %d] Decoding DL-CCCH message (%d bytes), State %d\n",ue_mod_idP,Srb_info->Rx_buffer.payload_size, // NR_UE_rrc_inst[ue_mod_idP].Info[gNB_index].State); dec_rval = uper_decode(NULL, &asn_DEF_NR_DL_CCCH_Message, (void **)&dl_ccch_msg, (uint8_t *)Srb_info->Rx_buffer.Payload, 100,0,0); // if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout,&asn_DEF_NR_DL_CCCH_Message,(void *)dl_ccch_msg); // } if ((dec_rval.code != RC_OK) && (dec_rval.consumed==0)) { LOG_E(RRC,"[UE %d] Frame %d : Failed to decode DL-CCCH-Message (%zu bytes)\n",ctxt_pP->module_id,ctxt_pP->frame,dec_rval.consumed); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_OUT); return -1; } if (dl_ccch_msg->message.present == NR_DL_CCCH_MessageType_PR_c1) { if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State == NR_RRC_SI_RECEIVED) { switch (dl_ccch_msg->message.choice.c1->present) { case NR_DL_CCCH_MessageType__c1_PR_NOTHING: LOG_I(NR_RRC, "[UE%d] Frame %d : Received PR_NOTHING on DL-CCCH-Message\n", ctxt_pP->module_id, ctxt_pP->frame); rval = 0; break; case NR_DL_CCCH_MessageType__c1_PR_rrcReject: LOG_I(NR_RRC, "[UE%d] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCConnectionReject \n", ctxt_pP->module_id, ctxt_pP->frame); rval = 0; break; case NR_DL_CCCH_MessageType__c1_PR_rrcSetup: LOG_I(NR_RRC, "[UE%d][RAPROC] Frame %d : Logical Channel DL-CCCH (SRB0), Received NR_RRCSetup RNTI %x\n", ctxt_pP->module_id, ctxt_pP->frame, ctxt_pP->rnti); // Get configuration // Release T300 timer NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T300_active = 0; nr_rrc_ue_process_masterCellGroup( ctxt_pP, gNB_index, &dl_ccch_msg->message.choice.c1->choice.rrcSetup->criticalExtensions.choice.rrcSetup->masterCellGroup); nr_sa_rrc_ue_process_radioBearerConfig( ctxt_pP, gNB_index, &dl_ccch_msg->message.choice.c1->choice.rrcSetup->criticalExtensions.choice.rrcSetup->radioBearerConfig); nr_rrc_set_state (ctxt_pP->module_id, RRC_STATE_CONNECTED); nr_rrc_set_sub_state (ctxt_pP->module_id, RRC_SUB_STATE_CONNECTED); NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].rnti = ctxt_pP->rnti; rrc_ue_generate_RRCSetupComplete( ctxt_pP, gNB_index, dl_ccch_msg->message.choice.c1->choice.rrcSetup->rrc_TransactionIdentifier, NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); rval = 0; break; default: LOG_E(NR_RRC, "[UE%d] Frame %d : Unknown message\n", ctxt_pP->module_id, ctxt_pP->frame); rval = -1; break; } } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_OUT); return rval; } int8_t check_requested_SI_List(module_id_t module_id, BIT_STRING_t requested_SI_List, NR_SIB1_t sib1) { if(sib1.si_SchedulingInfo) { bool SIB_to_request[32] = {}; LOG_D(RRC, "SIBs broadcasting: "); for(int i = 0; i < sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) { printf("SIB%li ", sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type + 2); } printf("\n"); LOG_D(RRC, "SIBs needed by UE: "); for(int j = 0; j < 8*requested_SI_List.size; j++) { if( ((requested_SI_List.buf[j/8]>>(j%8))&1) == 1) { printf("SIB%i ", j + 2); SIB_to_request[j] = true; for(int i = 0; i < sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) { if(sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type == j) { SIB_to_request[j] = false; break; } } } } printf("\n"); LOG_D(RRC, "SIBs to request by UE: "); bool do_ra = false; for(int j = 0; j < 8*requested_SI_List.size; j++) { if(SIB_to_request[j]) { printf("SIB%i ", j + 2); do_ra = true; } } printf("\n"); if(do_ra) { NR_UE_rrc_inst[module_id].ra_trigger = REQUEST_FOR_OTHER_SI; get_softmodem_params()->do_ra = 1; if(sib1.si_SchedulingInfo->si_RequestConfig) { LOG_D(RRC, "Trigger contention-free RA procedure (ra_trigger = %i)\n", NR_UE_rrc_inst[module_id].ra_trigger); } else { LOG_D(RRC, "Trigger contention-based RA procedure (ra_trigger = %i)\n", NR_UE_rrc_inst[module_id].ra_trigger); } } } return 0; } int8_t nr_rrc_ue_generate_ra_msg(module_id_t module_id, uint8_t gNB_index) { switch(NR_UE_rrc_inst[module_id].ra_trigger){ case INITIAL_ACCESS_FROM_RRC_IDLE: nr_rrc_ue_generate_RRCSetupRequest(module_id,gNB_index); break; case RRC_CONNECTION_REESTABLISHMENT: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); break; case DURING_HANDOVER: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); break; case NON_SYNCHRONISED: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); break; case TRANSITION_FROM_RRC_INACTIVE: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); break; case TO_ESTABLISH_TA: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); break; case REQUEST_FOR_OTHER_SI: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); break; case BEAM_FAILURE_RECOVERY: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); break; default: AssertFatal(1==0, "Invalid ra_trigger value!\n"); break; } return 0; } /*brief decode SIB1 message*/ int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) { NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_BCCH_DL_SCH_Message, (void **)&bcch_message, (const void *)bufferP, buffer_len); if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) { LOG_D(RRC,"NR_BCCH_DL_SCH decode error\n"); SEQUENCE_free( &asn_DEF_NR_BCCH_DL_SCH_Message, (void *)bcch_message, 1 ); return -1; } else { NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index]; if(sib1 != NULL){ SEQUENCE_free(&asn_DEF_NR_BCCH_BCH_Message, (void *)sib1, 1 ); } sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1; if (*(int64_t*)sib1 != 1) { LOG_D(RRC, "SIB1 address: %lx\n", *(int64_t*)sib1); if( g_log->log_component[RRC].level >= OAILOG_DEBUG ) xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1); // FIXME: fix condition for the RA trigger check_requested_SI_List(module_id, NR_UE_rrc_inst[module_id].requested_SI_List, *sib1); if( nr_rrc_get_state(module_id) == RRC_STATE_IDLE_NR ) { NR_UE_rrc_inst[module_id].ra_trigger = INITIAL_ACCESS_FROM_RRC_IDLE; get_softmodem_params()->do_ra = 1; } nr_rrc_ue_generate_ra_msg(module_id,gNB_index); } else LOG_E(PHY, "sib1 is starting by 8 times 0\n"); } return 0; } // from NR SRB3 int8_t nr_rrc_ue_decode_NR_DL_DCCH_Message( const module_id_t module_id, const uint8_t gNB_index, const uint8_t *bufferP, const uint32_t buffer_len ){ // uper_decode by nr R15 rrc_connection_reconfiguration int32_t i; NR_DL_DCCH_Message_t *nr_dl_dcch_msg = NULL; MessageDef *msg_p; asn_dec_rval_t dec_rval = uper_decode( NULL, &asn_DEF_NR_DL_DCCH_Message, (void**)&nr_dl_dcch_msg, (uint8_t *)bufferP, buffer_len, 0, 0); if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) { for (i=0; i<buffer_len; i++) printf("%02x ",bufferP[i]); printf("\n"); // free the memory SEQUENCE_free( &asn_DEF_NR_DL_DCCH_Message, (void *)nr_dl_dcch_msg, 1 ); return -1; } if(nr_dl_dcch_msg != NULL){ switch(nr_dl_dcch_msg->message.present){ case NR_DL_DCCH_MessageType_PR_c1: switch(nr_dl_dcch_msg->message.choice.c1->present){ case NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration: nr_rrc_ue_process_rrcReconfiguration(module_id,nr_dl_dcch_msg->message.choice.c1->choice.rrcReconfiguration); break; case NR_DL_DCCH_MessageType__c1_PR_NOTHING: case NR_DL_DCCH_MessageType__c1_PR_rrcResume: case NR_DL_DCCH_MessageType__c1_PR_rrcRelease: msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_CONN_RELEASE_IND); if((nr_dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.present == NR_RRCRelease__criticalExtensions_PR_rrcRelease) && (nr_dl_dcch_msg->message.choice.c1->present == NR_DL_DCCH_MessageType__c1_PR_rrcRelease)){ nr_dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.choice.rrcRelease->deprioritisationReq->deprioritisationTimer = NR_RRCRelease_IEs__deprioritisationReq__deprioritisationTimer_min5; nr_dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.choice.rrcRelease->deprioritisationReq->deprioritisationType = NR_RRCRelease_IEs__deprioritisationReq__deprioritisationType_frequency; } itti_send_msg_to_task(TASK_RRC_NRUE,module_id,msg_p); break; case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment: case NR_DL_DCCH_MessageType__c1_PR_securityModeCommand: case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: case NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry: case NR_DL_DCCH_MessageType__c1_PR_counterCheck: case NR_DL_DCCH_MessageType__c1_PR_mobilityFromNRCommand: case NR_DL_DCCH_MessageType__c1_PR_dlDedicatedMessageSegment_r16: case NR_DL_DCCH_MessageType__c1_PR_ueInformationRequest_r16: case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransferMRDC_r16: case NR_DL_DCCH_MessageType__c1_PR_loggedMeasurementConfiguration_r16: case NR_DL_DCCH_MessageType__c1_PR_spare3: case NR_DL_DCCH_MessageType__c1_PR_spare2: case NR_DL_DCCH_MessageType__c1_PR_spare1: default: // not supported or unused break; } break; case NR_DL_DCCH_MessageType_PR_NOTHING: case NR_DL_DCCH_MessageType_PR_messageClassExtension: default: // not supported or unused break; } // release memory allocation SEQUENCE_free( &asn_DEF_NR_DL_DCCH_Message, (void *)nr_dl_dcch_msg, 1 ); }else{ // log.. } return 0; } //----------------------------------------------------------------------------- void nr_rrc_ue_process_securityModeCommand( const protocol_ctxt_t *const ctxt_pP, NR_SecurityModeCommand_t *const securityModeCommand, const uint8_t gNB_index ) //----------------------------------------------------------------------------- { asn_enc_rval_t enc_rval; NR_UL_DCCH_Message_t ul_dcch_msg; uint8_t buffer[200]; int i, securityMode; LOG_I(NR_RRC,"[UE %d] SFN/SF %d/%d: Receiving from SRB1 (DL-DCCH), Processing securityModeCommand (eNB %d)\n", ctxt_pP->module_id,ctxt_pP->frame, ctxt_pP->subframe, gNB_index); switch (securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm) { case NR_CipheringAlgorithm_nea0: LOG_I(NR_RRC,"[UE %d] Security algorithm is set to nea0\n", ctxt_pP->module_id); securityMode= NR_CipheringAlgorithm_nea0; break; case NR_CipheringAlgorithm_nea1: LOG_I(NR_RRC,"[UE %d] Security algorithm is set to nea1\n",ctxt_pP->module_id); securityMode= NR_CipheringAlgorithm_nea1; break; case NR_CipheringAlgorithm_nea2: LOG_I(NR_RRC,"[UE %d] Security algorithm is set to nea2\n", ctxt_pP->module_id); securityMode = NR_CipheringAlgorithm_nea2; break; default: LOG_I(NR_RRC,"[UE %d] Security algorithm is set to none\n",ctxt_pP->module_id); securityMode = NR_CipheringAlgorithm_spare1; break; } switch (*securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm) { case NR_IntegrityProtAlgorithm_nia1: LOG_I(NR_RRC,"[UE %d] Integrity protection algorithm is set to nia1\n",ctxt_pP->module_id); securityMode |= 1 << 5; break; case NR_IntegrityProtAlgorithm_nia2: LOG_I(NR_RRC,"[UE %d] Integrity protection algorithm is set to nia2\n",ctxt_pP->module_id); securityMode |= 1 << 6; break; default: LOG_I(NR_RRC,"[UE %d] Integrity protection algorithm is set to none\n",ctxt_pP->module_id); securityMode |= 0x70 ; break; } LOG_D(NR_RRC,"[UE %d] security mode is %x \n",ctxt_pP->module_id, securityMode); NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm = securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm; NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm = *securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm; memset((void *)&ul_dcch_msg,0,sizeof(NR_UL_DCCH_Message_t)); //memset((void *)&SecurityModeCommand,0,sizeof(SecurityModeCommand_t)); ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; ul_dcch_msg.message.choice.c1 = calloc(1, sizeof(*ul_dcch_msg.message.choice.c1)); if (securityMode >= NO_SECURITY_MODE) { LOG_I(NR_RRC, "rrc_ue_process_securityModeCommand, security mode complete case \n"); ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete; } else { LOG_I(NR_RRC, "rrc_ue_process_securityModeCommand, security mode failure case \n"); ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeFailure; } uint8_t *kRRCenc = NULL; uint8_t *kUPenc = NULL; uint8_t *kRRCint = NULL; pdcp_t *pdcp_p = NULL; hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE; hashtable_rc_t h_rc; key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, DCCH, SRB_FLAG_YES); h_rc = hashtable_get(pdcp_coll_p, key, (void **) &pdcp_p); if (h_rc == HASH_TABLE_OK) { LOG_D(NR_RRC, "PDCP_COLL_KEY_VALUE() returns valid key = %ld\n", key); LOG_D(NR_RRC, "driving kRRCenc, kRRCint and kUPenc from KgNB=" "%02x%02x%02x%02x" "%02x%02x%02x%02x" "%02x%02x%02x%02x" "%02x%02x%02x%02x" "%02x%02x%02x%02x" "%02x%02x%02x%02x" "%02x%02x%02x%02x" "%02x%02x%02x%02x\n", NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[0], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[1], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[2], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[3], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[4], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[5], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[6], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[7], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[8], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[9], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[10], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[11], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[12], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[13], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[14], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[15], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[16], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[17], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[18], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[19], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[20], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[21], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[22], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[23], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[24], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[25], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[26], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[27], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[28], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[29], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[30], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[31]); derive_key_rrc_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, &kRRCenc); derive_key_rrc_int(NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm,NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, &kRRCint); derive_key_up_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, &kUPenc); if (securityMode != 0xff) { pdcp_config_set_security(ctxt_pP, pdcp_p, 0, 0, NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm | (NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm << 4), kRRCenc, kRRCint, kUPenc); } else { LOG_I(NR_RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x", securityMode); } } else { LOG_I(NR_RRC, "Could not get PDCP instance where key=0x%ld\n", key); } if (securityModeCommand->criticalExtensions.present == NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand) { ul_dcch_msg.message.choice.c1->choice.securityModeComplete = CALLOC(1, sizeof(NR_SecurityModeComplete_t)); ul_dcch_msg.message.choice.c1->choice.securityModeComplete->rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier; ul_dcch_msg.message.choice.c1->choice.securityModeComplete->criticalExtensions.present = NR_SecurityModeComplete__criticalExtensions_PR_securityModeComplete; ul_dcch_msg.message.choice.c1->choice.securityModeComplete->criticalExtensions.choice.securityModeComplete = CALLOC(1, sizeof(NR_SecurityModeComplete_IEs_t)); ul_dcch_msg.message.choice.c1->choice.securityModeComplete->criticalExtensions.choice.securityModeComplete->nonCriticalExtension =NULL; LOG_I(NR_RRC,"[UE %d] SFN/SF %d/%d: Receiving from SRB1 (DL-DCCH), encoding securityModeComplete (gNB %d), rrc_TransactionIdentifier: %ld\n", ctxt_pP->module_id,ctxt_pP->frame, ctxt_pP->subframe, gNB_index, securityModeCommand->rrc_TransactionIdentifier); enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, 100); AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); } LOG_D(NR_RRC, "securityModeComplete Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded+7)/8); for (i = 0; i < (enc_rval.encoded + 7) / 8; i++) { LOG_T(NR_RRC, "%02x.", buffer[i]); } LOG_T(NR_RRC, "\n"); #ifdef ITTI_SIM MessageDef *message_p; uint8_t *message_buffer; message_buffer = itti_malloc (TASK_RRC_UE_SIM,TASK_RRC_GNB_SIM, (enc_rval.encoded + 7) / 8); memcpy (message_buffer, buffer, (enc_rval.encoded + 7) / 8); message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, 0, UE_RRC_DCCH_DATA_IND); GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; GNB_RRC_DCCH_DATA_IND (message_p).size = (enc_rval.encoded + 7) / 8; itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); #else rrc_data_req ( ctxt_pP, DCCH, nr_rrc_mui++, SDU_CONFIRM_NO, (enc_rval.encoded + 7) / 8, buffer, PDCP_TRANSMISSION_MODE_CONTROL); #endif } else LOG_W(NR_RRC,"securityModeCommand->criticalExtensions.present (%d) != NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand\n", securityModeCommand->criticalExtensions.present); } //----------------------------------------------------------------------------- void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index ) { uint8_t i=0,rv[6]; if(NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size ==0) { // Get RRCConnectionRequest, fill random for now // Generate random byte stream for contention resolution for (i=0; i<6; i++) { #ifdef SMBV // if SMBV is configured the contention resolution needs to be fix for the connection procedure to succeed rv[i]=i; #else rv[i]=taus()&0xff; #endif LOG_T(NR_RRC,"%x.",rv[i]); } LOG_T(NR_RRC,"\n"); NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size = do_RRCSetupRequest( module_id, (uint8_t *)NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.Payload, rv); LOG_I(NR_RRC,"[UE %d] : Logical Channel UL-CCCH (SRB0), Generating RRCSetupRequest (bytes %d, gNB %d)\n", module_id, NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index); for (i=0; i<NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size; i++) { LOG_T(NR_RRC,"%x.",NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.Payload[i]); } LOG_T(NR_RRC,"\n"); /*UE_rrc_inst[ue_mod_idP].Srb0[Idx].Tx_buffer.Payload[i] = taus()&0xff; UE_rrc_inst[ue_mod_idP].Srb0[Idx].Tx_buffer.payload_size =i; */ #ifdef ITTI_SIM MessageDef *message_p; uint8_t *message_buffer; message_buffer = itti_malloc (TASK_RRC_UE_SIM,TASK_RRC_GNB_SIM, NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size); memcpy (message_buffer, (uint8_t*)NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload, NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size); message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, 0, UE_RRC_CCCH_DATA_IND); GNB_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; GNB_RRC_CCCH_DATA_IND (message_p).size = NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size; itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); #endif } } //----------------------------------------------------------------------------- int32_t nr_rrc_ue_establish_srb1( module_id_t ue_mod_idP, frame_t frameP, uint8_t gNB_index, NR_SRB_ToAddMod_t *SRB_config ) //----------------------------------------------------------------------------- { // add descriptor from RRC PDU NR_UE_rrc_inst[ue_mod_idP].Srb1[gNB_index].Active = 1; NR_UE_rrc_inst[ue_mod_idP].Srb1[gNB_index].Status = RADIO_CONFIG_OK;//RADIO CFG NR_UE_rrc_inst[ue_mod_idP].Srb1[gNB_index].Srb_info.Srb_id = 1; LOG_I(NR_RRC, "[UE %d], CONFIG_SRB1 %d corresponding to gNB_index %d\n", ue_mod_idP, DCCH, gNB_index); return(0); } //----------------------------------------------------------------------------- int32_t nr_rrc_ue_establish_srb2( module_id_t ue_mod_idP, frame_t frameP, uint8_t gNB_index, NR_SRB_ToAddMod_t *SRB_config ) //----------------------------------------------------------------------------- { // add descriptor from RRC PDU NR_UE_rrc_inst[ue_mod_idP].Srb2[gNB_index].Active = 1; NR_UE_rrc_inst[ue_mod_idP].Srb2[gNB_index].Status = RADIO_CONFIG_OK;//RADIO CFG NR_UE_rrc_inst[ue_mod_idP].Srb2[gNB_index].Srb_info.Srb_id = 2; LOG_I(NR_RRC, "[UE %d], CONFIG_SRB2 %d corresponding to gNB_index %d\n", ue_mod_idP, DCCH1, gNB_index); return(0); } //----------------------------------------------------------------------------- int32_t nr_rrc_ue_establish_drb( module_id_t ue_mod_idP, frame_t frameP, uint8_t gNB_index, NR_DRB_ToAddMod_t *DRB_config ) //----------------------------------------------------------------------------- { // add descriptor from RRC PDU int oip_ifup = 0, ip_addr_offset3 = 0, ip_addr_offset4 = 0; /* avoid gcc warnings */ (void)oip_ifup; (void)ip_addr_offset3; (void)ip_addr_offset4; LOG_I(NR_RRC,"[UE %d] Frame %d: processing RRCReconfiguration: reconfiguring DRB %ld\n", ue_mod_idP, frameP, DRB_config->drb_Identity); if(!AMF_MODE_ENABLED) { ip_addr_offset3 = 0; ip_addr_offset4 = 1; LOG_I(OIP, "[UE %d] trying to bring up the OAI interface %d, IP X.Y.%d.%d\n", ue_mod_idP, ip_addr_offset3+ue_mod_idP, ip_addr_offset3+ue_mod_idP+1, ip_addr_offset4+ue_mod_idP+1); oip_ifup = nas_config(ip_addr_offset3+ue_mod_idP+1, // interface_id UE_NAS_USE_TUN?1:(ip_addr_offset3+ue_mod_idP+1), // third_octet ip_addr_offset4+ue_mod_idP+1, // fourth_octet "oip"); // interface suffix (when using kernel module) if (oip_ifup == 0 && (!UE_NAS_USE_TUN)) { // interface is up --> send a config the DRB LOG_I(OIP, "[UE %d] Config the ue net interface %d to send/receive pkt on DRB %ld to/from the protocol stack\n", ue_mod_idP, ip_addr_offset3+ue_mod_idP, (long int)((gNB_index * NR_maxDRB) + DRB_config->drb_Identity)); rb_conf_ipv4(0,//add ue_mod_idP,//cx align with the UE index ip_addr_offset3+ue_mod_idP,//inst num_enb+ue_index (gNB_index * NR_maxDRB) + DRB_config->drb_Identity,//rb 0,//dscp ipv4_address(ip_addr_offset3+ue_mod_idP+1, ip_addr_offset4+ue_mod_idP+1),//saddr ipv4_address(ip_addr_offset3+ue_mod_idP+1, gNB_index+1));//daddr LOG_D(NR_RRC,"[UE %d] State = Attached (gNB %d)\n",ue_mod_idP,gNB_index); } } return(0); } //----------------------------------------------------------------------------- void nr_rrc_ue_process_measConfig( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index, NR_MeasConfig_t *const measConfig ) //----------------------------------------------------------------------------- { int i; long ind; NR_MeasObjectToAddMod_t *measObj = NULL; NR_ReportConfigToAddMod_t *reportConfig = NULL; if (measConfig->measObjectToRemoveList != NULL) { for (i = 0; i < measConfig->measObjectToRemoveList->list.count; i++) { ind = *measConfig->measObjectToRemoveList->list.array[i]; free(NR_UE_rrc_inst[ctxt_pP->module_id].MeasObj[gNB_index][ind-1]); } } if (measConfig->measObjectToAddModList != NULL) { LOG_I(NR_RRC, "Measurement Object List is present\n"); for (i = 0; i < measConfig->measObjectToAddModList->list.count; i++) { measObj = measConfig->measObjectToAddModList->list.array[i]; ind = measConfig->measObjectToAddModList->list.array[i]->measObjectId; if (NR_UE_rrc_inst[ctxt_pP->module_id].MeasObj[gNB_index][ind-1]) { LOG_D(NR_RRC, "Modifying measurement object %ld\n",ind); memcpy((char *)NR_UE_rrc_inst[ctxt_pP->module_id].MeasObj[gNB_index][ind-1], (char *)measObj, sizeof(NR_MeasObjectToAddMod_t)); } else { LOG_I(NR_RRC, "Adding measurement object %ld\n", ind); if (measObj->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) { NR_UE_rrc_inst[ctxt_pP->module_id].MeasObj[gNB_index][ind-1]=measObj; } } } LOG_I(NR_RRC, "call rrc_mac_config_req \n"); // rrc_mac_config_req_ue } if (measConfig->reportConfigToRemoveList != NULL) { for (i = 0; i < measConfig->reportConfigToRemoveList->list.count; i++) { ind = *measConfig->reportConfigToRemoveList->list.array[i]; free(NR_UE_rrc_inst[ctxt_pP->module_id].ReportConfig[gNB_index][ind-1]); } } if (measConfig->reportConfigToAddModList != NULL) { LOG_I(NR_RRC,"Report Configuration List is present\n"); for (i = 0; i < measConfig->reportConfigToAddModList->list.count; i++) { ind = measConfig->reportConfigToAddModList->list.array[i]->reportConfigId; reportConfig = measConfig->reportConfigToAddModList->list.array[i]; if (NR_UE_rrc_inst[ctxt_pP->module_id].ReportConfig[gNB_index][ind-1]) { LOG_I(NR_RRC, "Modifying Report Configuration %ld\n", ind-1); memcpy((char *)NR_UE_rrc_inst[ctxt_pP->module_id].ReportConfig[gNB_index][ind-1], (char *)measConfig->reportConfigToAddModList->list.array[i], sizeof(NR_ReportConfigToAddMod_t)); } else { LOG_D(RRC,"Adding Report Configuration %ld %p \n", ind-1, measConfig->reportConfigToAddModList->list.array[i]); if (reportConfig->reportConfig.present == NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR) { NR_UE_rrc_inst[ctxt_pP->module_id].ReportConfig[gNB_index][ind-1] = measConfig->reportConfigToAddModList->list.array[i]; } } } } if (measConfig->measIdToRemoveList != NULL) { for (i = 0; i < measConfig->measIdToRemoveList->list.count; i++) { ind = *measConfig->measIdToRemoveList->list.array[i]; free(NR_UE_rrc_inst[ctxt_pP->module_id].MeasId[gNB_index][ind-1]); } } if (measConfig->measIdToAddModList != NULL) { for (i = 0; i < measConfig->measIdToAddModList->list.count; i++) { ind = measConfig->measIdToAddModList->list.array[i]->measId; if (NR_UE_rrc_inst[ctxt_pP->module_id].MeasId[gNB_index][ind-1]) { LOG_D(NR_RRC, "Modifying Measurement ID %ld\n",ind-1); memcpy((char *)NR_UE_rrc_inst[ctxt_pP->module_id].MeasId[gNB_index][ind-1], (char *)measConfig->measIdToAddModList->list.array[i], sizeof(NR_MeasIdToAddMod_t)); } else { LOG_D(NR_RRC, "Adding Measurement ID %ld %p\n", ind-1, measConfig->measIdToAddModList->list.array[i]); NR_UE_rrc_inst[ctxt_pP->module_id].MeasId[gNB_index][ind-1] = measConfig->measIdToAddModList->list.array[i]; } } } if (measConfig->quantityConfig != NULL) { if (NR_UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[gNB_index]) { LOG_D(RRC,"Modifying Quantity Configuration \n"); memcpy((char *)NR_UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[gNB_index], (char *)measConfig->quantityConfig, sizeof(NR_QuantityConfig_t)); } else { LOG_D(NR_RRC, "Adding Quantity configuration\n"); NR_UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[gNB_index] = measConfig->quantityConfig; } } if (measConfig->measGapConfig != NULL) { if (NR_UE_rrc_inst[ctxt_pP->module_id].measGapConfig[gNB_index]) { memcpy((char *)NR_UE_rrc_inst[ctxt_pP->module_id].measGapConfig[gNB_index], (char *)measConfig->measGapConfig, sizeof(NR_MeasGapConfig_t)); } else { NR_UE_rrc_inst[ctxt_pP->module_id].measGapConfig[gNB_index] = measConfig->measGapConfig; } } if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_ssb_RSRP) { NR_UE_rrc_inst[ctxt_pP->module_id].s_measure = measConfig->s_MeasureConfig->choice.ssb_RSRP; } else if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_csi_RSRP) { NR_UE_rrc_inst[ctxt_pP->module_id].s_measure = measConfig->s_MeasureConfig->choice.csi_RSRP; } } //----------------------------------------------------------------------------- void nr_sa_rrc_ue_process_radioBearerConfig( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index, NR_RadioBearerConfig_t *const radioBearerConfig ) //----------------------------------------------------------------------------- { long SRB_id, DRB_id; int i, cnt; if( radioBearerConfig->srb3_ToRelease != NULL){ if( *radioBearerConfig->srb3_ToRelease == TRUE){ //TODO (release the PDCP entity and the srb-Identity of the SRB3.) } } if (radioBearerConfig->srb_ToAddModList != NULL) { if (radioBearerConfig->securityConfig != NULL) { if (*radioBearerConfig->securityConfig->keyToUse == NR_SecurityConfig__keyToUse_master) { NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm = radioBearerConfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm; NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm = *radioBearerConfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm; } } uint8_t *kRRCenc = NULL; uint8_t *kRRCint = NULL; derive_key_rrc_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm, NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, &kRRCenc); derive_key_rrc_int(NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm, NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, &kRRCint); // Refresh SRBs // nr_rrc_pdcp_config_asn1_req(ctxt_pP, // radioBearerConfig->srb_ToAddModList, // NULL, // NULL, // NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm | // (NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm << 4), // kRRCenc, // kRRCint, // NULL, // NULL, // NULL, // NULL); // Refresh SRBs // nr_rrc_rlc_config_asn1_req(ctxt_pP, // radioBearerConfig->srb_ToAddModList, // NULL, // NULL, // NULL, // NULL // ); for (cnt = 0; cnt < radioBearerConfig->srb_ToAddModList->list.count; cnt++) { SRB_id = radioBearerConfig->srb_ToAddModList->list.array[cnt]->srb_Identity; LOG_D(NR_RRC,"[UE %d]: Frame %d SRB config cnt %d (SRB%ld)\n", ctxt_pP->module_id, ctxt_pP->frame, cnt, SRB_id); if (SRB_id == 1) { if (NR_UE_rrc_inst[ctxt_pP->module_id].SRB1_config[gNB_index]) { memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].SRB1_config[gNB_index], radioBearerConfig->srb_ToAddModList->list.array[cnt], sizeof(NR_SRB_ToAddMod_t)); } else { NR_UE_rrc_inst[ctxt_pP->module_id].SRB1_config[gNB_index] = radioBearerConfig->srb_ToAddModList->list.array[cnt]; nr_rrc_ue_establish_srb1(ctxt_pP->module_id, ctxt_pP->frame, gNB_index, radioBearerConfig->srb_ToAddModList->list.array[cnt]); LOG_I(NR_RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (SRB1 gNB %d) --->][MAC_UE][MOD %02d][]\n", ctxt_pP->frame, ctxt_pP->module_id, gNB_index, ctxt_pP->module_id); // rrc_mac_config_req_ue } } else { if (NR_UE_rrc_inst[ctxt_pP->module_id].SRB2_config[gNB_index]) { memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].SRB2_config[gNB_index], radioBearerConfig->srb_ToAddModList->list.array[cnt], sizeof(NR_SRB_ToAddMod_t)); } else { NR_UE_rrc_inst[ctxt_pP->module_id].SRB2_config[gNB_index] = radioBearerConfig->srb_ToAddModList->list.array[cnt]; nr_rrc_ue_establish_srb2(ctxt_pP->module_id, ctxt_pP->frame, gNB_index, radioBearerConfig->srb_ToAddModList->list.array[cnt]); LOG_I(NR_RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (SRB2 gNB %d) --->][MAC_UE][MOD %02d][]\n", ctxt_pP->frame, ctxt_pP->module_id, gNB_index, ctxt_pP->module_id); // rrc_mac_config_req_ue } } // srb2 } } // srb_ToAddModList // Establish DRBs if present if (radioBearerConfig->drb_ToAddModList != NULL) { if ((NR_UE_rrc_inst[ctxt_pP->module_id].defaultDRB == NULL) && (radioBearerConfig->drb_ToAddModList->list.count >= 1)) { NR_UE_rrc_inst[ctxt_pP->module_id].defaultDRB = malloc(sizeof(rb_id_t)); *NR_UE_rrc_inst[ctxt_pP->module_id].defaultDRB = radioBearerConfig->drb_ToAddModList->list.array[0]->drb_Identity; } for (cnt = 0; cnt < radioBearerConfig->drb_ToAddModList->list.count; cnt++) { DRB_id = radioBearerConfig->drb_ToAddModList->list.array[cnt]->drb_Identity; if (NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]) { memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1], radioBearerConfig->drb_ToAddModList->list.array[cnt], sizeof(NR_DRB_ToAddMod_t)); } else { LOG_D(NR_RRC, "Adding DRB %ld %p\n", DRB_id-1, radioBearerConfig->drb_ToAddModList->list.array[cnt]); NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1] = radioBearerConfig->drb_ToAddModList->list.array[cnt]; } } uint8_t *kUPenc = NULL; derive_key_up_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm, NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, &kUPenc); MSC_LOG_TX_MESSAGE( MSC_RRC_UE, MSC_PDCP_UE, NULL, 0, MSC_AS_TIME_FMT" CONFIG_REQ UE %x DRB (security %X)", MSC_AS_TIME_ARGS(ctxt_pP), ctxt_pP->rnti, NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm | (NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm << 4)); // Refresh DRBs // nr_rrc_pdcp_config_asn1_req(ctxt_pP, // NULL, // radioBearerConfig->drb_ToAddModList, // NULL, // NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm | // (NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm << 4), // NULL, // NULL, // kUPenc, // NULL, // NR_UE_rrc_inst[ctxt_pP->module_id].defaultDRB, // NULL); // Refresh DRBs // nr_rrc_rlc_config_asn1_req(ctxt_pP, // NULL, // radioBearerConfig->drb_ToAddModList, // NULL, // NULL, // NULL // ); } // drb_ToAddModList if (radioBearerConfig->drb_ToReleaseList != NULL) { for (i = 0; i < radioBearerConfig->drb_ToReleaseList->list.count; i++) { DRB_id = *radioBearerConfig->drb_ToReleaseList->list.array[i]; free(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]); } } NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State = NR_RRC_CONNECTED; LOG_I(NR_RRC,"[UE %d] State = NR_RRC_CONNECTED (gNB %d)\n", ctxt_pP->module_id, gNB_index); } //----------------------------------------------------------------------------- void rrc_ue_process_rrcReconfiguration( const protocol_ctxt_t *const ctxt_pP, NR_RRCReconfiguration_t *rrcReconfiguration, uint8_t gNB_index ) //----------------------------------------------------------------------------- { LOG_I(NR_RRC, "[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), Processing RRCReconfiguration (gNB %d)\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index); NR_RRCReconfiguration_IEs_t *ie = NULL; if (rrcReconfiguration->criticalExtensions.present == NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration) { ie = rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration; if (ie->measConfig != NULL) { LOG_I(NR_RRC, "Measurement Configuration is present\n"); nr_rrc_ue_process_measConfig(ctxt_pP, gNB_index, ie->measConfig); } if (ie->radioBearerConfig != NULL) { LOG_I(NR_RRC, "radio Bearer Configuration is present\n"); nr_sa_rrc_ue_process_radioBearerConfig(ctxt_pP, gNB_index, ie->radioBearerConfig); } /* Check if there is dedicated NAS information to forward to NAS */ if (ie->nonCriticalExtension->dedicatedNAS_MessageList != NULL) { int list_count; uint32_t pdu_length; uint8_t *pdu_buffer; MessageDef *msg_p; for (list_count = 0; list_count < ie->nonCriticalExtension->dedicatedNAS_MessageList->list.count; list_count++) { pdu_length = ie->nonCriticalExtension->dedicatedNAS_MessageList->list.array[list_count]->size; pdu_buffer = ie->nonCriticalExtension->dedicatedNAS_MessageList->list.array[list_count]->buf; msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, NAS_CONN_ESTABLI_CNF); NAS_CONN_ESTABLI_CNF(msg_p).errCode = AS_SUCCESS; NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length = pdu_length; NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.data = pdu_buffer; itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); } free (ie->nonCriticalExtension->dedicatedNAS_MessageList); } } } //----------------------------------------------------------------------------- void nr_rrc_ue_generate_RRCReconfigurationComplete( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index, const uint8_t Transaction_id ) { uint8_t buffer[32], size; size = do_NR_RRCReconfigurationComplete(ctxt_pP, buffer, Transaction_id); LOG_I(NR_RRC,PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel UL-DCCH (SRB1), Generating RRCReconfigurationComplete (bytes %d, gNB_index %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), size, gNB_index); LOG_D(RLC, "[FRAME %05d][RRC_UE][INST %02d][][--- PDCP_DATA_REQ/%d Bytes (RRCReconfigurationComplete to gNB %d MUI %d) --->][PDCP][INST %02d][RB %02d]\n", ctxt_pP->frame, UE_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), size, gNB_index, nr_rrc_mui, UE_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), DCCH); #ifdef ITTI_SIM MessageDef *message_p; uint8_t *message_buffer; message_buffer = itti_malloc (TASK_RRC_UE_SIM,TASK_RRC_GNB_SIM,size); memcpy (message_buffer, buffer, size); message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, 0, UE_RRC_DCCH_DATA_IND); UE_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; UE_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; UE_RRC_DCCH_DATA_IND (message_p).size = size; itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); #else rrc_data_req_ue ( ctxt_pP, DCCH, nr_rrc_mui++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); #endif } // from NR SRB1 //----------------------------------------------------------------------------- int nr_rrc_ue_decode_dcch( const protocol_ctxt_t *const ctxt_pP, const srb_id_t Srb_id, const uint8_t *const Buffer, const uint8_t gNB_indexP ) //----------------------------------------------------------------------------- { asn_dec_rval_t dec_rval; NR_DL_DCCH_Message_t *dl_dcch_msg = NULL; MessageDef *msg_p; if (Srb_id != 1) { LOG_E(NR_RRC,"[UE %d] Frame %d: Received message on DL-DCCH (SRB%ld), should not have ...\n", ctxt_pP->module_id, ctxt_pP->frame, Srb_id); return -1; } else { LOG_D(NR_RRC, "Received message on SRB%ld\n", Srb_id); } LOG_D(NR_RRC, "Decoding DL-DCCH Message\n"); dec_rval = uper_decode( NULL, &asn_DEF_NR_DL_DCCH_Message, (void **)&dl_dcch_msg, Buffer, RRC_BUF_SIZE, 0, 0); if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { LOG_E(NR_RRC, "Failed to decode DL-DCCH (%zu bytes)\n", dec_rval.consumed); return -1; } // if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message,(void *)dl_dcch_msg); // } if (dl_dcch_msg->message.present == NR_DL_DCCH_MessageType_PR_c1) { switch (dl_dcch_msg->message.choice.c1->present) { case NR_DL_DCCH_MessageType__c1_PR_NOTHING: LOG_I(NR_RRC, "Received PR_NOTHING on DL-DCCH-Message\n"); break; case NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration: rrc_ue_process_rrcReconfiguration(ctxt_pP, dl_dcch_msg->message.choice.c1->choice.rrcReconfiguration, gNB_indexP); nr_rrc_ue_generate_RRCReconfigurationComplete(ctxt_pP, gNB_indexP, dl_dcch_msg->message.choice.c1->choice.rrcReconfiguration->rrc_TransactionIdentifier); break; case NR_DL_DCCH_MessageType__c1_PR_rrcResume: case NR_DL_DCCH_MessageType__c1_PR_rrcRelease: msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, NAS_CONN_RELEASE_IND); if((dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.present == NR_RRCRelease__criticalExtensions_PR_rrcRelease) && (dl_dcch_msg->message.choice.c1->present == NR_DL_DCCH_MessageType__c1_PR_rrcRelease)){ dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.choice.rrcRelease->deprioritisationReq->deprioritisationTimer = NR_RRCRelease_IEs__deprioritisationReq__deprioritisationTimer_min5; dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.choice.rrcRelease->deprioritisationReq->deprioritisationType = NR_RRCRelease_IEs__deprioritisationReq__deprioritisationType_frequency; } itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); break; case NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry: LOG_I(RRC, "[UE %d] Received Capability Enquiry (gNB %d)\n", ctxt_pP->module_id,gNB_indexP); nr_rrc_ue_process_ueCapabilityEnquiry( ctxt_pP, dl_dcch_msg->message.choice.c1->choice.ueCapabilityEnquiry, gNB_indexP); break; case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment: case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: case NR_DL_DCCH_MessageType__c1_PR_mobilityFromNRCommand: case NR_DL_DCCH_MessageType__c1_PR_dlDedicatedMessageSegment_r16: case NR_DL_DCCH_MessageType__c1_PR_ueInformationRequest_r16: case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransferMRDC_r16: case NR_DL_DCCH_MessageType__c1_PR_loggedMeasurementConfiguration_r16: case NR_DL_DCCH_MessageType__c1_PR_spare3: case NR_DL_DCCH_MessageType__c1_PR_spare2: case NR_DL_DCCH_MessageType__c1_PR_spare1: case NR_DL_DCCH_MessageType__c1_PR_counterCheck: break; case NR_DL_DCCH_MessageType__c1_PR_securityModeCommand: LOG_I(RRC, "[UE %d] Received securityModeCommand (gNB %d)\n", ctxt_pP->module_id, gNB_indexP); nr_rrc_ue_process_securityModeCommand( ctxt_pP, dl_dcch_msg->message.choice.c1->choice.securityModeCommand, gNB_indexP); break; } } return 0; } //----------------------------------------------------------------------------- void *rrc_nrue_task( void *args_p ) { MessageDef *msg_p; instance_t instance; unsigned int ue_mod_id; int result; NR_SRB_INFO *srb_info_p; protocol_ctxt_t ctxt; itti_mark_task_ready (TASK_RRC_NRUE); while(1) { // Wait for a message itti_receive_msg (TASK_RRC_NRUE, &msg_p); instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); ue_mod_id = UE_INSTANCE_TO_MODULE_ID(instance); switch (ITTI_MSG_ID(msg_p)) { case TERMINATE_MESSAGE: LOG_W(NR_RRC, " *** Exiting RRC thread\n"); itti_exit_task (); break; case MESSAGE_TEST: LOG_D(NR_RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); break; case NR_RRC_MAC_BCCH_DATA_IND: LOG_D(NR_RRC, "[UE %d] Received %s: frameP %d, gNB %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), NR_RRC_MAC_BCCH_DATA_IND (msg_p).frame, NR_RRC_MAC_BCCH_DATA_IND (msg_p).gnb_index); // PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_NO, NOT_A_RNTI, RRC_MAC_BCCH_DATA_IND (msg_p).frame, 0); PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NOT_A_RNTI, NR_RRC_MAC_BCCH_DATA_IND (msg_p).frame, 0,NR_RRC_MAC_BCCH_DATA_IND (msg_p).gnb_index); nr_decode_BCCH_DLSCH_Message (&ctxt, NR_RRC_MAC_BCCH_DATA_IND (msg_p).gnb_index, NR_RRC_MAC_BCCH_DATA_IND (msg_p).sdu, NR_RRC_MAC_BCCH_DATA_IND (msg_p).sdu_size, NR_RRC_MAC_BCCH_DATA_IND (msg_p).rsrq, NR_RRC_MAC_BCCH_DATA_IND (msg_p).rsrp); case NR_RRC_MAC_CCCH_DATA_IND: LOG_D(NR_RRC, "[UE %d] RNTI %x Received %s: frameP %d, gNB %d\n", ue_mod_id, NR_RRC_MAC_CCCH_DATA_IND (msg_p).rnti, ITTI_MSG_NAME (msg_p), NR_RRC_MAC_CCCH_DATA_IND (msg_p).frame, NR_RRC_MAC_CCCH_DATA_IND (msg_p).gnb_index); srb_info_p = &NR_UE_rrc_inst[ue_mod_id].Srb0[NR_RRC_MAC_CCCH_DATA_IND (msg_p).gnb_index]; memcpy (srb_info_p->Rx_buffer.Payload, NR_RRC_MAC_CCCH_DATA_IND (msg_p).sdu, NR_RRC_MAC_CCCH_DATA_IND (msg_p).sdu_size); srb_info_p->Rx_buffer.payload_size = NR_RRC_MAC_CCCH_DATA_IND (msg_p).sdu_size; // PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_NO, RRC_MAC_CCCH_DATA_IND (msg_p).rnti, RRC_MAC_CCCH_DATA_IND (msg_p).frame, 0); PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NR_RRC_MAC_CCCH_DATA_IND (msg_p).rnti, NR_RRC_MAC_CCCH_DATA_IND (msg_p).frame, 0, NR_RRC_MAC_CCCH_DATA_IND (msg_p).gnb_index); nr_rrc_ue_decode_ccch (&ctxt, srb_info_p, NR_RRC_MAC_CCCH_DATA_IND (msg_p).gnb_index); break; /* PDCP messages */ case NR_RRC_DCCH_DATA_IND: PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, NR_RRC_DCCH_DATA_IND (msg_p).module_id, GNB_FLAG_NO, NR_RRC_DCCH_DATA_IND (msg_p).rnti, NR_RRC_DCCH_DATA_IND (msg_p).frame, 0,NR_RRC_DCCH_DATA_IND (msg_p).gNB_index); LOG_D(NR_RRC, "[UE %d] Received %s: frameP %d, DCCH %d, gNB %d\n", NR_RRC_DCCH_DATA_IND (msg_p).module_id, ITTI_MSG_NAME (msg_p), NR_RRC_DCCH_DATA_IND (msg_p).frame, NR_RRC_DCCH_DATA_IND (msg_p).dcch_index, NR_RRC_DCCH_DATA_IND (msg_p).gNB_index); LOG_D(NR_RRC, PROTOCOL_RRC_CTXT_UE_FMT"Received %s DCCH %d, gNB %d\n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(&ctxt), ITTI_MSG_NAME (msg_p), NR_RRC_DCCH_DATA_IND (msg_p).dcch_index, NR_RRC_DCCH_DATA_IND (msg_p).gNB_index); nr_rrc_ue_decode_dcch ( &ctxt, NR_RRC_DCCH_DATA_IND (msg_p).dcch_index, NR_RRC_DCCH_DATA_IND (msg_p).sdu_p, NR_RRC_DCCH_DATA_IND (msg_p).gNB_index); break; default: LOG_E(NR_RRC, "[UE %d] Received unexpected message %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); break; } LOG_I(NR_RRC, "[UE %d] RRC Status %d\n", ue_mod_id, nr_rrc_get_state(ue_mod_id)); result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); msg_p = NULL; } } void nr_rrc_ue_process_sidelink_radioResourceConfig( module_id_t Mod_idP, uint8_t gNB_index, NR_SetupRelease_SL_ConfigDedicatedNR_r16_t *sl_ConfigDedicatedNR ) { //process sl_CommConfig, configure MAC/PHY for transmitting SL communication (RRC_CONNECTED) if (sl_ConfigDedicatedNR != NULL) { switch (sl_ConfigDedicatedNR->present){ case NR_SetupRelease_SL_ConfigDedicatedNR_r16_PR_setup: //TODO break; case NR_SetupRelease_SL_ConfigDedicatedNR_r16_PR_release: break; case NR_SetupRelease_SL_ConfigDedicatedNR_r16_PR_NOTHING: break; default: break; } } } //----------------------------------------------------------------------------- void nr_rrc_ue_process_ueCapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, NR_UECapabilityEnquiry_t *UECapabilityEnquiry, uint8_t gNB_index ) //----------------------------------------------------------------------------- { asn_enc_rval_t enc_rval; NR_UL_DCCH_Message_t ul_dcch_msg; NR_UE_CapabilityRAT_Container_t ue_CapabilityRAT_Container; uint8_t buffer[200]; int i; LOG_I(RRC,"[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), Processing UECapabilityEnquiry (gNB %d)\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index); memset((void *)&ul_dcch_msg,0,sizeof(NR_UL_DCCH_Message_t)); memset((void *)&ue_CapabilityRAT_Container,0,sizeof(NR_UE_CapabilityRAT_Container_t)); ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; ul_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_UL_DCCH_MessageType__c1)); ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation; ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation = CALLOC(1, sizeof(struct NR_UECapabilityInformation)); ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->rrc_TransactionIdentifier = UECapabilityEnquiry->rrc_TransactionIdentifier; ue_CapabilityRAT_Container.rat_Type = NR_RAT_Type_nr; NR_UE_NR_Capability_t* UE_Capability_nr; UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t)); NR_BandNR_t *nr_bandnr; nr_bandnr = CALLOC(1,sizeof(NR_BandNR_t)); nr_bandnr->bandNR = 1; ASN_SEQUENCE_ADD( &UE_Capability_nr->rf_Parameters.supportedBandListNR.list, nr_bandnr); OAI_NR_UECapability_t *UECap; UECap = CALLOC(1,sizeof(OAI_NR_UECapability_t)); UECap->UE_NR_Capability = UE_Capability_nr; if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout,&asn_DEF_NR_UE_NR_Capability,(void *)UE_Capability_nr); } enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_NR_Capability, NULL, (void *)UE_Capability_nr, &UECap->sdu[0], MAX_UE_NR_CAPABILITY_SIZE); AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); UECap->sdu_size = (enc_rval.encoded + 7) / 8; LOG_I(PHY, "[RRC]UE NR Capability encoded, %d bytes (%zd bits)\n", UECap->sdu_size, enc_rval.encoded + 7); NR_UE_rrc_inst[ctxt_pP->module_id].UECap = UECap; NR_UE_rrc_inst[ctxt_pP->module_id].UECapability = UECap->sdu; NR_UE_rrc_inst[ctxt_pP->module_id].UECapability_size = UECap->sdu_size; OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container.ue_CapabilityRAT_Container, (const char *)NR_UE_rrc_inst[ctxt_pP->module_id].UECapability, NR_UE_rrc_inst[ctxt_pP->module_id].UECapability_size); // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.buf = UE_rrc_inst[ue_mod_idP].UECapability; // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.size = UE_rrc_inst[ue_mod_idP].UECapability_size; AssertFatal(UECapabilityEnquiry->criticalExtensions.present == NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry, "UECapabilityEnquiry->criticalExtensions.present (%d) != UECapabilityEnquiry__criticalExtensions_PR_c1 (%d)\n", UECapabilityEnquiry->criticalExtensions.present,NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry); ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.present = NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation; ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation = CALLOC(1, sizeof(struct NR_UECapabilityInformation_IEs)); ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList = CALLOC(1, sizeof(struct NR_UE_CapabilityRAT_ContainerList)); ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.count = 0; for (i=0; i<UECapabilityEnquiry->criticalExtensions.choice.ueCapabilityEnquiry->ue_CapabilityRAT_RequestList.list.count; i++) { if (UECapabilityEnquiry->criticalExtensions.choice.ueCapabilityEnquiry->ue_CapabilityRAT_RequestList.list.array[i]->rat_Type == NR_RAT_Type_nr) { ASN_SEQUENCE_ADD( &ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list, &ue_CapabilityRAT_Container); enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *) &ul_dcch_msg, buffer, 100); AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); } LOG_I(RRC,"UECapabilityInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); #ifdef ITTI_SIM MessageDef *message_p; uint8_t *message_buffer; message_buffer = itti_malloc (TASK_RRC_UE_SIM,TASK_RRC_GNB_SIM, (enc_rval.encoded + 7) / 8); memcpy (message_buffer, buffer, (enc_rval.encoded + 7) / 8); message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, 0, UE_RRC_DCCH_DATA_IND); GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; GNB_RRC_DCCH_DATA_IND (message_p).size = (enc_rval.encoded + 7) / 8; itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); #else rrc_data_req_ue ( ctxt_pP, DCCH, nr_rrc_mui++, SDU_CONFIRM_NO, (enc_rval.encoded + 7) / 8, buffer, PDCP_TRANSMISSION_MODE_CONTROL); #endif } } }