The code is forced to use nea2, no matter what the UE supports. After 2^18 PDCP packets, it will fail to work (we don't use HFN yet). These limitations will be fixed in later commits. The existing security function was not reused, because it does too much memory allocation and initializes the security context at each ciphering. So here comes nr_pdcp_security_nea2_cipher(). And also the ciphering is done inplace. To be changed if necessary.
2852 lines
132 KiB
C
2852 lines
132 KiB
C
/*
|
|
* 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
|
|
);
|
|
|
|
void rrc_ue_generate_RRCReestablishmentRequest( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index );
|
|
|
|
void
|
|
nr_rrc_ue_generate_rrcReestablishmentComplete(
|
|
const protocol_ctxt_t *const ctxt_pP,
|
|
NR_RRCReestablishment_t *rrcReestablishment,
|
|
uint8_t gNB_index
|
|
);
|
|
|
|
mui_t nr_rrc_mui=0;
|
|
uint8_t first_rrcreconfigurationcomplete = 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,
|
|
uint8_t *const kUPint
|
|
#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;
|
|
// 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) {
|
|
rrc_ue_generate_RRCSetupRequest( ctxt_pP, 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(NR_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_NRUE, 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_NRUE, 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)) {
|
|
rrc_ue_generate_RRCSetupRequest(ctxt_pP, 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_NRUE, TASK_RRC_GNB_SIM, size);
|
|
memcpy (message_buffer, buffer, size);
|
|
message_p = itti_alloc_new_message (TASK_RRC_NRUE, 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;
|
|
}
|
|
|
|
/*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_I(RRC, "SIB1 decoded\n");
|
|
if( g_log->log_component[RRC].level >= OAILOG_DEBUG )
|
|
xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1);
|
|
}
|
|
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_NRUE,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_NRUE, 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 rrc_ue_generate_RRCSetupRequest( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index ) {
|
|
uint8_t i=0,rv[6];
|
|
|
|
if(NR_UE_rrc_inst[ctxt_pP->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[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size =
|
|
do_RRCSetupRequest(
|
|
ctxt_pP->module_id,
|
|
(uint8_t *)NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload,
|
|
rv);
|
|
LOG_I(NR_RRC,"[UE %d] : Frame %d, Logical Channel UL-CCCH (SRB0), Generating RRCSetupRequest (bytes %d, eNB %d)\n",
|
|
ctxt_pP->module_id, ctxt_pP->frame, NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index);
|
|
|
|
for (i=0; i<NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size; i++) {
|
|
LOG_T(NR_RRC,"%x.",NR_UE_rrc_inst[ctxt_pP->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_NRUE,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_NRUE, 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(NR_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(NR_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,
|
|
// 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,
|
|
// 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;
|
|
#ifdef ITTI_SIM
|
|
uint8_t msg_type = 0;
|
|
if((pdu_buffer + 1) != NULL){
|
|
if (*(pdu_buffer + 1) > 0 ) {
|
|
if((pdu_buffer + 9) != NULL){
|
|
msg_type = *(pdu_buffer + 9);
|
|
} else {
|
|
LOG_W(NR_RRC, "[UE] Received invalid downlink message\n");
|
|
return;
|
|
}
|
|
} else {
|
|
if((pdu_buffer + 2) != NULL){
|
|
msg_type = *(pdu_buffer + 2);
|
|
} else {
|
|
LOG_W(NR_RRC, "[UE] Received invalid downlink message\n");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if(msg_type == REGISTRATION_ACCEPT){
|
|
LOG_I(NR_RRC, "[UE] Received REGISTRATION ACCEPT message\n");
|
|
}
|
|
#endif
|
|
msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 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_NRUE,TASK_RRC_GNB_SIM,size);
|
|
memcpy (message_buffer, buffer, size);
|
|
|
|
message_p = itti_alloc_new_message (TASK_RRC_NRUE, 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);
|
|
|
|
if (first_rrcreconfigurationcomplete == 0) {
|
|
first_rrcreconfigurationcomplete = 1;
|
|
#ifdef ITTI_SIM
|
|
if (AMF_MODE_ENABLED) {
|
|
as_nas_info_t initialNasMsg;
|
|
memset(&initialNasMsg, 0, sizeof(as_nas_info_t));
|
|
generateRegistrationComplete(&initialNasMsg, NULL);
|
|
if(initialNasMsg.length > 0){
|
|
MessageDef *message_p;
|
|
message_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_UPLINK_DATA_REQ);
|
|
NAS_UPLINK_DATA_REQ(message_p).UEid = ctxt_pP->module_id;
|
|
NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)initialNasMsg.data;
|
|
NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = initialNasMsg.length;
|
|
itti_send_msg_to_task(TASK_RRC_NRUE, ctxt_pP->instance, message_p);
|
|
LOG_I(NR_RRC, " Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n");
|
|
}
|
|
as_nas_info_t pduEstablishMsg;
|
|
memset(&pduEstablishMsg, 0, sizeof(as_nas_info_t));
|
|
generatePduSessionEstablishRequest(&pduEstablishMsg);
|
|
if(initialNasMsg.length > 0){
|
|
MessageDef *message_p;
|
|
message_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_UPLINK_DATA_REQ);
|
|
NAS_UPLINK_DATA_REQ(message_p).UEid = ctxt_pP->module_id;
|
|
NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)pduEstablishMsg.data;
|
|
NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = pduEstablishMsg.length;
|
|
itti_send_msg_to_task(TASK_RRC_NRUE, ctxt_pP->instance, message_p);
|
|
LOG_I(NR_RRC, " Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n");
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NR_DL_DCCH_MessageType__c1_PR_rrcResume:
|
|
case NR_DL_DCCH_MessageType__c1_PR_rrcRelease:
|
|
LOG_I(NR_RRC, "[UE %d] Received RRC Release (gNB %d)\n",
|
|
ctxt_pP->module_id, gNB_indexP);
|
|
|
|
msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 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(NR_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:
|
|
LOG_I(NR_RRC,
|
|
"[UE%d] Frame %d : Logical Channel DL-DCCH (SRB1), Received RRCReestablishment\n",
|
|
ctxt_pP->module_id,
|
|
ctxt_pP->frame);
|
|
nr_rrc_ue_generate_rrcReestablishmentComplete(
|
|
ctxt_pP,
|
|
dl_dcch_msg->message.choice.c1->choice.rrcReestablishment,
|
|
gNB_indexP);
|
|
break;
|
|
case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer:
|
|
{
|
|
NR_DLInformationTransfer_t *dlInformationTransfer = dl_dcch_msg->message.choice.c1->choice.dlInformationTransfer;
|
|
|
|
if (dlInformationTransfer->criticalExtensions.present
|
|
== NR_DLInformationTransfer__criticalExtensions_PR_dlInformationTransfer) {
|
|
/* This message hold a dedicated info NAS payload, forward it to NAS */
|
|
NR_DedicatedNAS_Message_t *dedicatedNAS_Message =
|
|
dlInformationTransfer->criticalExtensions.choice.dlInformationTransfer->dedicatedNAS_Message;
|
|
uint32_t pdu_length;
|
|
uint8_t *pdu_buffer;
|
|
pdu_length = dedicatedNAS_Message->size;
|
|
pdu_buffer = dedicatedNAS_Message->buf;
|
|
#ifdef ITTI_SIM
|
|
LOG_I(NR_RRC, "[UE %d] Received %s: UEid %u, length %u , buffer %p\n", ctxt_pP->module_id, messages_info[NAS_DOWNLINK_DATA_IND].name,
|
|
ctxt_pP->module_id, pdu_length, pdu_buffer);
|
|
as_nas_info_t initialNasMsg;
|
|
uint8_t msg_type = 0;
|
|
memset(&initialNasMsg, 0, sizeof(as_nas_info_t));
|
|
if((pdu_buffer + 1) != NULL){
|
|
if (*(pdu_buffer + 1) > 0 ) {
|
|
msg_type = *(pdu_buffer + 9);
|
|
} else {
|
|
msg_type = *(pdu_buffer + 2);
|
|
}
|
|
}
|
|
if((pdu_buffer + 2) == NULL){
|
|
LOG_W(NR_RRC, "[UE] Received invalid downlink message\n");
|
|
return 0;
|
|
}
|
|
|
|
switch(msg_type){
|
|
case FGS_IDENTITY_REQUEST:
|
|
generateIdentityResponse(&initialNasMsg,*(pdu_buffer+3));
|
|
break;
|
|
case FGS_AUTHENTICATION_REQUEST:
|
|
generateAuthenticationResp(&initialNasMsg, pdu_buffer);
|
|
break;
|
|
case FGS_SECURITY_MODE_COMMAND:
|
|
generateSecurityModeComplete(&initialNasMsg);
|
|
break;
|
|
default:
|
|
LOG_W(NR_RRC,"unknow message type %d\n",msg_type);
|
|
break;
|
|
}
|
|
if(initialNasMsg.length > 0){
|
|
MessageDef *message_p;
|
|
message_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_UPLINK_DATA_REQ);
|
|
NAS_UPLINK_DATA_REQ(message_p).UEid = ctxt_pP->module_id;
|
|
NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)initialNasMsg.data;
|
|
NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = initialNasMsg.length;
|
|
itti_send_msg_to_task(TASK_RRC_NRUE, ctxt_pP->instance, message_p);
|
|
LOG_I(NR_RRC, " Send NAS_UPLINK_DATA_REQ message\n");
|
|
}
|
|
#else
|
|
MessageDef *msg_p;
|
|
msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_DOWNLINK_DATA_IND);
|
|
NAS_DOWNLINK_DATA_IND(msg_p).UEid = ctxt_pP->module_id; // TODO set the UEid to something else ?
|
|
NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length = pdu_length;
|
|
NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data = pdu_buffer;
|
|
itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
break;
|
|
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(NR_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, GNB_FLAG_NO, NR_RRC_MAC_CCCH_DATA_IND (msg_p).rnti, NR_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;
|
|
|
|
case NAS_UPLINK_DATA_REQ: {
|
|
uint32_t length;
|
|
uint8_t *buffer;
|
|
LOG_I(NR_RRC, "[UE %d] Received %s: UEid %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), NAS_UPLINK_DATA_REQ (msg_p).UEid);
|
|
/* Create message for PDCP (ULInformationTransfer_t) */
|
|
length = do_NR_ULInformationTransfer(&buffer, NAS_UPLINK_DATA_REQ (msg_p).nasMsg.length, NAS_UPLINK_DATA_REQ (msg_p).nasMsg.data);
|
|
/* Transfer data to PDCP */
|
|
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NR_UE_rrc_inst[ue_mod_id].Info[0].rnti, 0, 0,0);
|
|
#ifdef ITTI_SIM
|
|
MessageDef *message_p;
|
|
uint8_t *message_buffer;
|
|
message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM,length);
|
|
memcpy (message_buffer, buffer, length);
|
|
|
|
message_p = itti_alloc_new_message (TASK_RRC_NRUE, 0, UE_RRC_DCCH_DATA_IND);
|
|
if(NR_UE_rrc_inst[ue_mod_id].SRB2_config[0] == NULL)
|
|
UE_RRC_DCCH_DATA_IND (message_p).rbid = DCCH;
|
|
else
|
|
UE_RRC_DCCH_DATA_IND (message_p).rbid = DCCH1;
|
|
UE_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer;
|
|
UE_RRC_DCCH_DATA_IND (message_p).size = length;
|
|
itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt.instance, message_p);
|
|
|
|
#else
|
|
// check if SRB2 is created, if yes request data_req on DCCH1 (SRB2)
|
|
if(NR_UE_rrc_inst[ue_mod_id].SRB2_config[0] == NULL) {
|
|
rrc_data_req_ue (&ctxt,
|
|
DCCH,
|
|
nr_rrc_mui++,
|
|
SDU_CONFIRM_NO,
|
|
length, buffer,
|
|
PDCP_TRANSMISSION_MODE_CONTROL);
|
|
} else {
|
|
rrc_data_req_ue (&ctxt,
|
|
DCCH1,
|
|
nr_rrc_mui++,
|
|
SDU_CONFIRM_NO,
|
|
length, buffer,
|
|
PDCP_TRANSMISSION_MODE_CONTROL);
|
|
}
|
|
#endif
|
|
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(NR_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_NRUE,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_NRUE, 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
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void rrc_ue_generate_RRCReestablishmentRequest( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index )
|
|
{
|
|
NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size =
|
|
do_RRCReestablishmentRequest(
|
|
ctxt_pP->module_id,
|
|
(uint8_t *)NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload, 1);
|
|
LOG_I(NR_RRC,"[UE %d] : Frame %d, Logical Channel UL-CCCH (SRB0), Generating RRCReestablishmentRequest (bytes %d, gNB %d)\n",
|
|
ctxt_pP->module_id, ctxt_pP->frame, NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index);
|
|
|
|
for (int i=0; i<NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size; i++) {
|
|
LOG_T(NR_RRC,"%x.",NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload[i]);
|
|
}
|
|
|
|
LOG_T(NR_RRC,"\n");
|
|
|
|
#ifdef ITTI_SIM
|
|
MessageDef *message_p;
|
|
uint8_t *message_buffer;
|
|
message_buffer = itti_malloc (TASK_RRC_NRUE,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_NRUE, 0, UE_RRC_CCCH_DATA_IND);
|
|
UE_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer;
|
|
UE_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
|
|
}
|
|
|
|
void
|
|
nr_rrc_ue_generate_rrcReestablishmentComplete(
|
|
const protocol_ctxt_t *const ctxt_pP,
|
|
NR_RRCReestablishment_t *rrcReestablishment,
|
|
uint8_t gNB_index
|
|
)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
uint32_t length;
|
|
uint8_t buffer[100];
|
|
length = do_RRCReestablishmentComplete(buffer, rrcReestablishment->rrc_TransactionIdentifier);
|
|
LOG_I(NR_RRC,"[UE %d][RAPROC] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCReestablishmentComplete (bytes%d, gNB %d)\n",
|
|
ctxt_pP->module_id,ctxt_pP->frame, length, gNB_index);
|
|
#ifdef ITTI_SIM
|
|
MessageDef *message_p;
|
|
uint8_t *message_buffer;
|
|
message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM,length);
|
|
memcpy (message_buffer, buffer, length);
|
|
|
|
message_p = itti_alloc_new_message (TASK_RRC_NRUE, 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 = length;
|
|
itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p);
|
|
|
|
#endif
|
|
}
|