/* 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.0 (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_eNB.c * \brief rrc procedures for eNB * \author Navid Nikaein, Raymond Knopp and Michele Paffetti * \date 2011 - 2014 * \version 1.0 * \company Eurecom * \email: navid.nikaein@eurecom.fr, raymond.knopp@eurecom.fr, michele.paffetti@studio.unibo.it */ #define RRC_ENB #define RRC_ENB_C /*NB-IoT include files*/ #include "defs_nb_iot.h" #include "RRC/LITE/MESSAGES/asn1_msg_nb_iot.h" #include "RRCConnectionRequest-NB.h" #include "RRCConnectionReestablishmentRequest-NB.h" #include "ReestablishmentCause-NB-r13.h" #include "UL-CCCH-Message-NB.h" #include "DL-CCCH-Message-NB.h" #include "UL-DCCH-Message-NB.h" #include "DL-DCCH-Message-NB.h" #include "SRB-ToAddMod-NB-r13.h" #include "extern.h" #include "extern_nb_iot.h" #include "assertions.h" #include "asn1_conversions.h" #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" #include "LAYER2/RLC/rlc.h" #include "LAYER2/MAC/proto.h" #include "UTIL/LOG/log.h" #include "COMMON/mac_rrc_primitives.h" #include "rlc.h" #include "SIMULATION/ETH_TRANSPORT/extern.h" #include "rrc_eNB_UE_context.h" #include "platform_types.h" #include "msc.h" #include "T.h" #include "LAYER2/MAC/defs.h" #include "LAYER2/MAC/defs_nb_iot.h" #ifdef USER_MODE # include "RRC/NAS/nas_config.h" # include "RRC/NAS/rb_config.h" # include "OCG.h" # include "OCG_extern.h" #endif #if defined(ENABLE_SECURITY) # include "UTIL/OSA/osa_defs.h" #endif #if defined(ENABLE_USE_MME) # include "rrc_eNB_S1AP.h" # include "rrc_eNB_GTPV1U.h" # if defined(ENABLE_ITTI) # else # include "../../S1AP/s1ap_eNB.h" # endif #endif #include "pdcp.h" #if defined(ENABLE_ITTI) # include "intertask_interface.h" #endif #include "SIMULATION/TOOLS/defs.h" // for taus #if defined(FLEXRAN_AGENT_SB_IF) #include "flexran_agent_extern.h" #endif #ifdef PHY_EMUL extern EMULATION_VARS *Emul_vars; #endif extern eNB_MAC_INST *eNB_mac_inst; extern UE_MAC_INST *UE_mac_inst; #ifdef BIGPHYSAREA extern void* bigphys_malloc(int); #endif /*the Message Unit Identifieer (MUI) is an Identity of the RLC SDU, whic is used to indicate which RLC SDU that is confirmed * with the RLC-AM-Data-conf. e.g. ((struct rlc_am_data_req *) (new_sdu_p->data))->mui (NB_rlc_data_req) */ mui_t rrc_eNB_mui_NB = 0; // should be called when UE is lost by eNB void rrc_eNB_free_UE_NB(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_NB_s* const ue_context_pP) //----------------------------------------------------------------------------- { protocol_ctxt_t ctxt; #if !defined(ENABLE_USE_MME) module_id_t ue_module_id; /* avoid gcc warnings */ (void)ue_module_id; #endif rnti_t rnti = ue_context_pP->ue_context.rnti; AssertFatal(enb_mod_idP < NB_eNB_INST, "eNB inst invalid (%d/%d) for UE %x!", enb_mod_idP, NB_eNB_INST, rnti); /* ue_context_p = rrc_eNB_get_ue_context( &eNB_rrc_inst[enb_mod_idP], rntiP ); */ if (NULL != ue_context_pP) { PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, enb_mod_idP, ENB_FLAG_YES, rnti, 0, 0,enb_mod_idP); LOG_W(RRC, "[eNB %d] Removing UE RNTI %x\n", enb_mod_idP, rnti); #if defined(ENABLE_USE_MME) rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 21); // send cause 21: connection with ue lost /* From 3GPP 36300v10 p129 : 19.2.2.2.2 S1 UE Context Release Request (eNB triggered) * If the E-UTRAN internal reason is a radio link failure detected in the eNB, the eNB shall wait a sufficient time before * triggering the S1 UE Context Release Request procedure * in order to allow the UE to perform the NAS recovery * procedure, see TS 23.401 [17]. */ #else #if defined(OAI_EMU) AssertFatal(ue_context_pP->local_uid < NUMBER_OF_UE_MAX, "local_uid invalid (%d<%d) for UE %x!", ue_context_pP->local_uid, NUMBER_OF_UE_MAX, rnti); ue_module_id = oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[enb_mod_idP][ue_context_pP->local_uid]; AssertFatal(ue_module_id < NUMBER_OF_UE_MAX, "ue_module_id invalid (%d<%d) for UE %x!", ue_module_id, NUMBER_OF_UE_MAX, rnti); oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[enb_mod_idP][ue_context_pP->local_uid] = -1; oai_emulation.info.eNB_ue_module_id_to_rnti[enb_mod_idP][ue_module_id] = NOT_A_RNTI; #endif #endif rrc_mac_remove_ue(enb_mod_idP,rnti); rrc_rlc_remove_ue(&ctxt); pdcp_remove_UE(&ctxt); rrc_eNB_remove_ue_context_NB( &ctxt, &eNB_rrc_inst_NB[enb_mod_idP], (struct rrc_eNB_ue_context_NB_s*) ue_context_pP); } } //----------------------------------------------------------------------------- //actually is not used void rrc_eNB_generate_RRCConnectionRelease_NB( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_NB_t* const ue_context_pP ) //----------------------------------------------------------------------------- { uint8_t buffer[RRC_BUF_SIZE]; uint16_t size; T(T_ENB_RRC_CONNECTION_RELEASE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); memset(buffer, 0, RRC_BUF_SIZE); size = do_RRCConnectionRelease_NB(ctxt_pP->module_id, buffer, rrc_eNB_get_next_transaction_identifier_NB(ctxt_pP->module_id)); // set release timer ue_context_pP->ue_context.ue_release_timer=1; // remove UE after 10 frames after RRCConnectionRelease is triggered ue_context_pP->ue_context.ue_release_timer_thres=100; LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate RRCConnectionRelease-NB (bytes %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), size); LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (rrcConnectionRelease-NB MUI %d) --->[PDCP][RB %u]\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), size, rrc_eNB_mui_NB, DCCH1);//Through SRB1/or SRB1bis MSC_LOG_TX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, buffer, size, MSC_AS_TIME_FMT" rrcConnectionRelease-NB UE %x MUI %d size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_pP->ue_context.rnti, rrc_eNB_mui_NB, size); rrc_data_req( ctxt_pP, DCCH1,//Through SRB1/or SRB1bis rrc_eNB_mui_NB++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); } //----------------------------------------------------------------------------- void rrc_eNB_generate_RRCConnectionReestablishmentReject_NB( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_NB_t* const ue_context_pP, const int CC_id ) //----------------------------------------------------------------------------- { //exactly as in legacy LTE implementation #ifdef RRC_MSG_PRINT int cnt; #endif T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_REJECT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size = do_RRCConnectionReestablishmentReject_NB(ctxt_pP->module_id, (uint8_t*) eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRCConnectionReestablishmentReject\n"); for (cnt = 0; cnt < eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) { LOG_F(RRC,"%02x ", ((uint8_t*)eNB_rrc_inst_NB[ctxt_pP->module_id].Srb0.Tx_buffer.Payload)[cnt]); } LOG_F(RRC,"\n"); #endif MSC_LOG_TX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Header, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size, MSC_AS_TIME_FMT" RRCConnectionReestablishmentReject UE %x size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_pP == NULL ? -1 : ue_context_pP->ue_context.rnti, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCConnectionReestablishmentReject (bytes %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size); } //----------------------------------------------------------------------------- void rrc_eNB_free_mem_UE_context_NB( const protocol_ctxt_t* const ctxt_pP, struct rrc_eNB_ue_context_NB_s* const ue_context_pP ) //----------------------------------------------------------------------------- { LOG_T(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Clearing UE context 0x%p (free internal structs)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), ue_context_pP); //no Scell in NB-IoT --> no DC (Dual Connectivity) if (ue_context_pP->ue_context.SRB_configList) { ASN_STRUCT_FREE(asn_DEF_SRB_ToAddModList_NB_r13, ue_context_pP->ue_context.SRB_configList); ue_context_pP->ue_context.SRB_configList = NULL; } if (ue_context_pP->ue_context.DRB_configList) { ASN_STRUCT_FREE(asn_DEF_DRB_ToAddModList_NB_r13, ue_context_pP->ue_context.DRB_configList); ue_context_pP->ue_context.DRB_configList = NULL; } memset(ue_context_pP->ue_context.DRB_active, 0, sizeof(ue_context_pP->ue_context.DRB_active)); if (ue_context_pP->ue_context.physicalConfigDedicated_NB) { ASN_STRUCT_FREE(asn_DEF_PhysicalConfigDedicated_NB_r13, ue_context_pP->ue_context.physicalConfigDedicated_NB); ue_context_pP->ue_context.physicalConfigDedicated_NB = NULL; } if (ue_context_pP->ue_context.mac_MainConfig_NB) { ASN_STRUCT_FREE(asn_DEF_MAC_MainConfig_NB_r13, ue_context_pP->ue_context.mac_MainConfig_NB); ue_context_pP->ue_context.mac_MainConfig_NB = NULL; } //no sps in NB_IoT //no meas object //no report config //no quantity config //no meas gap config //no measConfig } //----------------------------------------------------------------------------- // return the ue context if there is already an UE with ue_identityP, NULL otherwise static struct rrc_eNB_ue_context_NB_s* rrc_eNB_ue_context_random_exist_NB( const protocol_ctxt_t* const ctxt_pP, const uint64_t ue_identityP ) //----------------------------------------------------------------------------- { struct rrc_eNB_ue_context_NB_s* ue_context_p = NULL; //FIXME: there is a warning related to the new type rrc_ue_tree_NB_s RB_FOREACH(ue_context_p, rrc_ue_tree_NB_s, &(eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head)) { if (ue_context_p->ue_context.random_ue_identity == ue_identityP) return ue_context_p; } return NULL; } //----------------------------------------------------------------------------- // return a new ue context structure if ue_identityP, ctxt_pP->rnti not found in collection static struct rrc_eNB_ue_context_NB_s* rrc_eNB_get_next_free_ue_context_NB( const protocol_ctxt_t* const ctxt_pP, const uint64_t ue_identityP ) //----------------------------------------------------------------------------- { struct rrc_eNB_ue_context_NB_s* ue_context_p = NULL; ue_context_p = rrc_eNB_get_ue_context_NB( &eNB_rrc_inst_NB[ctxt_pP->module_id], ctxt_pP->rnti); if (ue_context_p == NULL) { RB_FOREACH(ue_context_p, rrc_ue_tree_NB_s, &(eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head)) { if (ue_context_p->ue_context.random_ue_identity == ue_identityP) { LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Cannot create new UE context, already exist rand UE id 0x%"PRIx64", uid %u\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), ue_identityP, ue_context_p->local_uid); return NULL; } } ue_context_p = rrc_eNB_allocate_new_UE_context_NB(&eNB_rrc_inst_NB[ctxt_pP->module_id]); if (ue_context_p == NULL) { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Cannot create new UE context, no memory\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); return NULL; } ue_context_p->ue_id_rnti = ctxt_pP->rnti; // here ue_id_rnti is just a key, may be something else ue_context_p->ue_context.rnti = ctxt_pP->rnti; // yes duplicate, 1 may be removed ue_context_p->ue_context.random_ue_identity = ue_identityP; RB_INSERT(rrc_ue_tree_NB_s, &eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head, ue_context_p); LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Created new UE context uid %u\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), ue_context_p->local_uid); return ue_context_p; } else { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Cannot create new UE context, already exist\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); return NULL; } } //----------------------------------------------------------------------------- // return the ue context if there is already an UE with the same S-TMSI(MMEC+M-TMSI), NULL otherwise static struct rrc_eNB_ue_context_NB_s* rrc_eNB_ue_context_stmsi_exist_NB( const protocol_ctxt_t* const ctxt_pP, const mme_code_t mme_codeP, const m_tmsi_t m_tmsiP ) //----------------------------------------------------------------------------- { struct rrc_eNB_ue_context_NB_s* ue_context_p = NULL; RB_FOREACH(ue_context_p, rrc_ue_tree_NB_s, &(eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head)) { LOG_I(RRC,"checking for UE S-TMSI %x, mme %x (%p): rnti %x", m_tmsiP, mme_codeP, ue_context_p, ue_context_p->ue_context.rnti); if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) { printf("=> S-TMSI %x, MME %x\n", ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code); if (ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi == m_tmsiP) if (ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code == mme_codeP) return ue_context_p; } else printf("\n"); } return NULL; } //----------------------------------------------------------------------------- uint8_t rrc_eNB_get_next_transaction_identifier_NB( module_id_t enb_mod_idP ) //----------------------------------------------------------------------------- { static uint8_t rrc_transaction_identifier[NUMBER_OF_eNB_MAX]; rrc_transaction_identifier[enb_mod_idP] = (rrc_transaction_identifier[enb_mod_idP] + 1) % RRC_TRANSACTION_IDENTIFIER_NUMBER; LOG_T(RRC,"generated xid is %d\n",rrc_transaction_identifier[enb_mod_idP]); return rrc_transaction_identifier[enb_mod_idP]; } //----------------------------------------------------------------------------- void rrc_eNB_generate_RRCConnectionReject_NB( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_NB_t* const ue_context_pP, const int CC_id ) //----------------------------------------------------------------------------- { #ifdef RRC_MSG_PRINT int cnt; #endif T(T_ENB_RRC_CONNECTION_REJECT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size = do_RRCConnectionReject_NB(ctxt_pP->module_id, (uint8_t*) eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRCConnectionReject-NB\n"); for (cnt = 0; cnt < eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) { LOG_F(RRC,"%02x ", ((uint8_t*)eNB_rrc_inst_NB[ctxt_pP->module_id].Srb0.Tx_buffer.Payload)[cnt]); } LOG_F(RRC,"\n"); #endif MSC_LOG_TX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Header, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size, MSC_AS_TIME_FMT" RRCConnectionReject-NB UE %x size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_pP == NULL ? -1 : ue_context_pP->ue_context.rnti, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCConnectionReject-NB (bytes %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size); } //----------------------------------------------------------------------------- void rrc_eNB_generate_RRCConnectionSetup_NB( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_NB_t* const ue_context_pP, const int CC_id ) //----------------------------------------------------------------------------- { //connection setup involve the establishment of SRB1 and SRB1bis (but srb1bis is established implicitly) //XXX: this message should go through SRB0 to see this--> uper_encode //XXX: they are assuming that 2 RLC-AM entities are used for SRB1 and SRB1bis // SRB_ToAddMod_NB_r13_t *SRB1_config; //may not needed now // LogicalChannelConfig_NB_r13_t *SRB1_logicalChannelConfig; SRB_ToAddModList_NB_r13_t **SRB_configList; //for both SRB1 and SRB1bis SRB_ToAddMod_NB_r13_t *SRB1bis_config; LogicalChannelConfig_NB_r13_t *SRB1bis_logicalChannelConfig; int cnt; //XXX MP:warning due to function still not completed at PHY (get_lte_frame_parms) //XXX this approach is gone most probably NB_IoT_DL_FRAME_PARMS *fp = mac_xface->get_lte_frame_parms(ctxt_pP->module_id,CC_id); T(T_ENB_RRC_CONNECTION_SETUP, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); SRB_configList = &ue_context_pP->ue_context.SRB_configList; eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size = do_RRCConnectionSetup_NB(ctxt_pP, ue_context_pP, CC_id, (uint8_t*) eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload, rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id), fp, SRB_configList, //MP:should contain only SRb1bis for the moment &ue_context_pP->ue_context.physicalConfigDedicated_NB); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRC Connection Setup\n"); for (cnt = 0; cnt < eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) { LOG_F(RRC,"%02x ", ((uint8_t*)eNB_rrc_inst_NB[ctxt_pP->module_id].Srb0.Tx_buffer.Payload)[cnt]); } LOG_F(RRC,"\n"); ////////////////////////////////// #endif // configure SRB1bis, PhysicalConfigDedicated, MAC_MainConfig for UE if (*SRB_configList != NULL) { // MP: the list should contain just one element for(cnt = 0; cnt < (*SRB_configList)->list.count; cnt++){ SRB1bis_config = (*SRB_configList)->list.array[cnt]; if (SRB1bis_config->logicalChannelConfig_r13) { if (SRB1bis_config->logicalChannelConfig_r13->present == SRB_ToAddMod_NB_r13__logicalChannelConfig_r13_PR_explicitValue) { SRB1bis_logicalChannelConfig = &SRB1bis_config->logicalChannelConfig_r13->choice.explicitValue; } else { SRB1bis_logicalChannelConfig = &SRB1bis_NB_logicalChannelConfig_defaultValue; } } else { SRB1bis_logicalChannelConfig = &SRB1bis_NB_logicalChannelConfig_defaultValue; } LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RRC_eNB --- MAC_CONFIG_REQ (SRB1bis/SRB1) ---> MAC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); //XXX: Maybe some problem if Connection Setup could be called also after security activation //configure the MAC for SRB1bis/SRb1 (but in principle this configuration should be not LCID dependent) NB_rrc_mac_config_req_eNB( ctxt_pP->module_id, ue_context_pP->ue_context.primaryCC_id, ue_context_pP->ue_context.rnti, 0, //physCellID 0, //p_eNB 0, //p_rx_eNB 0, //Ncp 0, //Ncp_UL 0, //eutraband (NS_PmaxList_NB_r13_t*) NULL, (MultiBandInfoList_NB_r13_t*) NULL, (DL_Bitmap_NB_r13_t*) NULL, (long*) NULL,//eutraControlRegionSize (long*)NULL, // (uint8_t*) NULL, //SIWindowSize // (uint16_t*)NULL, //SIperiod 0, //dl_carrierFrequency 0, //ul_carrierFrequency (BCCH_BCH_Message_NB_t*) NULL, (RadioResourceConfigCommonSIB_NB_r13_t *) NULL, (PhysicalConfigDedicated_NB_r13_t*) ue_context_pP->ue_context.physicalConfigDedicated_NB, ue_context_pP->ue_context.mac_MainConfig_NB, //XXX most probably is not needed since is only at UE side DCCH0_NB, //LCID = 3 of SRB1bis SRB1bis_logicalChannelConfig ); break; } } MSC_LOG_TX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Header, // LG WARNING eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size, MSC_AS_TIME_FMT" RRCConnectionSetup-NB UE %x size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_pP->ue_context.rnti, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCConnectionSetup-NB (bytes %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size); // activate release timer, if RRCSetupComplete-NB not received after 10 frames, remove UE ue_context_pP->ue_context.ue_release_timer=1; // remove UE after 10 frames after RRCConnectionRelease-NB is triggered ue_context_pP->ue_context.ue_release_timer_thres=100; } //----------------------------------------------------------------------------- void rrc_eNB_process_RRCConnectionReconfigurationComplete_NB( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_NB_t* ue_context_pP, const uint8_t xid //transaction identifier ) //----------------------------------------------------------------------------- { int i, drb_id; #ifdef PDCP_USE_NETLINK int oip_ifup = 0; int dest_ip_offset = 0; module_id_t ue_module_id = -1; /* avoid gcc warnings */ (void)oip_ifup; (void)dest_ip_offset; (void)ue_module_id; #endif uint8_t *kRRCenc = NULL; uint8_t *kRRCint = NULL; uint8_t *kUPenc = NULL; DRB_ToAddModList_NB_r13_t* DRB_configList2 = ue_context_pP->ue_context.DRB_configList2[xid]; SRB_ToAddModList_NB_r13_t* SRB_configList2 = ue_context_pP->ue_context.SRB_configList2[xid]; T(T_ENB_RRC_CONNECTION_RECONFIGURATION_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); /*Derive Keys*/ #if defined(ENABLE_SECURITY) /* Derive the keys from kenb */ if (DRB_configList2 != NULL) { derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.kenb, &kUPenc); } derive_key_rrc_enc(ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.kenb, &kRRCenc); derive_key_rrc_int(ue_context_pP->ue_context.integrity_algorithm, ue_context_pP->ue_context.kenb, &kRRCint); #endif //no RAL // Refresh SRBs/DRBs for PDCP MSC_LOG_TX_MESSAGE( MSC_RRC_ENB, MSC_PDCP_ENB, NULL, 0, MSC_AS_TIME_FMT" CONFIG_REQ UE %x DRB (security unchanged)", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_pP->ue_context.rnti); NB_rrc_pdcp_config_asn1_req( ctxt_pP, SRB_configList2, DRB_configList2, (DRB_ToReleaseList_NB_r13_t *) NULL, 0xff, //security mode already configured during the securitymodecommand --> they comes from S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_capabilities kRRCenc, kRRCint, kUPenc, NULL, DCCH1); //SRB1 // Refresh SRBs/DRBs for RLC NB_rrc_rlc_config_asn1_req( ctxt_pP, SRB_configList2, DRB_configList2, (DRB_ToReleaseList_NB_r13_t *) NULL, SRB1BIS_FLAG_NO ); // set the SRB active in Ue context if (SRB_configList2 != NULL) { //MP: SRB_ToAddModList_NB_r13_t size = 1 TS 36.331 V14.2.1 pag 615 should stop at first iteration for (i = 0; (i < SRB_configList2->list.count) && (i < 3); i++) { //no need of checking the srb-Identity //we should have only SRB1 in the list ue_context_pP->ue_context.Srb1.Active=1; ue_context_pP->ue_context.Srb1.Srb_info.Srb_id=DCCH1; //LCHAN_iD LOG_I(RRC,"[eNB %d] Frame %d CC %d : SRB1 is now active\n", ctxt_pP->module_id, ctxt_pP->frame, ue_context_pP->ue_context.primaryCC_id); } } // Loop through DRBs, configure MAC, and (optionally) bringup the IP interface if needed if (DRB_configList2 != NULL) { for (i = 0; (i < DRB_configList2->list.count) && (i<2); i++) { // num maxDRB-NB = 2 if (DRB_configList2->list.array[i]) { drb_id = (int)DRB_configList2->list.array[i]->drb_Identity_r13; LOG_I(RRC, "[eNB %d] Frame %d : Logical Channel UL-DCCH, Received RRCConnectionReconfigurationComplete-NB from UE rnti %x, reconfiguring DRB %d/LCID %d\n", ctxt_pP->module_id, ctxt_pP->frame, ctxt_pP->rnti, (int)DRB_configList2->list.array[i]->drb_Identity_r13, //x (int)*DRB_configList2->list.array[i]->logicalChannelIdentity_r13);//x+3 // for pre-ci tests LOG_I(RRC, "[eNB %d] Frame %d : Logical Channel UL-DCCH, Received RRCConnectionReconfigurationComplete-NB from UE %u, reconfiguring DRB %d/LCID %d\n", ctxt_pP->module_id, ctxt_pP->frame, oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[ctxt_pP->module_id][ue_context_pP->local_uid], (int)DRB_configList2->list.array[i]->drb_Identity_r13, (int)*DRB_configList2->list.array[i]->logicalChannelIdentity_r13); if (ue_context_pP->ue_context.DRB_active[drb_id] == 0) { //is a new DRB ue_context_pP->ue_context.DRB_active[drb_id] = 1; /*this should run only once at first time for each DRB since later are never deactivated but only modified*/ #if defined(PDCP_USE_NETLINK) && !defined(LINK_ENB_PDCP_TO_GTPV1U) // can mean also IPV6 since ether -> ipv6 autoconf # if !defined(OAI_NW_DRIVER_TYPE_ETHERNET) && !defined(EXMIMO) && !defined(OAI_USRP) && !defined(OAI_BLADERF) && !defined(ETHERNET) LOG_I(OIP, "[eNB %d] trying to bring up the OAI interface oai%d\n", ctxt_pP->module_id, ctxt_pP->module_id); oip_ifup = nas_config( ctxt_pP->module_id, // interface index ctxt_pP->module_id + 1, // thrid octet ctxt_pP->module_id + 1); // fourth octet if (oip_ifup == 0) { // interface is up --> send a config the DRB # ifdef OAI_EMU oai_emulation.info.oai_ifup[ctxt_pP->module_id] = 1; dest_ip_offset = NB_eNB_INST; # else dest_ip_offset = 8; # endif LOG_I(OIP, "[eNB %d] Config the oai%d to send/receive pkt on DRB %ld to/from the protocol stack\n", ctxt_pP->module_id, ctxt_pP->module_id, (ue_context_pP->local_uid * maxDRB_NB_r13) + DRB_configList2->list.array[i]->drb_Identity_r13); ue_module_id = oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[ctxt_pP->module_id][ue_context_pP->local_uid]; rb_conf_ipv4(0, //add ue_module_id, //cx ctxt_pP->module_id, //inst (ue_module_id * maxDRB_NB_r13) + DRB_configList2->list.array[i]->drb_Identity_r13, // RB 0, //dscp ipv4_address(ctxt_pP->module_id + 1, ctxt_pP->module_id + 1), //saddr ipv4_address(ctxt_pP->module_id + 1, dest_ip_offset + ue_module_id + 1)); //daddr LOG_D(RRC, "[eNB %d] State = Attached (UE rnti %x module id %u)\n", ctxt_pP->module_id, ue_context_pP->ue_context.rnti, ue_module_id); } # else # ifdef OAI_EMU oai_emulation.info.oai_ifup[ctxt_pP->module_id] = 1; # endif # endif #endif LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RRC_eNB --- MAC_CONFIG_REQ (DRB) ---> MAC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); if (DRB_configList2->list.array[i]->logicalChannelIdentity_r13) { DRB2LCHAN_NB[i] = (uint8_t) * DRB_configList2->list.array[i]->logicalChannelIdentity_r13; //set in RRCConnectionReconfiguration (x+3) } //MP: for each DRB I send a rrc_mac_config_req--> what change is the DRB2LCHAN_NB and logicalChannelConfig_r13 NB_rrc_mac_config_req_eNB( ctxt_pP->module_id, ue_context_pP->ue_context.primaryCC_id, ue_context_pP->ue_context.rnti, 0,//physCellId --> this parameters could be set to 0 since no MIB is present 0,// p_eNB 0,//p_rx_eNB 0, //Ncp 0, //Ncp_UL 0, //eutra_band (struct NS_PmaxList_NB_r13*) NULL, (struct MultiBandInfoList_NB_r13*) NULL, (struct DL_Bitmap_NB_r13*) NULL, (long*)NULL,//eutraControlRegionSize (long*)NULL, //nrs_CRS_PowerOffset // (uint8_t*)NULL, // (uint16_t*)NULL, 0, //dl_CarrierFreq 0, //ul_CarrierFreq (BCCH_BCH_Message_NB_t*)NULL, (RadioResourceConfigCommonSIB_NB_r13_t*)NULL, ue_context_pP->ue_context.physicalConfigDedicated_NB, ue_context_pP->ue_context.mac_MainConfig_NB, DRB2LCHAN_NB[i], //over the logical channel id of the DRB (>=4) DRB_configList2->list.array[i]->logicalChannelConfig_r13 ); } else { //ue_context_pP->ue_context.DRB_active[drb_id] == 1 (means that DRB has been modified) /*MP: * since a the list that we manage are ADD/MOD lists and not RELEASE lists * it means that nothing should be deleted but only modified!! */ if (DRB_configList2->list.array[i]->logicalChannelIdentity_r13) { DRB2LCHAN_NB[i] = (uint8_t) * DRB_configList2->list.array[i]->logicalChannelIdentity_r13; //set in RRCConnectionReconfiguration (x+3) } LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RRC_eNB --- MAC_CONFIG_REQ (DRB) ---> MAC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); //MP: The only change w.r.t previous case is that we not put logicalChannelConfig NB_rrc_mac_config_req_eNB( ctxt_pP->module_id, ue_context_pP->ue_context.primaryCC_id, ue_context_pP->ue_context.rnti, 0,//physCellId --> this parameters could be set to 0 since no MIB is present 0,// p_eNB 0,//p_rx_eNB 0, //Ncp 0, //Ncp_UL 0, //eutra_band (struct NS_PmaxList_NB_r13*) NULL, (struct MultiBandInfoList_NB_r13*) NULL, (struct DL_Bitmap_NB_r13*) NULL, (long*)NULL,//eutraControlRegionSize (long*)NULL, //nrs_CRS_PowerOffset // (uint8_t*)NULL, // (uint16_t*)NULL, 0, //dl_CarrierFreq 0, //ul_CarrierFreq (BCCH_BCH_Message_NB_t*)NULL, (RadioResourceConfigCommonSIB_NB_r13_t*)NULL, ue_context_pP->ue_context.physicalConfigDedicated_NB, ue_context_pP->ue_context.mac_MainConfig_NB, DRB2LCHAN_NB[i], //over the logical channel id of the DRB (>=4) (LogicalChannelConfig_NB_r13_t*)NULL ); } } } } } //----------------------------------------------------------------------------- void //was under ITTI // This function triggers the establishment of dedicated bearer in the absence of EPC (oaisim case -- noS1) // to emulate it only establish 2 bearers (max number for NB-IoT) rrc_eNB_reconfigure_DRBs_NB(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_NB_t* ue_context_pP) //------------------------------------------------------------------ { int i; int e_rab_done=0; for (i = 0; i < NB_RB_MAX_NB_IOT-3; i++) { //most 2 DRB for NB-IoT = at most 2 e-rab (DRB) if ( ue_context_pP->ue_context.e_rab[i].status < E_RAB_NB_STATUS_DONE){ // all those new e-rab ( E_RAB_NB_STATUS_NEW) ue_context_pP->ue_context.e_rab[i].status = E_RAB_NB_STATUS_NEW; ue_context_pP->ue_context.e_rab[i].param.e_rab_id = i + 1; ue_context_pP->ue_context.e_rab[i].param.qos.qci = i % 9; ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.priority_level= i % PRIORITY_LEVEL_LOWEST; ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_capability= PRE_EMPTION_CAPABILITY_DISABLED; ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_vulnerability= PRE_EMPTION_VULNERABILITY_DISABLED; ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer = NULL; ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length = 0; // memset (ue_context_pP->ue_context.e_rab[i].param.sgw_addr.buffer,0,20); ue_context_pP->ue_context.e_rab[i].param.sgw_addr.length = 0; ue_context_pP->ue_context.e_rab[i].param.gtp_teid=0; ue_context_pP->ue_context.nb_of_e_rabs++; e_rab_done++; LOG_I(RRC,"setting up the dedicated DRBs %d (index %d) status %d \n", ue_context_pP->ue_context.e_rab[i].param.e_rab_id, i, ue_context_pP->ue_context.e_rab[i].status); } } ue_context_pP->ue_context.setup_e_rabs+=e_rab_done; //MP: in the case of EPC this function is called directly by S1AP (see rrc_eNB_S1AP.c) rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(ctxt_pP, ue_context_pP ); //XXX MP: no ho state } //----------------------------------------------------------------------------- //uint8_t qci_to_priority[9]={2,4,3,5,1,6,7,8,9}; //----------------------------------------------------------------------------- void //was under ITTI rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_NB_t* const ue_context_pP //no ho state ) //----------------------------------------------------------------------------- { uint8_t buffer[RRC_BUF_SIZE]; uint16_t size; int i; struct DRB_ToAddMod_NB_r13 *DRB_config = NULL; struct RLC_Config_NB_r13 *DRB_rlc_config = NULL; struct PDCP_Config_NB_r13 *DRB_pdcp_config = NULL; //only RLC AM for NB-IoT struct LogicalChannelConfig_NB_r13 *DRB_lchan_config = NULL; //no UL specific parameters DRB_ToAddModList_NB_r13_t* DRB_configList=ue_context_pP->ue_context.DRB_configList; DRB_ToAddModList_NB_r13_t** DRB_configList2=NULL; struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13 *dedicatedInfoNASList_NB = NULL; DedicatedInfoNAS_t *dedicatedInfoNas = NULL; /* for no gcc warnings */ (void)dedicatedInfoNas; int drb_identity_index=0; int e_rab_done=0; uint8_t xid = rrc_eNB_get_next_transaction_identifier_NB(ctxt_pP->module_id); //Transaction_id, DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid]; if (*DRB_configList2) { free(*DRB_configList2); } *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); /* Initialize NAS list */ dedicatedInfoNASList_NB = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13)); //MP:add a check on number of setup e_rabs if(ue_context_pP->ue_context.setup_e_rabs > 2){ LOG_E(RRC, "generate_dedicatedRRCConnectionReconfiguration_NB--> more that 2 e_rabs setup for NB-IoT"); return; } for ( i = 0 ; i < ue_context_pP->ue_context.setup_e_rabs ; i++){ //max must be 2 DRBs that are established // bypass the new and already configured erabs if (ue_context_pP->ue_context.e_rab[i].status >= E_RAB_NB_STATUS_DONE) { drb_identity_index++; continue; //skip to the next loop iteration } DRB_config = CALLOC(1, sizeof(*DRB_config)); DRB_config->eps_BearerIdentity_r13 = CALLOC(1, sizeof(long)); // allowed value 5..15, value : x+4 // e_rab_id set previously in rrc_eNB_reconfigure_DRB_NB function or in the EPC *(DRB_config->eps_BearerIdentity_r13) = ue_context_pP->ue_context.e_rab[i].param.e_rab_id;// x+4; // especial case generation DRB_config->drb_Identity_r13 = 1 + drb_identity_index + e_rab_done; //x // allowed values (3..10) but 3 is reserved for SRB1bis so value : x+3 DRB_config->logicalChannelIdentity_r13 = CALLOC(1, sizeof(long)); *(DRB_config->logicalChannelIdentity_r13) = DRB_config->drb_Identity_r13 + 3; DRB_rlc_config = CALLOC(1, sizeof(*DRB_rlc_config)); DRB_config->rlc_Config_r13 = DRB_rlc_config; DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config)); DRB_config->pdcp_Config_r13 = DRB_pdcp_config; DRB_pdcp_config->discardTimer_r13 = CALLOC(1, sizeof(long)); *(DRB_pdcp_config->discardTimer_r13) = PDCP_Config_NB_r13__discardTimer_r13_infinity; /*XXX MP:old implementation foresee a switch case on e_context_pP->ue_context.e_rab[i].param.qos.qci (TS 36.413 and TS 23.401) * but in reality since in NB-IoT only RLC-AM mode is allowed we can directly configure the DRBs whatever the qci * furthermore, the priority of the SRB is set fix to 1 */ // RLC conf //TODO: set properly the following parameters for the DRBs establishment DRB_rlc_config->present = RLC_Config_NB_r13_PR_am; DRB_rlc_config->choice.am.ul_AM_RLC_r13.t_PollRetransmit_r13 = T_PollRetransmit_NB_r13_ms250; //random DRB_rlc_config->choice.am.ul_AM_RLC_r13.maxRetxThreshold_r13 = UL_AM_RLC_NB_r13__maxRetxThreshold_r13_t8; DRB_rlc_config->choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 = CALLOC(1,sizeof(long)); /* OPTIONAL */ *(DRB_rlc_config->choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13)= DL_AM_RLC_NB_r13__enableStatusReportSN_Gap_r13_true; //XXX MP: TS 36.323 v14.2.0 ch5.3.2 PDCP status report operation is not applicable for NB-IoT //(in any case they set to FALSE in the LTE DRBs setup in OAI) //MP: not used header compression PDCP fr DRBs in OAI DRB_pdcp_config->headerCompression_r13.present = PDCP_Config_NB_r13__headerCompression_r13_PR_notUsed; DRB_lchan_config = CALLOC(1, sizeof(*DRB_lchan_config)); DRB_config->logicalChannelConfig_r13 = DRB_lchan_config; DRB_lchan_config->priority_r13 = CALLOC(1,sizeof(long)); *(DRB_lchan_config->priority_r13) = 1L; DRB_lchan_config->logicalChannelSR_Prohibit_r13 = NULL; /*OPTIONAL*/ //no prioritized bitrate //no bucketsize duration //no logical channel group ASN_SEQUENCE_ADD(&DRB_configList->list, DRB_config); ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config); LOG_I(RRC,"EPS ID %ld, DRB ID %ld (index %d), QCI %d, priority %ld, LCID %ld\n", *DRB_config->eps_BearerIdentity_r13, DRB_config->drb_Identity_r13, i, ue_context_pP->ue_context.e_rab[i].param.qos.qci, *(DRB_lchan_config->priority_r13), *(DRB_config->logicalChannelIdentity_r13) ); e_rab_done++; ue_context_pP->ue_context.e_rab[i].status = E_RAB_NB_STATUS_DONE; ue_context_pP->ue_context.e_rab[i].xid = xid; { if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) { dedicatedInfoNas = CALLOC(1, sizeof(DedicatedInfoNAS_t)); memset(dedicatedInfoNas, 0, sizeof(OCTET_STRING_t)); OCTET_STRING_fromBuf(dedicatedInfoNas, (char*)ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer, ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length); ASN_SEQUENCE_ADD(&dedicatedInfoNASList_NB->list, dedicatedInfoNas); LOG_I(RRC,"add NAS info with size %d (rab id %d)\n",ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length, i); } else { LOG_W(RRC,"Not received activate dedicated EPS bearer context request (NAS pdu buffer = NULL)\n"); } /* OLD TODO parameters yet to process ... */ { // ue_context_pP->ue_context.e_rab[i].param.qos; // ue_context_pP->ue_context.e_rab[i].param.sgw_addr; // ue_context_pP->ue_context.e_rab[i].param.gtp_teid; } } } /* If list is empty free the list and reset the address */ if (dedicatedInfoNASList_NB != NULL) { if (dedicatedInfoNASList_NB->list.count == 0) { free(dedicatedInfoNASList_NB); dedicatedInfoNASList_NB = NULL; LOG_W(RRC,"dedicated NAS list is empty, free the list and reset the address\n"); } } else { LOG_W(RRC,"dedicated NAS list is empty\n"); } memset(buffer, 0, RRC_BUF_SIZE); size = do_RRCConnectionReconfiguration_NB(ctxt_pP, buffer, xid, (SRB_ToAddModList_NB_r13_t*)NULL, (DRB_ToAddModList_NB_r13_t*)*DRB_configList2, (DRB_ToReleaseList_NB_r13_t*)NULL, // DRB2_list, NULL, NULL, //physical an MAC config dedicated (struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13*)dedicatedInfoNASList_NB ); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRC Connection Reconfiguration-NB\n"); for (i = 0; i < size; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]); } LOG_F(RRC,"\n"); //////////////////////////////////////// #endif //#if defined(ENABLE_ITTI).... /* Free all NAS PDUs */ for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) { if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) { /* Free the NAS PDU buffer and invalidate it */ free(ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer); ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer = NULL; } } LOG_I(RRC, "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCConnectionReconfiguration-NB (bytes %d, UE RNTI %x)\n", ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); LOG_D(RRC, "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui_NB, ctxt_pP->module_id, DCCH1); //through SRB1 MSC_LOG_TX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, buffer, size, MSC_AS_TIME_FMT" dedicated rrcConnectionReconfiguration-NB UE %x MUI %d size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_pP->ue_context.rnti, rrc_eNB_mui_NB, size); //transmit the RRCConnectionReconfiguration-NB NB_rrc_data_req( ctxt_pP, DCCH1,//through SRB1 rrc_eNB_mui_NB++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); } //----------------------------------------------------------------------------- void rrc_eNB_process_RRCConnectionSetupComplete_NB( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_NB_t* ue_context_pP, RRCConnectionSetupComplete_NB_r13_IEs_t * rrcConnectionSetupComplete_NB ) //----------------------------------------------------------------------------- { LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel UL-DCCH, " "processing RRCConnectionSetupComplete_NB from UE (SRB1bis/SRB1 Active)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); ue_context_pP->ue_context.Srb1bis.Active=1; //SRB1bis active for UE, from eNB point of view ue_context_pP->ue_context.Srb1.Active=1 //SRB1 active for UE (implicitly activated) T(T_ENB_RRC_CONNECTION_SETUP_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #if defined(ENABLE_USE_MME) if (EPC_MODE_ENABLED == 1) { // Forward message to S1AP layer rrc_eNB_send_S1AP_NAS_FIRST_REQ( ctxt_pP, ue_context_pP, rrcConnectionSetupComplete_NB); } else #endif { // RRC loop back (no S1AP), send SecurityModeCommand to UE rrc_eNB_generate_SecurityModeCommand_NB( ctxt_pP, ue_context_pP); } } //----------------------------------------------------------------------------- void rrc_eNB_generate_SecurityModeCommand_NB( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_NB_t* const ue_context_pP ) //----------------------------------------------------------------------------- { /* R2-163262 3GPP NB-IOT Ad-hoc Meeting #2 * The SRB1-bis (no PDCP) is used for SecurityModeCommand and SecurityModeFailure messages * The SRB1 (full PDCP) is used for SecurityModeComplete message */ uint8_t buffer[100]; uint8_t size; T(T_ENB_RRC_SECURITY_MODE_COMMAND, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); size = do_SecurityModeCommand_NB( ctxt_pP, buffer, rrc_eNB_get_next_transaction_identifier_NB(ctxt_pP->module_id), ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.integrity_algorithm); #ifdef RRC_MSG_PRINT uint16_t i=0; LOG_F(RRC,"[MSG] RRC Security Mode Command\n"); for (i = 0; i < size; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]); } LOG_F(RRC,"\n"); #endif LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate SecurityModeCommand-NB (bytes %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), size); LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (securityModeCommand to UE MUI %d) --->[PDCP][RB %02d]\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), size, rrc_eNB_mui_NB, DCCH0_NB); //MP: SRB1bis MSC_LOG_TX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, buffer, size, MSC_AS_TIME_FMT" securityModeCommand UE %x MUI %d size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_pP->ue_context.rnti, rrc_eNB_mui_NB, size); NB_rrc_data_req( //to PDCP ctxt_pP, DCCH0_NB,//MP:through SRB1bis rrc_eNB_mui_NB++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_TRANSPARENT); } //----------------------------------------------------------------------------- void rrc_eNB_generate_UECapabilityEnquiry_NB( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_NB_t* const ue_context_pP ) //----------------------------------------------------------------------------- { //MP: this message is also transmitted when we receive SecurityModeFailure--> in any case we start using SRB1 uint8_t buffer[100]; uint8_t size; T(T_ENB_RRC_UE_CAPABILITY_ENQUIRY, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); size = do_UECapabilityEnquiry_NB( ctxt_pP, buffer, rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id)); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate UECapabilityEnquiry-NB (bytes %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), size); LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (UECapabilityEnquiry-NB MUI %d) --->[PDCP][RB %02d]\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), size, rrc_eNB_mui_NB, DCCH0_NB);//through SRB1bis MSC_LOG_TX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, buffer, size, MSC_AS_TIME_FMT" rrcUECapabilityEnquiry UE %x MUI %d size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_pP->ue_context.rnti, rrc_eNB_mui_NB, size); NB_rrc_data_req( //to PDCP ctxt_pP, DCCH1, //MP: send over SRB1 rrc_eNB_mui_NB++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL);//MP: no more transparent to PDCP -->SRB1 was registered to the pdcp at the beginning } //----------------------------------------------------------------------------- void rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_NB_t* const ue_context_pP //no HO flag ) //----------------------------------------------------------------------------- { uint8_t buffer[RRC_BUF_SIZE]; uint16_t size; int i; // configure SRB1, PhysicalConfigDedicated, MAC_MainConfig for UE //eNB_RRC_INST_NB* rrc_inst = &eNB_rrc_inst_NB[ctxt_pP->module_id]; struct PhysicalConfigDedicated_NB_r13** physicalConfigDedicated_NB = &ue_context_pP->ue_context.physicalConfigDedicated_NB; struct SRB_ToAddMod_NB_r13 *SRB1_config = NULL; struct SRB_ToAddMod_NB_r13__rlc_Config_r13 *SRB1_rlc_config = NULL; struct SRB_ToAddMod_NB_r13__logicalChannelConfig_r13 *SRB1_lchan_config = NULL; SRB_ToAddModList_NB_r13_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; //both SRB1 and SRB1bis SRB_ToAddModList_NB_r13_t **SRB_configList2 = NULL; //only SRB1 struct DRB_ToAddMod_NB_r13 *DRB_config = NULL; struct RLC_Config_NB_r13 *DRB_rlc_config = NULL; struct PDCP_Config_NB_r13 *DRB_pdcp_config = NULL; struct LogicalChannelConfig_NB_r13 *DRB_lchan_config = NULL; DRB_ToAddModList_NB_r13_t** DRB_configList = &ue_context_pP->ue_context.DRB_configList; DRB_ToAddModList_NB_r13_t** DRB_configList2 = NULL; MAC_MainConfig_NB_r13_t *mac_MainConfig_NB = NULL; long *periodicBSR_Timer; long *enableStatusReportSN_Gap = NULL; //should be disabled long *priority= NULL; //1 for SRB1 and 1 for SRB1bis BOOLEAN_t *logicalChannelSR_Prohibit = NULL; //RSRP_Range_t *rsrp = NULL; //may not used struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13 *dedicatedInfoNASList_NB = NULL; DedicatedInfoNAS_t *dedicatedInfoNas = NULL; /* for no gcc warnings */ (void)dedicatedInfoNas; uint8_t xid = rrc_eNB_get_next_transaction_identifier_NB(ctxt_pP->module_id); //Transaction_id, T(T_ENB_RRC_CONNECTION_RECONFIGURATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); // Configure/ Refresh SRB1 /// SRB1 SRB_configList2=&ue_context_pP->ue_context.SRB_configList2[xid]; if (*SRB_configList2) { free(*SRB_configList2); } *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); memset(*SRB_configList2, 0, sizeof(**SRB_configList2)); SRB1_config = CALLOC(1, sizeof(*SRB1_config)); SRB1_rlc_config = CALLOC(1, sizeof(*SRB1_rlc_config)); SRB1_config->rlc_Config_r13 = SRB1_rlc_config; //parameters values set as in the TS 36.331 specs ( pag 640) SRB1_rlc_config->present = SRB_ToAddMod__rlc_Config_PR_explicitValue; SRB1_rlc_config->choice.explicitValue.present = RLC_Config_NB_r13_PR_am; SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC_r13.t_PollRetransmit_r13 = T_PollRetransmit_NB_r13_ms25000; SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC_r13.maxRetxThreshold_r13 = UL_AM_RLC_NB_r13__maxRetxThreshold_r13_t4; SRB1_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 = enableStatusReportSN_Gap; SRB1_lchan_config = CALLOC(1, sizeof(*SRB1_lchan_config)); SRB1_config->logicalChannelConfig_r13 = SRB1_lchan_config; SRB1_lchan_config->present = SRB_ToAddMod_NB_r13__logicalChannelConfig_r13_PR_explicitValue; priority = CALLOC(1, sizeof(long)); *priority = 1; SRB1_lchan_config->choice.explicitValue.priority_r13 =priority; logicalChannelSR_Prohibit = CALLOC(1, sizeof(BOOLEAN_t)); *logicalChannelSR_Prohibit = 1; // is the timer for BSR SRB1_lchan_config->choice.explicitValue.logicalChannelSR_Prohibit_r13 = logicalChannelSR_Prohibit; /* OPTIONAL */ // this list has the configuration for SRB1 and SRB1bis //XXX: Problems ? because SRB_ToAddModList_NB_r13_t max size = 1 // should before flush the list??? or directly overwrite ASN_SEQUENCE_ADD(&SRB_configList->list, SRB1_config); // this list has only the configuration for SRB1 ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB1_config); /// Configure DRB //list of all DRBs if (*DRB_configList) { free(*DRB_configList); } *DRB_configList = CALLOC(1, sizeof(**DRB_configList)); memset(*DRB_configList, 0, sizeof(**DRB_configList)); // list for the configured DRB for this xid (transaction id) DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid]; if (*DRB_configList2) { free(*DRB_configList2); } *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); memset(*DRB_configList2, 0, sizeof(**DRB_configList2)); /// DRB (maxDRBs = 2) DRB_config = CALLOC(1, sizeof(*DRB_config)); DRB_config->eps_BearerIdentity_r13 = CALLOC(1, sizeof(long)); //FIXME: MP: I'm not sure that in NB-IoT the first 0..4 eps-bearerIdentity will be reserved for NSAPI (NEtwork Service Access Point Identifier) *(DRB_config->eps_BearerIdentity_r13) = 5L; // LW set to first value, allowed value 5..15, value : x+4 // NN/MP: this is the 1st DRB for this ue, so set it to 1 DRB_config->drb_Identity_r13 = (DRB_Identity_t) 1; //allowed values INTEGER (1..32), value: x DRB_config->logicalChannelIdentity_r13 = CALLOC(1, sizeof(long)); //MP: logical channel identity =3 is reserved for SRB1bis, seee TS 36.331 pag 616 *(DRB_config->logicalChannelIdentity_r13) = (long)4; //allowed value (4..10), value : x+3 DRB_rlc_config = CALLOC(1, sizeof(*DRB_rlc_config)); DRB_config->rlc_Config_r13 = DRB_rlc_config; //set as TS 36.331 specs ///RLC-AM DRB_rlc_config->present = RLC_Config_NB_r13_PR_am; DRB_rlc_config->choice.am.ul_AM_RLC_r13.t_PollRetransmit_r13 = T_PollRetransmit_NB_r13_ms25000; DRB_rlc_config->choice.am.ul_AM_RLC_r13.maxRetxThreshold_r13 = UL_AM_RLC_NB_r13__maxRetxThreshold_r13_t4; DRB_rlc_config->choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 = enableStatusReportSN_Gap; ///PDCP DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config)); DRB_config->pdcp_Config_r13 = DRB_pdcp_config; DRB_pdcp_config->discardTimer_r13 = CALLOC(1, sizeof(long)); *(DRB_pdcp_config->discardTimer_r13) = PDCP_Config_NB_r13__discardTimer_r13_infinity; //no UM modality for RLC in NB-IoT DRB_pdcp_config->headerCompression_r13.present = PDCP_Config_NB_r13__headerCompression_r13_PR_notUsed; DRB_lchan_config = CALLOC(1, sizeof(*DRB_lchan_config)); DRB_config->logicalChannelConfig_r13 = DRB_lchan_config; DRB_lchan_config->priority_r13 = CALLOC(1, sizeof(long)); *(DRB_lchan_config->priority_r13) = 12; // lower priority than srb1, srb1bis and other dedicated bearer DRB_lchan_config->logicalChannelSR_Prohibit_r13 = NULL;// is the timer for BSR /* OPTIONAL */ //Add the DRB in both list ASN_SEQUENCE_ADD(&(*DRB_configList)->list, DRB_config); ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config); ///Mac_MainConfig (default as defined in TS 36.331 ch 9.2.2) mac_MainConfig_NB = CALLOC(1, sizeof(*mac_MainConfig_NB)); ue_context_pP->ue_context.mac_MainConfig_NB = mac_MainConfig_NB; mac_MainConfig_NB->ul_SCH_Config_r13 = CALLOC(1, sizeof(*mac_MainConfig_NB->ul_SCH_Config_r13)); //no maxARQtx periodicBSR_Timer = CALLOC(1, sizeof(long)); *periodicBSR_Timer = PeriodicBSR_Timer_NB_r13_pp8; mac_MainConfig_NB->ul_SCH_Config_r13->periodicBSR_Timer_r13 = periodicBSR_Timer; mac_MainConfig_NB->ul_SCH_Config_r13->retxBSR_Timer_r13 = RetxBSR_Timer_NB_r13_infinity; mac_MainConfig_NB->timeAlignmentTimerDedicated_r13 = TimeAlignmentTimer_infinity; mac_MainConfig_NB->drx_Config_r13 = NULL; //no phr_config mac_MainConfig_NB->logicalChannelSR_Config_r13 = CALLOC(1, sizeof(struct MAC_MainConfig_NB_r13__logicalChannelSR_Config_r13)); mac_MainConfig_NB->logicalChannelSR_Config_r13->present = MAC_MainConfig_NB_r13__logicalChannelSR_Config_r13_PR_setup; //depends if previously activated mac_MainConfig_NB->logicalChannelSR_Config_r13->choice.setup.logicalChannelSR_ProhibitTimer_r13 = MAC_MainConfig_NB_r13__logicalChannelSR_Config_r13__setup__logicalChannelSR_ProhibitTimer_r13_pp2; //value in PP=PDCCH periods if (*physicalConfigDedicated_NB) { //DL_CarrierConfigDedicated_NB_r13_t cio; //UL_CarrierConfigDedicated_NB_r13_t c; //TODO: which value should be configured of phisical config dedicated? //antennaInfo not present in PhysicalConfigDedicated for NB_IoT //cqi reporting is not present in PhysicalConfigDedicated for NB_IoT //* carrierConfigDedicated_r13 /* OPTIONAL */ //* npdcch_ConfigDedicated_r13 /* OPTIONAL */ //* npusch_ConfigDedicated_r13 /* OPTIONAL */ //* uplinkPowerControlDedicated_r13 /* OPTIONAL */ } else { LOG_E(RRC,"physical_config_dedicated not present in RRCConnectionReconfiguration-NB. Not reconfiguring!\n"); } //no Measurement ID list //no measurement Object--> no cellToAddModList //no report config_list //no Sparams //no handover //#if defined(ENABLE_ITTI)..... /* Initialize NAS list */ dedicatedInfoNASList_NB = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13)); /* Add all NAS PDUs to the list */ for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) { if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) { dedicatedInfoNas = CALLOC(1, sizeof(DedicatedInfoNAS_t)); memset(dedicatedInfoNas, 0, sizeof(OCTET_STRING_t)); OCTET_STRING_fromBuf(dedicatedInfoNas, (char*)ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer, ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length); ASN_SEQUENCE_ADD(&dedicatedInfoNASList_NB->list, dedicatedInfoNas); } /*OLD TODO parameters yet to process ... */ { // ue_context_pP->ue_context.e_rab[i].param.qos; // ue_context_pP->ue_context.e_rab[i].param.sgw_addr; // ue_context_pP->ue_context.e_rab[i].param.gtp_teid; } /* TODO should test if e RAB are Ok before! */ ue_context_pP->ue_context.e_rab[i].status = E_RAB_NB_STATUS_DONE; LOG_D(RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", i, ue_context_pP->ue_context.e_rab[i].status, "E_RAB_NB_STATUS_DONE"); } /* If list is empty free the list and reset the address */ if (dedicatedInfoNASList_NB->list.count == 0) { free(dedicatedInfoNASList_NB); dedicatedInfoNASList_NB = NULL; } memset(buffer, 0, RRC_BUF_SIZE); size = do_RRCConnectionReconfiguration_NB(ctxt_pP, buffer, xid, //Transaction_id, (SRB_ToAddModList_NB_r13_t*)*SRB_configList2, //only SRB1 (DRB_ToAddModList_NB_r13_t*)*DRB_configList, (DRB_ToReleaseList_NB_r13_t*)NULL, // DRB2_list, (struct PhysicalConfigDedicated_NB_r13*)*physicalConfigDedicated_NB, (MAC_MainConfig_t*)mac_MainConfig_NB, (struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13*)dedicatedInfoNASList_NB ); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRCConnectionReconfiguration-NB\n"); for (i = 0; i < size; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]); } LOG_F(RRC,"\n"); //////////////////////////////////////// #endif /// was inside ITTI but I think it is needed /* Free all NAS PDUs */ for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) { if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) { /* Free the NAS PDU buffer and invalidate it */ free(ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer); ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer = NULL; } } LOG_I(RRC, "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCConnectionReconfiguration-NB (bytes %d, UE id %x)\n", ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); LOG_D(RRC, "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration-NB to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui_NB, ctxt_pP->module_id, DCCH1);//through SRB1 MSC_LOG_TX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, buffer, size, MSC_AS_TIME_FMT" rrcConnectionReconfiguration-NB UE %x MUI %d size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_pP->ue_context.rnti, rrc_eNB_mui_NB, size); NB_rrc_data_req( //to PDCP ctxt_pP, DCCH1,//through SRB1 rrc_eNB_mui_NB++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); } /*-----------------CONFIGURATION-------------------*/ //----------------------------------------------------------------------------- static void init_SI_NB( const protocol_ctxt_t* const ctxt_pP, const int CC_id, RrcConfigurationReq* configuration //openair2/COMMON/rrc_messages_types ) //----------------------------------------------------------------------------- { /*WE should allocate memory for PHY_Config structure * is declared in vars_nb_iot.c and put also in the extern_nb_iot * */ config_INFO = malloc(sizeof(PHY_Config_t)); //copy basic parameters eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].physCellId = configuration->Nid_cell[CC_id]; eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].p_eNB = configuration->nb_antenna_ports[CC_id]; eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].p_rx_eNB = configuration->nb_antenna_ports_rx[CC_id]; eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Ncp = configuration->prefix_type[CC_id]; //DL Cyclic prefix eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Ncp_UL = configuration->prefix_type_UL[CC_id];//UL cyclic prefix eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].dl_CarrierFreq = configuration->downlink_frequency[CC_id]; eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].ul_CarrierFreq = configuration->downlink_frequency[CC_id]+ configuration->uplink_frequency_offset[CC_id]; //TODO: verify who allocate memory for sib1_NB, sib2_NB, sib3_NB and mib_nb in the carrier before being passed as parameter eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1_NB = 0; eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23_NB = 0; eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_MIB_NB = 0; //MIB eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].MIB_NB = (uint8_t*) malloc16(32); //MIB is 34 bits=5bytes needed if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].MIB_NB) { eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_MIB_NB = do_MIB_NB(&eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id], configuration->N_RB_DL[CC_id], 0 //FIXME is correct to pass frame = 0?? ); } else { LOG_E(RRC, PROTOCOL_RRC_CTXT_FMT" init_SI: FATAL, no memory for MIB_NB allocated\n", PROTOCOL_RRC_CTXT_ARGS(ctxt_pP)); mac_xface->macphy_exit("[RRC][init_SI] FATAL, no memory for MIB_NB allocated"); } if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_MIB_NB == 255) { mac_xface->macphy_exit("[RRC][init_SI] FATAL, eNB_rrc_inst_NB[enb_mod_idP].carrier[CC_id].sizeof_MIB_NB == 255"); } //SIB1_NB eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].SIB1_NB = (uint8_t*) malloc16(32);//allocation of buffer memory for SIB1_NB if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].SIB1_NB) eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1_NB = do_SIB1_NB( //follow the new implementation ctxt_pP->module_id, CC_id, &eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id], configuration, 0 //FIXME is correct to pass frame = 0?? ); else { LOG_E(RRC, PROTOCOL_RRC_CTXT_FMT" init_SI: FATAL, no memory for SIB1_NB allocated\n", PROTOCOL_RRC_CTXT_ARGS(ctxt_pP)); mac_xface->macphy_exit("[RRC][init_SI] FATAL, no memory for SIB1_NB allocated"); } if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1_NB == 255) { mac_xface->macphy_exit("[RRC][init_SI] FATAL, eNB_rrc_inst_NB[enb_mod_idP].carrier[CC_id].sizeof_SIB1_NB == 255"); } //SIB23_NB eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].SIB23_NB = (uint8_t*) malloc16(64); if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].SIB23_NB) { eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23_NB = do_SIB23_NB( ctxt_pP->module_id, CC_id, &eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id], configuration ); if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23_NB == 255) { mac_xface->macphy_exit("[RRC][init_SI] FATAL, eNB_rrc_inst_NB[mod].carrier[CC_id].sizeof_SIB23_NB == 255"); } LOG_T(RRC, PROTOCOL_RRC_CTXT_FMT" SIB2/3 Contents (partial)\n", PROTOCOL_RRC_CTXT_ARGS(ctxt_pP)); /*FIXME: decide which parameter to show....*/ LOG_T(RRC, PROTOCOL_RRC_CTXT_FMT" TODO: some parameter of SIB23-NB to show\n", PROTOCOL_RRC_CTXT_ARGS(ctxt_pP)); //Use the following as an example // LOG_T(RRC, PROTOCOL_RRC_CTXT_FMT" npusch_config_common.groupAssignmentNPUSCH = %ld\n", // PROTOCOL_RRC_CTXT_ARGS(ctxt_pP), // eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib2_NB->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13. // ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13); //Configure MAC LOG_D(RRC, PROTOCOL_RRC_CTXT_FMT" RRC_UE --- MAC_CONFIG_REQ (SIB1_NB & SIB2_NB params) ---> MAC_UE\n", PROTOCOL_RRC_CTXT_ARGS(ctxt_pP)); // NB_rrc_mac_config_req_eNB(ctxt_pP->module_id, CC_id, 0,//rnti eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].physCellId, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].p_eNB, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].p_rx_eNB, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Ncp, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Ncp_UL, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->freqBandIndicator_r13, //eutra_band eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->freqBandInfo_r13, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->multiBandInfoList_r13, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->downlinkBitmap_r13, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->eutraControlRegionSize_r13, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->nrs_CRS_PowerOffset_r13, // &SIwindowsize, // &SIperiod, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].dl_CarrierFreq, eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].ul_CarrierFreq, (BCCH_BCH_Message_NB_t*) & eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].mib_NB, (RadioResourceConfigCommonSIB_NB_r13_t *) & eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib2_NB->radioResourceConfigCommon_r13, (struct PhysicalConfigDedicated_NB_r13 *)NULL, (MAC_MainConfig_NB_r13_t *) NULL, 0,// MP:logicalChannelID //TODO still have to be properly managed in the interface (struct LogicalChannelConfig_NB_r13 *)NULL ); } else { LOG_E(RRC, PROTOCOL_RRC_CTXT_FMT" init_SI: FATAL, no memory for SIB2/3_NB allocated\n", PROTOCOL_RRC_CTXT_ARGS(ctxt_pP)); mac_xface->macphy_exit("[RRC][init_SI] FATAL, no memory for SIB2/3_NB allocated"); } } //----------------------------------------------------------------------------- //aka openair_rrc_eNB_init char openair_rrc_eNB_configuration_NB( const module_id_t enb_mod_idP, RrcConfigurationReq* configuration //MP: previously was insiede ITTI but actually I put it out ) //----------------------------------------------------------------------------- { protocol_ctxt_t ctxt; int CC_id; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, enb_mod_idP, ENB_FLAG_YES, NOT_A_RNTI, 0, 0,enb_mod_idP); LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" Init...\n", PROTOCOL_RRC_CTXT_ARGS(&ctxt)); #if OCP_FRAMEWORK while ( eNB_rrc_inst_NB == NULL ) { LOG_E(RRC, "eNB_rrc_inst_NB not yet initialized, waiting 1 second\n"); sleep(1); } #endif AssertFatal(eNB_rrc_inst_NB != NULL, "eNB_rrc_nb_iot_inst not initialized!"); AssertFatal(NUMBER_OF_UE_MAX < (module_id_t)0xFFFFFFFFFFFFFFFF, " variable overflow"); eNB_rrc_inst_NB[ctxt.module_id].Nb_ue = 0; for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { eNB_rrc_inst_NB[ctxt.module_id].carrier[CC_id].Srb0.Active = 0; } uid_linear_allocator_init_NB(&eNB_rrc_inst_NB[ctxt.module_id].uid_allocator); //rrc_eNB_UE_context RB_INIT(&eNB_rrc_inst_NB[ctxt.module_id].rrc_ue_head); eNB_rrc_inst_NB[ctxt.module_id].initial_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL); eNB_rrc_inst_NB[ctxt.module_id].s1ap_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL); memcpy(&eNB_rrc_inst_NB[ctxt.module_id].configuration,configuration,sizeof(RrcConfigurationReq)); /// System Information INIT LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" Checking release \n", PROTOCOL_RRC_CTXT_ARGS(&ctxt)); LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" NB-IoT Rel13 detected\n",PROTOCOL_RRC_CTXT_ARGS(&ctxt)); //no CBA //init SI for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { init_SI_NB(&ctxt, CC_id,configuration); } /*New implementation Raymond*/ //MP: NEW defined in rrc_common_nb_iot.h // no more called in MAC/main.c but directly here //rrc_init_global_param_NB(); //XXX following the old implementation: openair_rrc_top_init is called in MAC/main.c //In Rymond version actually is called here //openair_rrc_top_init_eNB_NB(); //init ch SRB0, SRB1 & BDTCH openair_eNB_rrc_on_NB(&ctxt); return 0; } /*-----------------STATE MACHINE---------------*/ //----------------------------------------------------------------------------- int rrc_eNB_decode_ccch_NB( protocol_ctxt_t* const ctxt_pP, const SRB_INFO_NB* const Srb_info, //SRB0 const int CC_id ) //----------------------------------------------------------------------------- { asn_dec_rval_t dec_rval; UL_CCCH_Message_NB_t *ul_ccch_msg_NB = NULL; RRCConnectionRequest_NB_r13_IEs_t *rrcConnectionRequest_NB = NULL; RRCConnectionReestablishmentRequest_NB_r13_IEs_t* rrcConnectionReestablishmentRequest_NB = NULL; RRCConnectionResumeRequest_NB_r13_IEs_t *rrcConnectionResumeRequest_NB= NULL; int i, rval; struct rrc_eNB_ue_context_NB_s* ue_context_p = NULL; uint64_t random_value = 0; int stmsi_received = 0; T(T_ENB_RRC_UL_CCCH_DATA_IN, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); //memset(ul_ccch_msg,0,sizeof(UL_CCCH_Message_t)); LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Decoding UL CCCH %x.%x.%x.%x.%x.%x (%p)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), ((uint8_t*) Srb_info->Rx_buffer.Payload)[0], ((uint8_t *) Srb_info->Rx_buffer.Payload)[1], ((uint8_t *) Srb_info->Rx_buffer.Payload)[2], ((uint8_t *) Srb_info->Rx_buffer.Payload)[3], ((uint8_t *) Srb_info->Rx_buffer.Payload)[4], ((uint8_t *) Srb_info->Rx_buffer.Payload)[5], (uint8_t *) Srb_info->Rx_buffer.Payload); dec_rval = uper_decode( NULL, &asn_DEF_UL_CCCH_Message_NB, (void**)&ul_ccch_msg_NB, (uint8_t*) Srb_info->Rx_buffer.Payload, 100, 0, 0); //#if defined(ENABLE_ITTI).... //# if defined(DISABLE_ITTI_XER_PRINT)... for (i = 0; i < 8; i++) { //MP: FIXME why 8? LOG_T(RRC, "%x.", ((uint8_t *) & ul_ccch_msg_NB)[i]); } if (dec_rval.consumed == 0) { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" FATAL Error in receiving CCCH\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); return -1; } if (ul_ccch_msg_NB->message.present == UL_CCCH_MessageType_NB_PR_c1) { switch (ul_ccch_msg_NB->message.choice.c1.present) { case UL_CCCH_MessageType_NB__c1_PR_NOTHING: LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" Received PR_NOTHING on UL-CCCH-Message-NB\n", PROTOCOL_RRC_CTXT_ARGS(ctxt_pP)); break; case UL_CCCH_MessageType_NB__c1_PR_rrcConnectionReestablishmentRequest_r13: T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_REQUEST, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRCConnectionReestablishementRequest-NB\n"); for (i = 0; i < Srb_info->Rx_buffer.payload_size; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)Srb_info->Rx_buffer.Payload)[i]); } LOG_F(RRC,"\n"); #endif LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT"MAC_eNB--- MAC_DATA_IND (rrcConnectionReestablishmentRequest-NB on SRB0) --> RRC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); rrcConnectionReestablishmentRequest_NB = &ul_ccch_msg_NB->message.choice.c1.choice.rrcConnectionReestablishmentRequest_r13.criticalExtensions.choice.rrcConnectionReestablishmentRequest_r13; //for NB-IoT only "reconfiguration Failure" and "other failure" are allowed as reestablishment cause LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReestablishmentRequest-NB cause %s\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), ((rrcConnectionReestablishmentRequest_NB->reestablishmentCause_r13 == ReestablishmentCause_NB_r13_otherFailure) ? "Other Failure" : "reconfigurationFailure")); //TODO:connection reestablishment to be implemented /*{ uint64_t c_rnti = 0; memcpy(((uint8_t *) & c_rnti) + 3, rrcConnectionReestablishmentRequest.UE_identity.c_RNTI.buf, rrcConnectionReestablishmentRequest.UE_identity.c_RNTI.size); ue_mod_id = rrc_eNB_get_UE_index(enb_mod_idP, c_rnti); } if ((eNB_rrc_inst_NB[enb_mod_idP].phyCellId == rrcConnectionReestablishmentRequest.UE_identity.physCellId) && (ue_mod_id != UE_INDEX_INVALID)){ rrc_eNB_generate_RRCConnectionReestablishment(enb_mod_idP, frameP, ue_mod_id); }else { rrc_eNB_generate_RRCConnectionReestablishmentReject(enb_mod_idP, frameP, ue_mod_id); } */ /* reject all reestablishment attempts for the moment */ //MP:for the moment we only reject rrc_eNB_generate_RRCConnectionReestablishmentReject_NB(ctxt_pP, rrc_eNB_get_ue_context_NB(&eNB_rrc_inst_NB[ctxt_pP->module_id], ctxt_pP->rnti), CC_id); break; case UL_CCCH_MessageType_NB__c1_PR_rrcConnectionRequest_r13: //MSG3 T(T_ENB_RRC_CONNECTION_REQUEST, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRCConnectionRequest-NB\n"); for (i = 0; i < Srb_info->Rx_buffer.payload_size; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)Srb_info->Rx_buffer.Payload)[i]); } LOG_F(RRC,"\n"); #endif LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT"MAC_eNB --- MAC_DATA_IND (rrcConnectionRequest-NB on SRB0) --> RRC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); ue_context_p = rrc_eNB_get_ue_context_NB( //XXX define new function in rrc_eNB_UE_context &eNB_rrc_inst_NB[ctxt_pP->module_id], ctxt_pP->rnti); if (ue_context_p != NULL) { //MP: i receive a ConnectionRequest from a UE which have already a context // erase content rrc_eNB_free_mem_UE_context_NB(ctxt_pP, ue_context_p); MSC_LOG_RX_DISCARDED_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, Srb_info->Rx_buffer.Payload, dec_rval.consumed, MSC_AS_TIME_FMT" RRCConnectionRequest-NB UE %x size %u (UE already in context)", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_p->ue_context.rnti, dec_rval.consumed); } else { rrcConnectionRequest_NB = &ul_ccch_msg_NB->message.choice.c1.choice.rrcConnectionRequest_r13.criticalExtensions.choice.rrcConnectionRequest_r13; { if (InitialUE_Identity_PR_randomValue == rrcConnectionRequest_NB->ue_Identity_r13.present) { //InitialUE-Identity randomValue size should be 40bits = 5 byte AssertFatal(rrcConnectionRequest_NB->ue_Identity_r13.choice.randomValue.size == 5, "wrong InitialUE-Identity randomValue size, expected 5, provided %d", rrcConnectionRequest_NB->ue_Identity_r13.choice.randomValue.size); memcpy(((uint8_t*) & random_value) + 3, rrcConnectionRequest_NB->ue_Identity_r13.choice.randomValue.buf, rrcConnectionRequest_NB->ue_Identity_r13.choice.randomValue.size); /* if there is already a registered UE (with another RNTI) with this random_value, * the current one must be removed from MAC/PHY (zombie UE) */ if ((ue_context_p = rrc_eNB_ue_context_random_exist_NB(ctxt_pP, random_value))) { LOG_W(RRC, "new UE rnti %x (coming with random value) is already there as UE %x, removing %x from MAC/PHY\n", ctxt_pP->rnti, ue_context_p->ue_context.rnti, ctxt_pP->rnti); NB_rrc_mac_remove_ue(ctxt_pP->module_id, ctxt_pP->rnti); ue_context_p = NULL; return 0; } else { ue_context_p = rrc_eNB_get_next_free_ue_context_NB(ctxt_pP, random_value); } } else if (InitialUE_Identity_PR_s_TMSI == rrcConnectionRequest_NB->ue_Identity_r13.present) { /* Save s-TMSI */ S_TMSI_t s_TMSI = rrcConnectionRequest_NB->ue_Identity_r13.choice.s_TMSI; mme_code_t mme_code = BIT_STRING_to_uint8(&s_TMSI.mmec); m_tmsi_t m_tmsi = BIT_STRING_to_uint32(&s_TMSI.m_TMSI); random_value = (((uint64_t)mme_code) << 32) | m_tmsi; if ((ue_context_p = rrc_eNB_ue_context_stmsi_exist_NB(ctxt_pP, mme_code, m_tmsi))) { LOG_I(RRC," S-TMSI exists, ue_context_p %p, old rnti %x => %x\n",ue_context_p,ue_context_p->ue_context.rnti,ctxt_pP->rnti); NB_rrc_mac_remove_ue(ctxt_pP->module_id, ue_context_p->ue_context.rnti); stmsi_received=1; /* replace rnti in the context */ /* for that, remove the context from the RB tree */ ///FIXME MP: warning --> implicit declaration because I insert the new type "rrc_ue_tree_NB_s" RB_REMOVE(rrc_ue_tree_NB_s, &eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head, ue_context_p); /* and insert again, after changing rnti everywhere it has to be changed */ ue_context_p->ue_id_rnti = ctxt_pP->rnti; ue_context_p->ue_context.rnti = ctxt_pP->rnti; RB_INSERT(rrc_ue_tree_NB_s, &eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head, ue_context_p); /* reset timers */ ue_context_p->ue_context.ul_failure_timer = 0; ue_context_p->ue_context.ue_release_timer = 0; } else { LOG_I(RRC," S-TMSI doesn't exist, setting Initialue_identity_s_TMSI.m_tmsi to %p => %x\n",ue_context_p,m_tmsi); ue_context_p = rrc_eNB_get_next_free_ue_context_NB(ctxt_pP, NOT_A_RANDOM_UE_IDENTITY); if (ue_context_p == NULL) LOG_E(RRC, "%s:%d:%s: rrc_eNB_get_next_free_ue_context_NB returned NULL\n", __FILE__, __LINE__, __FUNCTION__); if (ue_context_p != NULL) { ue_context_p->ue_context.Initialue_identity_s_TMSI.presence = TRUE; ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code = mme_code; ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi = m_tmsi; } else { /* TODO: do we have to break here? */ //break; } } MSC_LOG_RX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, Srb_info->Rx_buffer.Payload, dec_rval.consumed, MSC_AS_TIME_FMT" RRCConnectionRequest-NB UE %x size %u (s-TMSI mmec %u m_TMSI %u random UE id (0x%" PRIx64 ")", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_p->ue_context.rnti, dec_rval.consumed, ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code, ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, ue_context_p->ue_context.random_ue_identity); } else { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionRequest-NB without random UE identity or S-TMSI not supported, let's reject the UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); rrc_eNB_generate_RRCConnectionReject_NB(ctxt_pP, rrc_eNB_get_ue_context_NB(&eNB_rrc_inst_NB[ctxt_pP->module_id], ctxt_pP->rnti), CC_id); break; } } LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE context: %p\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), ue_context_p); if (ue_context_p != NULL) { //#if defined(ENABLE_ITTI) ue_context_p->ue_context.establishment_cause_NB = rrcConnectionRequest_NB->establishmentCause_r13; if (stmsi_received==0){ LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Accept new connection from UE random UE identity (0x%" PRIx64 ") MME code %u TMSI %u cause %ld\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), ue_context_p->ue_context.random_ue_identity, ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code, ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, ue_context_p->ue_context.establishment_cause_NB); } else{ LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Accept new connection from UE MME code %u TMSI %u cause %ld\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code, ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, ue_context_p->ue_context.establishment_cause_NB); } //#else // LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Accept new connection for UE random UE identity (0x%" PRIx64 ")\n", // PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), // ue_context_p->ue_context.random_ue_identity); //#endif if (stmsi_received == 0) eNB_rrc_inst_NB[ctxt_pP->module_id].Nb_ue++; } else { // no context available LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Can't create new context for UE random UE identity (0x%" PRIx64 ")\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), random_value); NB_rrc_mac_remove_ue(ctxt_pP->module_id,ctxt_pP->rnti); return -1; } } //MP: RRM not used //#ifndef NO_RRM // send_msg(&S_rrc, msg_rrc_MR_attach_ind(ctxt_pP->module_id, Mac_id)); //#else ue_context_p->ue_context.primaryCC_id = CC_id; // SRB1bis (LCID = 3 = DCCH0) ue_context_p->ue_context.Srb1bis.Active = 1; ue_context_p->ue_context.Srb1bis.Srb_info.Srb_id = DCCH0_NB; //generate RRCConnectionSetup-NB rrc_eNB_generate_RRCConnectionSetup_NB(ctxt_pP, ue_context_p, CC_id); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT"CALLING RLC CONFIG SRB1bis and SRB1 (rbid %d, rbid %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), DCCH0_NB, DCCH1_NB); MSC_LOG_TX_MESSAGE( MSC_RRC_ENB, MSC_PDCP_ENB, NULL, 0, MSC_AS_TIME_FMT" CONFIG_REQ UE %x SRB", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_p->ue_context.rnti); //MP: we should not configure PDCP for SRB1bis but only for SRB1 NB_rrc_pdcp_config_asn1_req(ctxt_pP, ue_context_p->ue_context.SRB_configList, //contain SRB1bis but used as SRB1 (DRB_ToAddModList_NB_r13_t *) NULL, (DRB_ToReleaseList_NB_r13_t*) NULL, 0xff, NULL, NULL, NULL, NULL, DCCH1); ///MP: Configure RLC for SRB1bis NB_rrc_rlc_config_asn1_req(ctxt_pP, ue_context_p->ue_context.SRB_configList, (DRB_ToAddModList_NB_r13_t*) NULL, (DRB_ToReleaseList_NB_r13_t*) NULL, SRB1BIS_FLAG_YES ); //MP: Configure RLC for SRB1 NB_rrc_rlc_config_asn1_req(ctxt_pP, ue_context_p->ue_context.SRB_configList, (DRB_ToAddModList_NB_r13_t*) NULL, (DRB_ToReleaseList_NB_r13_t*) NULL, SRB1BIS_FLAG_NO ); //#endif //NO_RRM break; //RRCConnectionSetup-NB case UL_CCCH_MessageType_NB__c1_PR_rrcConnectionResumeRequest_r13: // TS 36.331 accept the resume, or switch back to a Connection setup or reject the request T(T_ENB_RRC_CONNECTION_RESUME_REQUEST, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRCConnectionResumeRequest-NB\n"); for (i = 0; i < Srb_info->Rx_buffer.payload_size; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)Srb_info->Rx_buffer.Payload)[i]); } LOG_F(RRC,"\n"); #endif LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT"MAC_eNB--- MAC_DATA_IND (rrcConnectionResumeRequest-NB on SRB0) --> RRC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); rrcConnectionResumeRequest_NB= &ul_ccch_msg_NB->message.choice.c1.choice.rrcConnectionResumeRequest_r13.criticalExtensions.choice.rrcConnectionResumeRequest_r13; LOG_I(RRC,PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionResumeRequest-NB cause %s\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), ((rrcConnectionResumeRequest_NB->resumeCause_r13 == EstablishmentCause_NB_r13_mt_Access) ? "mt Access" : (rrcConnectionResumeRequest_NB->resumeCause_r13 == EstablishmentCause_NB_r13_mo_Signalling) ? "mo Signalling" : (rrcConnectionResumeRequest_NB->resumeCause_r13 == EstablishmentCause_NB_r13_mo_Data) ? "mo Data": (rrcConnectionResumeRequest_NB->resumeCause_r13 == EstablishmentCause_NB_r13_mo_ExceptionData) ? "mo Exception data" : "delay tollerant Access v1330")); //MP: only reject for now rrc_eNB_generate_RRCConnectionReject_NB(ctxt_pP, rrc_eNB_get_ue_context_NB(&eNB_rrc_inst_NB[ctxt_pP->module_id], ctxt_pP->rnti), CC_id); break; default: LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Unknown message\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); rval = -1; break; } rval = 0; } else { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Unknown error \n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); rval = -1; } return rval; } //----------------------------------------------------------------------------- int rrc_eNB_decode_dcch_NB( const protocol_ctxt_t* const ctxt_pP, const rb_id_t Srb_id, //Dcch_index const uint8_t* const Rx_sdu, const sdu_size_t sdu_sizeP ) //----------------------------------------------------------------------------- { asn_dec_rval_t dec_rval; UL_DCCH_Message_NB_t *ul_dcch_msg_NB = NULL; UE_Capability_NB_r13_t *UE_Capability_NB = NULL; int i; struct rrc_eNB_ue_context_NB_s* ue_context_p = NULL; int dedicated_DRB=0; T(T_ENB_RRC_UL_DCCH_DATA_IN, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); if ((Srb_id != 1) && (Srb_id != 3)) { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received message on SRB%d, should not have ...\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), Srb_id); } else { LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received message on SRB%d\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), Srb_id); } LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Decoding UL-DCCH Message-NB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); dec_rval = uper_decode( NULL, &asn_DEF_UL_DCCH_Message_NB, (void**)&ul_dcch_msg_NB, Rx_sdu, sdu_sizeP, 0, 0); //#if defined(ENABLE_ITTI) //# if defined(DISABLE_ITTI_XER_PRINT) { for (i = 0; i < sdu_sizeP; i++) { LOG_T(RRC, "%x.", Rx_sdu[i]); } LOG_T(RRC, "\n"); } if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Failed to decode UL-DCCH (%zu bytes)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), dec_rval.consumed); return -1; } ue_context_p = rrc_eNB_get_ue_context_NB( &eNB_rrc_inst_NB[ctxt_pP->module_id], ctxt_pP->rnti); if (ul_dcch_msg_NB->message.present == UL_DCCH_MessageType_NB_PR_c1) { switch (ul_dcch_msg_NB->message.choice.c1.present) { case UL_DCCH_MessageType_NB__c1_PR_NOTHING: /* No components present */ break; //no measurement reports case UL_DCCH_MessageType_NB__c1_PR_rrcConnectionReconfigurationComplete_r13: #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRCConnectionReconfigurationComplete-NB\n"); for (i = 0; i < sdu_sizeP; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]); } LOG_F(RRC,"\n"); #endif MSC_LOG_RX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, Rx_sdu, sdu_sizeP, MSC_AS_TIME_FMT" RRCConnectionReconfigurationComplete-NB UE %x size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_p->ue_context.rnti, sdu_sizeP); LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " "(RRCConnectionReconfigurationComplete-NB) ---> RRC_eNB]\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), DCCH1, //through SRB1 sdu_sizeP); if (ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.criticalExtensions. present == RRCConnectionReconfigurationComplete_NB__criticalExtensions_PR_rrcConnectionReconfigurationComplete_r13) { /*NN: revise the condition */ //MP: RRC_RECONFIGURED indicate if the default/dedicated bearer has been/not established if (ue_context_p->ue_context.Status == RRC_RECONFIGURED){ // a dedicated bearers has been established dedicated_DRB = 1; LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB, xid %ld)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier); }else { //a default bearer has been established dedicated_DRB = 0; ue_context_p->ue_context.Status = RRC_RECONFIGURED; LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (default DRB, xid %ld)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier); } rrc_eNB_process_RRCConnectionReconfigurationComplete_NB( ctxt_pP, ue_context_p, ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier); #if defined(FLEXRAN_AGENT_SB_IF) //WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future if (mac_agent_registered[ctxt_pP->module_id]) { agent_mac_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id, ue_context_p->ue_id_rnti, PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED); } #endif } //#if defined(ENABLE_ITTI)... #if defined(ENABLE_USE_MME) if (EPC_MODE_ENABLED == 1) { if (dedicated_DRB == 1){ rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(ctxt_pP, ue_context_p, ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier); }else { rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); } } #else // MP: not use of MME //dedicated bearer in the absence of EPC if (dedicated_DRB == 0 ) { rrc_eNB_reconfigure_DRBs_NB(ctxt_pP,ue_context_p); //MP: establish a dedicated DRB } #endif break; case UL_DCCH_MessageType_NB__c1_PR_rrcConnectionReestablishmentComplete_r13: //for the moment will be not possible since we reject any connectionReestablishmentRequest T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRCConnectionReestablishmentComplete-NB \n"); for (i = 0; i < sdu_sizeP; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]); } LOG_F(RRC,"\n"); #endif MSC_LOG_RX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, Rx_sdu, sdu_sizeP, MSC_AS_TIME_FMT" rrcConnectionReestablishmentComplete-NB UE %x size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_p->ue_context.rnti, sdu_sizeP); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " "(rrcConnectionReestablishmentComplete-NB) ---> RRC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), DCCH, sdu_sizeP); break; case UL_DCCH_MessageType_NB__c1_PR_rrcConnectionSetupComplete_r13: //MP: Ts 36.331 V14.2.1 RRCConnectionSetupComplete is transmitted over SRB1bis (pag 585) #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRCConnectionSetupComplete-NB\n"); for (i = 0; i < sdu_sizeP; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]); } LOG_F(RRC,"\n"); #endif MSC_LOG_RX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, Rx_sdu, sdu_sizeP, MSC_AS_TIME_FMT" RRCConnectionSetupComplete-NB UE %x size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_p->ue_context.rnti, sdu_sizeP); LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " "(RRCConnectionSetupComplete-NB) ---> RRC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), DCCH0_NB,//SRB1bis sdu_sizeP); if (ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionSetupComplete_r13.criticalExtensions.present == RRCConnectionSetupComplete_NB__criticalExtensions_PR_rrcConnectionSetupComplete_r13) { rrc_eNB_process_RRCConnectionSetupComplete_NB( ctxt_pP, ue_context_p, &ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionSetupComplete_r13.criticalExtensions.choice.rrcConnectionSetupComplete_r13); //set Ue status CONNECTED ue_context_p->ue_context.Status = RRC_CONNECTED; LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_CONNECTED \n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); #if defined(FLEXRAN_AGENT_SB_IF) //WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future if (mac_agent_registered[ctxt_pP->module_id]) { agent_mac_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id, ue_context_p->ue_id_rnti, PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED); } #endif } ue_context_p->ue_context.ue_release_timer=0; break; case UL_DCCH_MessageType_NB__c1_PR_securityModeComplete_r13: /* R2-163262 3GPP NB-IOT Ad-hoc Meeting #2 * After receiving the SMC and performing the security activation, the UE shall use the SRB1. */ T(T_ENB_RRC_SECURITY_MODE_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRC SecurityModeComplete-NB\n"); for (i = 0; i < sdu_sizeP; i++) eNB->pusch_vars[UE_id]{ LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]); } LOG_F(RRC,"\n"); #endif MSC_LOG_RX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, Rx_sdu, sdu_sizeP, MSC_AS_TIME_FMT" securityModeComplete UE %x size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_p->ue_context.rnti, sdu_sizeP); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" received securityModeComplete-NB on UL-DCCH %d from UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), DCCH); LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " "(securityModeComplete-NB) ---> RRC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), DCCH0_NB,//through SRB1bis sdu_sizeP); #ifdef XER_PRINT xer_fprint(stdout, &asn_DEF_UL_DCCH_Message_NB, (void *)ul_dcch_msg_NB); #endif //MP: this is OPTIONAL ue_context_p->ue_context.Srb1bis.Active=0; rrc_eNB_generate_UECapabilityEnquiry_NB(ctxt_pP, ue_context_p); break; case UL_DCCH_MessageType_NB__c1_PR_securityModeFailure_r13: //MP: Security Mode failure should be received over SRB1bis since the security activation fails /*(see R2-163262) The SRB1-bis (no PDCP) is used for SecurityModeCommand and SecurityModeFailure messages, The SRB1 (full PDCP) is used for SecurityModeComplete message.*/ /* * Furthermore from TS 36.331 ch:5.3.4.3 Reception of the SecurityModeCommand by the UE * if the SecurityModeCommand message passes the integrity protection check * .... * else * 2> continue using the configuration used prior to the reception of the SecurityModeCommand message, * i.e. neither apply integrity protection nor ciphering. * 2> submit the SecurityModeFailure message to lower layers for transmission, upon which the procedure ends */ T(T_ENB_RRC_SECURITY_MODE_FAILURE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRC SecurityModeFailure-NB\n"); for (i = 0; i < sdu_sizeP; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]); } LOG_F(RRC,"\n"); #endif MSC_LOG_RX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, Rx_sdu, sdu_sizeP, MSC_AS_TIME_FMT" securityModeFailure-NB UE %x size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_p->ue_context.rnti, sdu_sizeP); LOG_W(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " "(securityModeFailure-NB) ---> RRC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), DCCH0_NB, sdu_sizeP); #ifdef XER_PRINT xer_fprint(stdout, &asn_DEF_UL_DCCH_Message_NB, (void *)ul_dcch_msg_NB); #endif //MP: After reception of SecurityModeFailure we should configure no security //therefore setting securityActivated=0 for the corresponding PDCP entity in the PDCP but still start the usage of SRB1 // pdcp_pP-> security_activated modified (=1) by pdcp_config_set_security in NB_pdcp_config_req_asn1 at configuration time // we now create a particular case for pdcp_config_set_securityy function in which for a particular securityMode (= -1) we deactivate security. // we first invoke the NB_rrc_pdcp_config_asn1_req that with the particular case of securityMode = -1 will disable security through the pdcp_config_set_security //MP: the integrity protection is still not used in OAI --> MAC-I is padded always to 0 so no need to modify it NB_rrc_pdcp_config_asn1_req( ctxt_pP, ue_context_p->ue_context.SRB_configList, (DRB_ToAddModList_NB_r13_t *)NULL, (DRB_ToReleaseList_NB_r13_t*)NULL, -1, //security_modeP particular case NULL, NULL, NULL, NULL, DCCH1//its only for check purposes (if correctly called could be deleted) ); rrc_eNB_generate_UECapabilityEnquiry_NB(ctxt_pP, ue_context_p); break; case UL_DCCH_MessageType_NB__c1_PR_ueCapabilityInformation_r13: //MP: received over SRB1 T(T_ENB_RRC_UE_CAPABILITY_INFORMATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRC UECapablilityInformation-NB \n"); for (i = 0; i < sdu_sizeP; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]); } LOG_F(RRC,"\n"); #endif MSC_LOG_RX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, Rx_sdu, sdu_sizeP, MSC_AS_TIME_FMT" ueCapabilityInformation-NB UE %x size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_p->ue_context.rnti, sdu_sizeP); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" received ueCapabilityInformation-NB on UL-DCCH %d from UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), DCCH1); LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " "(UECapabilityInformation) ---> RRC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), DCCH1, sdu_sizeP); #ifdef XER_PRINT xer_fprint(stdout, &asn_DEF_UL_DCCH_Message_NB, (void *)ul_dcch_msg); #endif LOG_I(RRC, "got UE capabilities for UE %x\n", ctxt_pP->rnti); //FIXME MP: ueCapabilityInformation different w.r.t LTE --> how to decode it? dec_rval = uper_decode(NULL, &asn_DEF_UE_Capability_NB_r13, (void **)&UE_Capability_NB, Rx_sdu, //*buffer//FIXME may this is not the best way (may incorrect) sdu_sizeP,//*size //FIXME may this is not the best way (may incorrect) 0, //skip bits 0); //unused bits #if defined(ENABLE_USE_MME) if (EPC_MODE_ENABLED == 1) { rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP, ue_context_p, ul_dcch_msg_NB); } #else ue_context_p->ue_context.nb_of_e_rabs = 1; //FIXME may no more present in NB_IoT or different parameter to set for (i = 0; i < ue_context_p->ue_context.nb_of_e_rabs; i++){ ue_context_p->ue_context.e_rab[i].status = E_RAB_NB_STATUS_NEW; ue_context_p->ue_context.e_rab[i].param.e_rab_id = 1+i; ue_context_p->ue_context.e_rab[i].param.qos.qci=9; //Non-GBR } ue_context_p->ue_context.setup_e_rabs =ue_context_p->ue_context.nb_of_e_rabs; #endif rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(ctxt_pP, ue_context_p);//no HO_FLAG break; ///no ULHandoverPreparationTransfer case UL_DCCH_MessageType_NB__c1_PR_ulInformationTransfer_r13: T(T_ENB_RRC_UL_INFORMATION_TRANSFER, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRC ULInformationTransfer-NB \n"); for (i = 0; i < sdu_sizeP; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]); } LOG_F(RRC,"\n"); #endif MSC_LOG_RX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, Rx_sdu, sdu_sizeP, MSC_AS_TIME_FMT" ulInformationTransfer-NB UE %x size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_p->ue_context.rnti, sdu_sizeP); #if defined(ENABLE_USE_MME) if (EPC_MODE_ENABLED == 1) { rrc_eNB_send_S1AP_UPLINK_NAS(ctxt_pP, ue_context_p, ul_dcch_msg_NB); } #endif break; ///no CounterCheckResponse case UL_DCCH_MessageType_NB__c1_PR_rrcConnectionResumeComplete_r13: //will be not possible because for the moment we reject any ConnectionResumeRequest T(T_ENB_RRC_CONNECTION_RESUME_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRCConnectionResumeComplete-NB \n"); for (i = 0; i < sdu_sizeP; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]); } LOG_F(RRC,"\n"); #endif MSC_LOG_RX_MESSAGE( MSC_RRC_ENB, MSC_RRC_UE, Rx_sdu, sdu_sizeP, MSC_AS_TIME_FMT" rrcConnectionResumeComplete-NB UE %x size %u", MSC_AS_TIME_ARGS(ctxt_pP), ue_context_p->ue_context.rnti, sdu_sizeP); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " "(rrcConnectionResumeComplete-NB) ---> RRC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), DCCH, //check sdu_sizeP); break; default: T(T_ENB_RRC_UNKNOW_MESSAGE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Unknown message %s:%u\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), __FILE__, __LINE__); return -1; } return 0; } else { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Unknown error %s:%u\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), __FILE__, __LINE__); return -1; } } //----------------------------------------------------------------------------- //put out from the ITTI FIXME is completely based on ITTI--> must be changed (msg_p, itti_receive_msg ecc...) void* rrc_enb_task_NB( void* args_p ) //----------------------------------------------------------------------------- { MessageDef *msg_p; const char *msg_name_p; instance_t instance; int result; SRB_INFO_NB *srb_info_p; int CC_id; protocol_ctxt_t ctxt; itti_mark_task_ready(TASK_RRC_ENB); while (1) { // Wait for a message itti_receive_msg(TASK_RRC_ENB, &msg_p); msg_name_p = ITTI_MSG_NAME(msg_p); instance = ITTI_MSG_INSTANCE(msg_p); switch (ITTI_MSG_ID(msg_p)) { case TERMINATE_MESSAGE: itti_exit_task(); break; case MESSAGE_TEST: LOG_I(RRC, "[eNB %d] Received %s\n", instance, msg_name_p); break; /* Messages from MAC */ case RRC_MAC_CCCH_DATA_IND: PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, RRC_MAC_CCCH_DATA_IND(msg_p).rnti, msg_p->ittiMsgHeader.lte_time.frame, msg_p->ittiMsgHeader.lte_time.slot); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received %s\n", PROTOCOL_RRC_CTXT_UE_ARGS(&ctxt), msg_name_p); CC_id = RRC_MAC_CCCH_DATA_IND(msg_p).CC_id; ///SRB0 srb_info_p = &eNB_rrc_inst_NB[instance].carrier[CC_id].Srb0; memcpy(srb_info_p->Rx_buffer.Payload, RRC_MAC_CCCH_DATA_IND(msg_p).sdu, RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size); srb_info_p->Rx_buffer.payload_size = RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size; rrc_eNB_decode_ccch_NB(&ctxt, srb_info_p, CC_id); //SRB0 break; /* Messages from PDCP */ case RRC_DCCH_DATA_IND: PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, RRC_DCCH_DATA_IND(msg_p).rnti, msg_p->ittiMsgHeader.lte_time.frame, msg_p->ittiMsgHeader.lte_time.slot); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received on DCCH %d %s\n", PROTOCOL_RRC_CTXT_UE_ARGS(&ctxt), RRC_DCCH_DATA_IND(msg_p).dcch_index, msg_name_p); rrc_eNB_decode_dcch_NB(&ctxt, RRC_DCCH_DATA_IND(msg_p).dcch_index, //3 if SRB1bis and 1 for SRB1 RRC_DCCH_DATA_IND(msg_p).sdu_p, //rx_sdu RRC_DCCH_DATA_IND(msg_p).sdu_size); // Message buffer has been processed, free it now. result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_IND(msg_p).sdu_p); AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); break; #if defined(ENABLE_USE_MME) /* Messages from S1AP */ case S1AP_DOWNLINK_NAS: rrc_eNB_process_S1AP_DOWNLINK_NAS(msg_p, msg_name_p, instance, &rrc_eNB_mui_NB); break; case S1AP_INITIAL_CONTEXT_SETUP_REQ: rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p, msg_name_p, instance); break; case S1AP_UE_CTXT_MODIFICATION_REQ: rrc_eNB_process_S1AP_UE_CTXT_MODIFICATION_REQ(msg_p, msg_name_p, instance); break; case S1AP_PAGING_IND: LOG_E(RRC, "[eNB %d] Received not yet implemented message %s\n", instance, msg_name_p); break; case S1AP_E_RAB_SETUP_REQ: rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(msg_p, msg_name_p, instance); LOG_D(RRC, "[eNB %d] Received the message %s\n", instance, msg_name_p); break; case S1AP_UE_CONTEXT_RELEASE_REQ: rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ(msg_p, msg_name_p, instance); break; case S1AP_UE_CONTEXT_RELEASE_COMMAND: rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND(msg_p, msg_name_p, instance); break; case GTPV1U_ENB_DELETE_TUNNEL_RESP: /* Nothing to do. Apparently everything is done in S1AP processing */ //LOG_I(RRC, "[eNB %d] Received message %s, not processed because procedure not synched\n", //instance, msg_name_p); break; # endif /* Messages from eNB app */ case RRC_CONFIGURATION_REQ: LOG_I(RRC, "[eNB %d] Received %s\n", instance, msg_name_p); openair_rrc_eNB_configuration_NB(ENB_INSTANCE_TO_MODULE_ID(instance), &RRC_CONFIGURATION_REQ(msg_p)); break; default: LOG_E(RRC, "[eNB %d] Received unexpected message %s\n", instance, msg_name_p); break; } 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; } } #ifndef USER_MODE EXPORT_SYMBOL(Rlc_info_am_config); #endif