From 46a8c83b6c4f79489f8e3fddb9e36446940d91a8 Mon Sep 17 00:00:00 2001 From: Javier Morgade Date: Thu, 14 Feb 2019 15:35:00 +0100 Subject: [PATCH] UE procedures for FeMBMS SIB1-MBMS (SystemInformationBlockType1-MBMS message) -- asn1 dissectors ETSI TS 136 331 V14.2.2 (2017-05) -- schedule_SI_MBMS -- ue_decode_si_mbms --- openair1/SCHED_UE/phy_procedures_lte_ue.c | 21 +- openair2/COMMON/mac_messages_def.h | 3 + openair2/COMMON/mac_messages_types.h | 23 ++ openair2/LAYER2/MAC/config.c | 8 + openair2/LAYER2/MAC/eNB_scheduler.c | 5 +- openair2/LAYER2/MAC/eNB_scheduler_bch.c | 454 ++++++++++++++++++++++ openair2/LAYER2/MAC/mac.h | 19 + openair2/LAYER2/MAC/mac_proto.h | 16 + openair2/LAYER2/MAC/ue_procedures.c | 39 ++ openair2/RRC/LTE/L2_interface.c | 20 + openair2/RRC/LTE/L2_interface_ue.c | 35 ++ openair2/RRC/LTE/MESSAGES/asn1_msg.c | 303 +++++++++++++++ openair2/RRC/LTE/MESSAGES/asn1_msg.h | 20 + openair2/RRC/LTE/rrc_UE.c | 126 ++++++ openair2/RRC/LTE/rrc_defs.h | 17 + openair2/RRC/LTE/rrc_proto.h | 10 + 16 files changed, 1117 insertions(+), 2 deletions(-) diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index d9c6744069..2008e0b25f 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -3413,12 +3413,31 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, break; case SI_PDSCH: - ue_decode_si(ue->Mod_id, +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + if(subframe_rx == 0 /*&& fembms_flag*/) { //TODO MBMS //Just check SI at subframe 0 for FeMBMS + ue_decode_si_mbms(ue->Mod_id, CC_id, frame_rx, eNB_id, ue->dlsch_SI[eNB_id]->harq_processes[0]->b, ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3); + + } else { + ue_decode_si(ue->Mod_id, + CC_id, + frame_rx, + eNB_id, + ue->dlsch_SI[eNB_id]->harq_processes[0]->b, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3); + } +#else + ue_decode_si(ue->Mod_id, + CC_id, + frame_rx, + eNB_id, + ue->dlsch_SI[eNB_id]->harq_processes[0]->b, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3); +#endif break; case P_PDSCH: diff --git a/openair2/COMMON/mac_messages_def.h b/openair2/COMMON/mac_messages_def.h index fcb4543149..f69186e4b8 100644 --- a/openair2/COMMON/mac_messages_def.h +++ b/openair2/COMMON/mac_messages_def.h @@ -34,6 +34,9 @@ MESSAGE_DEF(RRC_MAC_OUT_OF_SYNC_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacOutOfSy MESSAGE_DEF(RRC_MAC_BCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcMacBcchDataReq, rrc_mac_bcch_data_req) MESSAGE_DEF(RRC_MAC_BCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacBcchDataInd, rrc_mac_bcch_data_ind) +MESSAGE_DEF(RRC_MAC_BCCH_MBMS_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcMacBcchMbmsDataReq, rrc_mac_bcch_mbms_data_req) +MESSAGE_DEF(RRC_MAC_BCCH_MBMS_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacBcchMbmsDataInd, rrc_mac_bcch_mbms_data_ind) + MESSAGE_DEF(RRC_MAC_CCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcMacCcchDataReq, rrc_mac_ccch_data_req) MESSAGE_DEF(RRC_MAC_CCCH_DATA_CNF, MESSAGE_PRIORITY_MED_PLUS, RrcMacCcchDataCnf, rrc_mac_ccch_data_cnf) MESSAGE_DEF(RRC_MAC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacCcchDataInd, rrc_mac_ccch_data_ind) diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index d7fd44f072..3bbea66d0d 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -37,6 +37,9 @@ #define RRC_MAC_BCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_data_req #define RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_data_ind +#define RRC_MAC_BCCH_MBMS_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_req +#define RRC_MAC_BCCH_MBMS_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_ind + #define RRC_MAC_CCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_ccch_data_req #define RRC_MAC_CCCH_DATA_CNF(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_ccch_data_cnf #define RRC_MAC_CCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_ccch_data_ind @@ -47,6 +50,7 @@ // Some constants from "LAYER2/MAC/defs.h" #define BCCH_SDU_SIZE (512) +#define BCCH_SDU_MBMS_SIZE (512) #define CCCH_SDU_SIZE (512) #define MCCH_SDU_SIZE (512) #define PCCH_SDU_SIZE (512) @@ -78,6 +82,25 @@ typedef struct RrcMacBcchDataInd_s { uint8_t rsrp; } RrcMacBcchDataInd; + +typedef struct RrcMacBcchMbmsDataReq_s { + uint32_t frame; + uint32_t sdu_size; + uint8_t sdu[BCCH_SDU_MBMS_SIZE]; + uint8_t enb_index; +} RrcMacBcchMbmsDataReq; + +typedef struct RrcMacBcchMbmsDataInd_s { + uint32_t frame; + uint8_t sub_frame; + uint32_t sdu_size; + uint8_t sdu[BCCH_SDU_MBMS_SIZE]; + uint8_t enb_index; + uint8_t rsrq; + uint8_t rsrp; +} RrcMacBcchMbmsDataInd; + + typedef struct RrcMacCcchDataReq_s { uint32_t frame; uint32_t sdu_size; diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index 3252bb6b92..fb1aea48cc 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -831,6 +831,14 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, RC.mac[Mod_idP]->common_channels[CC_idP].schedulingInfoList = schedulingInfoList; config_sib1(Mod_idP,CC_idP,tdd_Config); } + +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) //TODO MBMS this must be passed through function + /*if (schedulingInfoList_MBMS!=NULL) { + RC.mac[Mod_idP]->common_channels[CC_idP].schedulingInfoList_MBMS = schedulingInfoList_MBMS; + config_sib1_mbms(Mod_idP,CC_idP,tdd_Config); + }*/ +#endif + #if (LTE_RRC_VERSION >= MAKE_VERSION(13, 0, 0)) if (sib1_v13ext != NULL) { RC.mac[Mod_idP]->common_channels[CC_idP].sib1_v13ext = sib1_v13ext; diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 4ebe7313e8..a9036f61c5 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -658,8 +658,11 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, } // This schedules MIB - if ((subframeP == 0) && (frameP & 3) == 0) + if ((subframeP == 0) && (frameP & 3) == 0) { schedule_mib(module_idP, frameP, subframeP); + + //schedule_SI_MBMS(module_idP, frameP, subframeP); + } if (get_softmodem_params()->phy_test == 0){ // This schedules SI for legacy LTE and eMTC starting in subframeP schedule_SI(module_idP, frameP, subframeP); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c index 339d4102aa..ab24544f2c 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c @@ -75,6 +75,233 @@ int Sj100[size_Sj100] = { 0, 1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 13, 14, 15 }; int SIB1_BR_TBS_table[6] = { 208, 256, 328, 504, 712, 936 }; +//------------------------------------------------------------------------------ +void +schedule_SIB1_MBMS(module_id_t module_idP, + frame_t frameP, sub_frame_t subframeP) +//------------------------------------------------------------------------------ +{ + int8_t bcch_sdu_length; + int CC_id; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc; + uint8_t *vrb_map; + int first_rb = -1; + int N_RB_DL; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_tx_request_pdu_t *TX_req; + nfapi_dl_config_request_body_t *dl_req; + int m, i, N_S_NB; + int *Sj; + int n_NB = 0; + int TBS; + int k = 0, rvidx; + uint16_t sfn_sf = frameP<<4|subframeP; + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + + cc = &eNB->common_channels[CC_id]; + vrb_map = (void *) &cc->vrb_map; + N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); + dl_req = &eNB->DL_req[CC_id].dl_config_request_body; + + int foffset = cc->physCellId & 1; + int sfoffset = (cc->tdd_Config == NULL) ? 0 : 1; + + // Time-domain scheduling + if (cc->mib->message.schedulingInfoSIB1_BR_r13 == 0) + continue; + else + switch ((cc->mib->message.schedulingInfoSIB1_BR_r13 - 1) % 3) { + case 0: // repetition 4 + k = (frameP >> 1) & 3; + if ((subframeP != (4 + sfoffset)) + || ((frameP & 1) != foffset)) + continue; + break; + case 1: // repetition 8 + k = frameP & 3; + AssertFatal(N_RB_DL > 15, + "SIB1-BR repetition 8 not allowed for N_RB_DL= %d\n", + N_RB_DL); + if ((foffset == 0) && (subframeP != (4 + sfoffset))) + continue; + else if ((foffset == 1) + && (subframeP != ((9 + sfoffset) % 10))) + continue; + break; + case 2: // repetition 16 + k = ((10 * frameP) + subframeP) & 3; + AssertFatal(N_RB_DL > 15, + "SIB1-BR repetition 16 not allowed for N_RB_DL= %d\n", + N_RB_DL); + if ((sfoffset == 1) + && ((subframeP != 0) || (subframeP != 5))) + continue; + else if ((sfoffset == 0) && (foffset == 0) + && (subframeP != 4) && (subframeP != 9)) + continue; + else if ((sfoffset == 0) && (foffset == 1) + && (subframeP != 0) && (subframeP != 9)) + continue; + break; + } + // if we get here we have to schedule SIB1_BR in this frame/subframe + + // keep counter of SIB1_BR repetitions in 8 frame period to choose narrowband on which to transmit + if ((frameP & 7) == 0) + cc->SIB1_BR_cnt = 0; + else + cc->SIB1_BR_cnt++; + + // Frequency-domain scheduling + switch (N_RB_DL) { + case 6: + case 15: + default: + m = 1; + n_NB = 0; + N_S_NB = 0; + Sj = NULL; + break; + case 25: + m = 2; + N_S_NB = 2; + Sj = Sj25; + break; + case 50: + m = 2; + N_S_NB = 6; + Sj = Sj50; + break; + case 75: + m = 4; + N_S_NB = 10; + Sj = Sj75; + break; + case 100: + m = 4; + N_S_NB = 14; + Sj = Sj100; + break; + } + // Note: definition of k above and rvidx from 36.321 section 5.3.1 + rvidx = (((3 * k) >> 1) + (k & 1)) & 3; + + i = cc->SIB1_BR_cnt & (m - 1); + + n_NB = Sj[((cc->physCellId % N_S_NB) + (i * N_S_NB / m)) % N_S_NB]; + + + bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SIB1_BR, 1, &cc->BCCH_BR_pdu[0].payload[0], 0); // not used in this case + + AssertFatal(cc->mib->message.schedulingInfoSIB1_BR_r13 < 19, + "schedulingInfoSIB1_BR_r13 %d > 18\n", + (int) cc->mib->message.schedulingInfoSIB1_BR_r13); + + AssertFatal(bcch_sdu_length > 0, + "RRC returned 0 bytes for SIB1-BR\n"); + + TBS = + SIB1_BR_TBS_table[(cc->mib->message.schedulingInfoSIB1_BR_r13 - + 1) / 3] >> 3; + + AssertFatal(bcch_sdu_length <= TBS, + "length returned by RRC %d is not compatible with the TBS %d from MIB\n", + bcch_sdu_length, TBS); + + if ((frameP & 1023) < 200) + LOG_D(MAC, + "[eNB %d] Frame %d Subframe %d: SIB1_BR->DLSCH CC_id %d, Received %d bytes, scheduling on NB %d (i %d,m %d,N_S_NB %d) rvidx %d\n", + module_idP, frameP, subframeP, CC_id, bcch_sdu_length, + n_NB, i, m, N_S_NB, rvidx); + + // allocate all 6 PRBs in narrowband for SIB1_BR + + first_rb = narrowband_to_first_rb(cc, n_NB); + + vrb_map[first_rb] = 1; + vrb_map[first_rb + 1] = 1; + vrb_map[first_rb + 2] = 1; + vrb_map[first_rb + 3] = 1; + vrb_map[first_rb + 4] = 1; + vrb_map[first_rb + 5] = 1; + + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = TBS; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 6); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = rvidx; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB == 1) ? 0 : 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB == 1) ? 1 : 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; + // Rel10 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3; + // Rel13 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = 1; // CEModeA UE + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 0; // SIB1-BR + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SFx + + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + dl_req->number_pdu++; + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + + // Program TX Request + TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; + TX_req->pdu_length = bcch_sdu_length; + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = bcch_sdu_length; + TX_req->segments[0].segment_data = cc->BCCH_BR_pdu[0].payload; + eNB->TX_req[CC_id].sfn_sf = sfn_sf; + eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG; + eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; + eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST; + + if (opt_enabled == 1) { + trace_pdu(DIRECTION_DOWNLINK, + &cc->BCCH_BR_pdu[0].payload[0], + bcch_sdu_length, + 0xffff, WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0); + LOG_D(OPT, + "[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", + module_idP, frameP, CC_id, 0xffff, bcch_sdu_length); + } + if (cc->tdd_Config != NULL) { //TDD + LOG_D(MAC, + "[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (TDD) for CC_id %d SIB1-BR %d bytes\n", + frameP, CC_id, bcch_sdu_length); + } else { + LOG_D(MAC, + "[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (FDD) for CC_id %d SIB1-BR %d bytes\n", + frameP, CC_id, bcch_sdu_length); + } + } +} + + //------------------------------------------------------------------------------ void schedule_SIB1_BR(module_id_t module_idP, @@ -304,6 +531,8 @@ schedule_SIB1_BR(module_id_t module_idP, int si_WindowLength_BR_r13tab[LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_spare] = { 20, 40, 60, 80, 120, 160, 200 }; int si_TBS_r13tab[LTE_SchedulingInfo_BR_r13__si_TBS_r13_b936 + 1] = { 152, 208, 256, 328, 408, 504, 600, 712, 808, 936 }; +int si_WindowLength_MBMS_r14tab[8] = { 1, 2, 5, 10, 15, 20, 40, 80 }; + //------------------------------------------------------------------------------ void schedule_SI_BR(module_id_t module_idP, frame_t frameP, @@ -494,6 +723,231 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP, } // CC_id return; } + + +//------------------------------------------------------------------------------ +void +schedule_SI_MBMS(module_id_t module_idP, frame_t frameP, + sub_frame_t subframeP) +//------------------------------------------------------------------------------ +{ + int8_t bcch_sdu_length; + int mcs = -1; + int CC_id; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc; + uint8_t *vrb_map; + int first_rb = -1; + int N_RB_DL; + nfapi_dl_config_request_t *dl_config_request; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_tx_request_pdu_t *TX_req; + nfapi_dl_config_request_body_t *dl_req; + uint16_t sfn_sf = frameP << 4 | subframeP; + + start_meas(&eNB->schedule_si_mbms); + + // Only schedule LTE System Information in subframe 0 + if (subframeP == 0) { + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + + cc = &eNB->common_channels[CC_id]; + vrb_map = (void *) &cc->vrb_map; + N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); + dl_config_request = &eNB->DL_req[CC_id]; + dl_req = &eNB->DL_req[CC_id].dl_config_request_body; + + + bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SI_MBMS, 1, &cc->BCCH_MBMS_pdu.payload[0], 0); // not used in this case + + if (bcch_sdu_length > 0) { + LOG_D(MAC, "[eNB %d] Frame %d : BCCH-MBMS->DLSCH CC_id %d, Received %d bytes \n", module_idP, frameP, CC_id, bcch_sdu_length); + + // Allocate 4 PRBs in a random location + /* + while (1) { + first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL-4)); + if ((vrb_map[first_rb] != 1) && + (vrb_map[first_rb+1] != 1) && + (vrb_map[first_rb+2] != 1) && + (vrb_map[first_rb+3] != 1)) + break; + } + */ + switch (N_RB_DL) { + case 6: + first_rb = 0; + break; + case 15: + first_rb = 6; + break; + case 25: + first_rb = 11; + break; + case 50: + first_rb = 23; + break; + case 100: + first_rb = 48; + break; + } + + vrb_map[first_rb] = 1; + vrb_map[first_rb + 1] = 1; + vrb_map[first_rb + 2] = 1; + vrb_map[first_rb + 3] = 1; + + // Get MCS for length of SI, 3 PRBs + if (bcch_sdu_length <= 7) { + mcs = 0; + } else if (bcch_sdu_length <= 11) { + mcs = 1; + } else if (bcch_sdu_length <= 18) { + mcs = 2; + } else if (bcch_sdu_length <= 22) { + mcs = 3; + } else if (bcch_sdu_length <= 26) { + mcs = 4; + } else if (bcch_sdu_length <= 28) { + mcs = 5; + } else if (bcch_sdu_length <= 32) { + mcs = 6; + } else if (bcch_sdu_length <= 41) { + mcs = 7; + } else if (bcch_sdu_length <= 49) { + mcs = 8; + } + + + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = 0xFFFF; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // S-RNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4); + dl_config_request->sfn_sf = sfn_sf; + + if (!CCE_allocation_infeasible(module_idP, CC_id, 0, subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, SI_RNTI)) { + LOG_D(MAC, "Frame %d: Subframe %d : Adding common DCI for S_RNTI MBMS\n", frameP, subframeP); + dl_req->number_dci++; + dl_req->number_pdu++; + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = bcch_sdu_length; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB == 1) ? 0 : 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB == 1) ? 1 : 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + dl_req->number_pdu++; + + // Rel10 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3; + // Rel13 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = 0; // regular UE + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not BR + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SF + + dl_config_request->header.message_id = NFAPI_DL_CONFIG_REQUEST; + dl_config_request->sfn_sf = sfn_sf; + + // Program TX Request + TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; + TX_req->pdu_length = bcch_sdu_length; + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = bcch_sdu_length; + TX_req->segments[0].segment_data = cc->BCCH_MBMS_pdu.payload; + eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; + eNB->TX_req[CC_id].sfn_sf = sfn_sf; + eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG; + eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST; + + } else { + LOG_E(MAC, + "[eNB %d] CCid %d Frame %d, subframe %d : Cannot add DCI 1A for SI MBMS\n", + module_idP, CC_id, frameP, subframeP); + } + + T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(0xffff), + T_INT(frameP), T_INT(subframeP), T_INT(0), T_BUFFER(cc->BCCH_MBMS_pdu.payload, bcch_sdu_length)); + + if (opt_enabled == 1) { + trace_pdu(DIRECTION_DOWNLINK, + &cc->BCCH_MBMS_pdu.payload[0], + bcch_sdu_length, + 0xffff, + WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0); + LOG_D(OPT, + "[eNB %d][BCH-MBMS] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", + module_idP, frameP, CC_id, 0xffff, + bcch_sdu_length); + } + if (0/*cc->tdd_Config != NULL*/) { //TDD not for FeMBMS + LOG_D(MAC, + "[eNB] Frame %d : Scheduling BCCH->DLSCH (TDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", + frameP, CC_id, bcch_sdu_length, mcs); + } else { + LOG_D(MAC, "[eNB] Frame %d : Scheduling BCCH->DLSCH (FDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", frameP, CC_id, bcch_sdu_length, mcs); + } + + + eNB->eNB_stats[CC_id].total_num_bcch_pdu += 1; + eNB->eNB_stats[CC_id].bcch_buffer = bcch_sdu_length; + eNB->eNB_stats[CC_id].total_bcch_buffer += bcch_sdu_length; + eNB->eNB_stats[CC_id].bcch_mcs = mcs; +//printf("SI %d.%d\n", frameP, subframeP);/////////////////////////////////////////****************************** + } else { + + //LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame); + } + } + } +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + //schedule_SIB1_BR(module_idP, frameP, subframeP); + //schedule_SI_BR(module_idP, frameP, subframeP); +#endif + + stop_meas(&eNB->schedule_si_mbms); + + +} #endif void diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 5511216678..638738db32 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -66,6 +66,12 @@ #include "LTE_SystemInformationBlockType1-v1310-IEs.h" #include "LTE_SystemInformationBlockType18-r12.h" #endif +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) +#include "LTE_BCCH-BCH-Message-MBMS.h" +#include "LTE_BCCH-DL-SCH-Message-MBMS.h" +#include "LTE_SystemInformationBlockType1-MBMS-r14.h" +#include "LTE_NonMBSFN-SubframeConfig-r14.h" +#endif #include "LTE_RadioResourceConfigCommonSIB.h" #include "nfapi_interface.h" #include "PHY_INTERFACE/IF_Module.h" @@ -415,6 +421,11 @@ typedef struct { #define BCCH_SIB1_BR 6 // SIB1_BR /*!\brief Values of BCCH SIB_BR logical channel (fake) */ #define BCCH_SI_BR 7 // SI-BR +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) +/*!\brief Values of BCCH SIB1_BR logical channel (fake) */ +#define BCCH_SIB1_MBMS 60 // SIB1_MBMS //TODO better armonize index +#define BCCH_SI_MBMS 61 // SIB_MBMS //TODO better armonize index +#endif /*!\brief Value of CCCH / SRB0 logical channel */ #define CCCH 0 // srb0 /*!\brief DCCH / SRB1 logical channel */ @@ -1244,6 +1255,7 @@ typedef struct { LTE_RadioResourceConfigCommonSIB_t *radioResourceConfigCommon; #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) LTE_RadioResourceConfigCommonSIB_t *radioResourceConfigCommon_BR; + LTE_SchedulingInfoList_MBMS_r14_t *schedulingInfoList_MBMS; #endif LTE_TDD_Config_t *tdd_Config; LTE_SchedulingInfoList_t *schedulingInfoList; @@ -1303,6 +1315,10 @@ typedef struct { /// Outgoing BCCH-BR pdu for PHY BCCH_PDU BCCH_BR_pdu[20]; #endif +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + BCCH_PDU BCCH_MBMS_pdu; +#endif + } COMMON_channels_t; /*! \brief top level eNB MAC structure */ typedef struct eNB_MAC_INST_s { @@ -1370,6 +1386,9 @@ typedef struct eNB_MAC_INST_s { time_stats_t eNB_scheduler; /// processing time of eNB scheduler for SI time_stats_t schedule_si; +#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) + time_stats_t schedule_si_mbms; +#endif /// processing time of eNB scheduler for Random access time_stats_t schedule_ra; /// processing time of eNB ULSCH scheduler diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 883010e8d5..6a6ead84be 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -67,6 +67,17 @@ void schedule_RA(module_id_t module_idP, frame_t frameP, void schedule_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) +/** \brief First stage of SI Scheduling. Gets a SI SDU from RRC if available and computes the MCS required to transport it as a function of the SDU length. It assumes a length less than or equal to 64 bytes (MCS 6, 3 PRBs). +@param Mod_id Instance ID of eNB +@param frame Frame index +@param subframe Subframe number on which to act +*/ +void schedule_SI_MBMS(module_id_t module_idP, frame_t frameP, + sub_frame_t subframeP); +#endif + + /** \brief MBMS scheduling: Checking the position for MBSFN subframes. Create MSI, transfer MCCH from RRC to MAC, transfer MTCHs from RLC to MAC. Multiplexing MSI,MCCH&MTCHs. Return 1 if there are MBSFN data being allocated, otherwise return 0; @param Mod_id Instance ID of eNB @param frame Frame index @@ -539,6 +550,11 @@ void mac_out_of_sync_ind(module_id_t module_idP, frame_t frameP, void ue_decode_si(module_id_t module_idP, int CC_id, frame_t frame, uint8_t CH_index, void *pdu, uint16_t len); +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) +void ue_decode_si_mbms(module_id_t module_idP, int CC_id, frame_t frame, + uint8_t CH_index, void *pdu, uint16_t len); +#endif + void ue_decode_p(module_id_t module_idP, int CC_id, frame_t frame, uint8_t CH_index, void *pdu, uint16_t len); diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index bca5ef0ae8..ddfe7cb54d 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -618,6 +618,45 @@ ue_send_sdu(module_id_t module_idP, #endif } +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) +void +ue_decode_si_mbms(module_id_t module_idP, int CC_id, frame_t frameP, + uint8_t eNB_index, void *pdu, uint16_t len) +{ +#if UE_TIMING_TRACE + start_meas(&UE_mac_inst[module_idP].rx_si); +#endif + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_IN); + + LOG_D(MAC, "[UE %d] Frame %d Sending SI MBMS to RRC (LCID Id %d,len %d)\n", + module_idP, frameP, BCCH, len); + + mac_rrc_data_ind_ue(module_idP, CC_id, frameP, 0, // unknown subframe + SI_RNTI, + BCCH_SI_MBMS, (uint8_t *) pdu, len, eNB_index, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_OUT); +#if UE_TIMING_TRACE + stop_meas(&UE_mac_inst[module_idP].rx_si); +#endif + if (opt_enabled == 1) { + trace_pdu(DIRECTION_UPLINK, + (uint8_t *) pdu, + len, + module_idP, + WS_SI_RNTI, + 0xffff, + UE_mac_inst[module_idP].rxFrame, + UE_mac_inst[module_idP].rxSubframe, 0, 0); + LOG_D(OPT, + "[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", + module_idP, frameP, CC_id, 0xffff, len); + } +} +#endif + void ue_decode_si(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_index, void *pdu, uint16_t len) diff --git a/openair2/RRC/LTE/L2_interface.c b/openair2/RRC/LTE/L2_interface.c index 5929ac6689..4b57a4f5f9 100644 --- a/openair2/RRC/LTE/L2_interface.c +++ b/openair2/RRC/LTE/L2_interface.c @@ -75,6 +75,26 @@ mac_rrc_data_req( carrier = &rrc->carrier[0]; mib = &carrier->mib; + if(Srb_id == BCCH_SI_MBMS){ + if (frameP%4 == 0){ + memcpy(&buffer_pP[0], + RC.rrc[Mod_idP]->carrier[CC_id].SIB1_MBMS, + RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1_MBMS); + + if (LOG_DEBUGFLAG(DEBUG_RRC)) { + LOG_T(RRC,"[eNB %d] Frame %d : BCCH request => SIB 1 MBMS\n",Mod_idP,frameP); + + for (int i=0; icarrier[CC_id].sizeof_SIB1_MBMS; i++) { + LOG_T(RRC,"%x.",buffer_pP[i]); + } + + LOG_T(RRC,"\n"); + } /* LOG_DEBUGFLAG(DEBUG_RRC) */ + + return (RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1_MBMS); + } + } + if((Srb_id & RAB_OFFSET) == BCCH) { if(RC.rrc[Mod_idP]->carrier[CC_id].SI.Active==0) { return 0; diff --git a/openair2/RRC/LTE/L2_interface_ue.c b/openair2/RRC/LTE/L2_interface_ue.c index 9dfbeed61e..b6cde649ee 100644 --- a/openair2/RRC/LTE/L2_interface_ue.c +++ b/openair2/RRC/LTE/L2_interface_ue.c @@ -145,6 +145,41 @@ mac_rrc_data_ind_ue( */ PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, 0, rntiP, frameP, sub_frameP,eNB_indexP); +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + if(srb_idP == BCCH_SI_MBMS) { + LOG_D(RRC,"[UE %d] Received SDU for BCCH on MBMS SRB %d from eNB %d\n",module_idP,srb_idP,eNB_indexP); + +#if defined(ENABLE_ITTI) + { + MessageDef *message_p; + int msg_sdu_size = sizeof(RRC_MAC_BCCH_MBMS_DATA_IND (message_p).sdu); + + if (sdu_lenP > msg_sdu_size) { + LOG_E(RRC, "SDU larger than BCCH SDU buffer size (%d, %d)", sdu_lenP, msg_sdu_size); + sdu_size = msg_sdu_size; + } else { + sdu_size = sdu_lenP; + } + + message_p = itti_alloc_new_message (TASK_MAC_UE, RRC_MAC_BCCH_MBMS_DATA_IND); + memset (RRC_MAC_BCCH_MBMS_DATA_IND (message_p).sdu, 0, BCCH_SDU_MBMS_SIZE); + RRC_MAC_BCCH_MBMS_DATA_IND (message_p).frame = frameP; + RRC_MAC_BCCH_MBMS_DATA_IND (message_p).sub_frame = sub_frameP; + RRC_MAC_BCCH_MBMS_DATA_IND (message_p).sdu_size = sdu_size; + memcpy (RRC_MAC_BCCH_MBMS_DATA_IND (message_p).sdu, sduP, sdu_size); + RRC_MAC_BCCH_MBMS_DATA_IND (message_p).enb_index = eNB_indexP; + RRC_MAC_BCCH_MBMS_DATA_IND (message_p).rsrq = 30 /* TODO change phy to report rspq */; + RRC_MAC_BCCH_MBMS_DATA_IND (message_p).rsrp = 45 /* TODO change phy to report rspp */; + + itti_send_msg_to_task (TASK_RRC_UE, ctxt.instance, message_p); + } +#else + decode_BCCH_MBMS_DLSCH_Message(&ctxt,eNB_indexP,(uint8_t*)sduP,sdu_lenP, 0, 0); +#endif + } +#endif + + if(srb_idP == BCCH) { LOG_D(RRC,"[UE %d] Received SDU for BCCH on SRB %d from eNB %d\n",module_idP,srb_idP,eNB_indexP); diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c index 0bb11fa037..5d1171e58f 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c @@ -76,6 +76,13 @@ #include "LTE_SBCCH-SL-BCH-MessageType.h" #include "LTE_SBCCH-SL-BCH-Message.h" +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + #include "LTE_BCCH-BCH-Message-MBMS.h" + #include "LTE_BCCH-DL-SCH-Message-MBMS.h" + #include "LTE_SystemInformationBlockType1-MBMS-r14.h" + #include "LTE_NonMBSFN-SubframeConfig-r14.h" +#endif + //#include "PHY/defs.h" #include "LTE_MeasObjectToAddModList.h" @@ -175,6 +182,88 @@ uint8_t get_adjacent_cell_mod_id(uint16_t phyCellId) { return 0xFF; //error! } +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) +uint8_t do_MIB_FeMBMS(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_t additionalNonMBSFN, uint32_t frame) { + asn_enc_rval_t enc_rval; + LTE_BCCH_BCH_Message_MBMS_t *mib_fembms=&carrier->mib_fembms; + uint8_t sfn = (uint8_t)((frame>>2)&0xff); + uint16_t *spare = calloc(1,sizeof(uint16_t)); + uint16_t *additionalNonMBSFNSubframes = calloc(1,sizeof(uint16_t)); + + if( spare == NULL || additionalNonMBSFNSubframes == NULL ) abort(); + + switch (N_RB_DL) { + case 6: + mib_fembms->message.dl_Bandwidth_MBMS_r14 = LTE_MasterInformationBlock_MBMS_r14__dl_Bandwidth_MBMS_r14_n6; + break; + + case 15: + mib_fembms->message.dl_Bandwidth_MBMS_r14 = LTE_MasterInformationBlock_MBMS_r14__dl_Bandwidth_MBMS_r14_n15; + break; + + case 25: + mib_fembms->message.dl_Bandwidth_MBMS_r14 = LTE_MasterInformationBlock_MBMS_r14__dl_Bandwidth_MBMS_r14_n25; + break; + + case 50: + mib_fembms->message.dl_Bandwidth_MBMS_r14 = LTE_MasterInformationBlock_MBMS_r14__dl_Bandwidth_MBMS_r14_n50; + break; + + case 75: + mib_fembms->message.dl_Bandwidth_MBMS_r14 = LTE_MasterInformationBlock_MBMS_r14__dl_Bandwidth_MBMS_r14_n75; + break; + + case 100: + mib_fembms->message.dl_Bandwidth_MBMS_r14 = LTE_MasterInformationBlock_MBMS_r14__dl_Bandwidth_MBMS_r14_n100; + break; + + default: + AssertFatal(1==0,"Unknown dl_Bandwidth %d\n",N_RB_DL); + } + LOG_I(RRC,"[MIB] systemBandwidth %x, additional non MBMS subframes %x, sfn %x\n", + (uint32_t)mib_fembms->message.dl_Bandwidth_MBMS_r14, + (uint32_t)additionalNonMBSFN, + (uint32_t)sfn); + + + mib_fembms->message.systemFrameNumber_r14.buf = &sfn; + mib_fembms->message.systemFrameNumber_r14.size = 1; + mib_fembms->message.systemFrameNumber_r14.bits_unused=0; + mib_fembms->message.spare.buf = (uint8_t *)spare; +//#if (LTE_RRC_VERSION < MAKE_VERSION(14, 0, 0)) + mib_fembms->message.spare.size = 2; + mib_fembms->message.spare.bits_unused = 6; // This makes a spare of 10 bits +//#else + //mib->message.spare.size = 1; + //mib->message.spare.bits_unused = 3; // This makes a spare of 5 bits + //mib->message.schedulingInfoSIB1_BR_r13 = 0; // turn off eMTC +//#endif + + //TODO additionalNonBMSFNSubframes-r14 INTEGER (0..3) ? + + //if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_LTE_BCCH_BCH_Message_MBMS, (void *)mib_fembms); + //} + + + + enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_BCH_Message_MBMS, + NULL, + (void *)mib_fembms, + carrier->MIB_FeMBMS, + 24); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + + if (enc_rval.encoded==-1) { + return(-1); + } + + return((enc_rval.encoded+7)/8); + +} +#endif + uint8_t do_MIB(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_t phich_Resource, uint32_t phich_duration, uint32_t frame #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) @@ -315,6 +404,220 @@ uint8_t do_MIB_SL(const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, return((enc_rval.encoded+7)/8); } +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) +uint8_t do_SIB1_MBMS(rrc_eNB_carrier_data_t *carrier, + int Mod_id,int CC_id +#if defined(ENABLE_ITTI) + , RrcConfigurationReq *configuration +#endif + ) { + // SystemInformation_t systemInformation; +#if defined(ENABLE_ITTI) + int num_plmn = configuration->num_plmn; +#else + int num_plmn = 1; +#endif + LTE_PLMN_IdentityInfo_t PLMN_identity_info[num_plmn]; + LTE_MCC_MNC_Digit_t dummy_mcc[num_plmn][3], dummy_mnc[num_plmn][3]; + asn_enc_rval_t enc_rval; + LTE_SchedulingInfo_MBMS_r14_t schedulingInfo; + LTE_SIB_Type_t sib_type; + uint8_t *buffer = carrier->SIB1_MBMS; + LTE_BCCH_DL_SCH_Message_MBMS_t *bcch_message = &carrier->siblock1_MBMS; + LTE_SystemInformationBlockType1_MBMS_r14_t **sib1_MBMS = &carrier->sib1_MBMS; + + int i; + //LTE_NonMBSFN_SubframeConfig_r14 nonMBSFN_SubframeConfig_r14; + + struct LTE_MBSFN_AreaInfo_r9 *MBSFN_Area1, *MBSFN_Area2; + struct LTE_NonMBSFN_SubframeConfig_r14 nonMBSFN_SubframeConfig_r14; + + memset(bcch_message,0,sizeof(LTE_BCCH_DL_SCH_Message_MBMS_t)); + bcch_message->message.present = LTE_BCCH_DL_SCH_MessageType_MBMS_r14_PR_c1; + bcch_message->message.choice.c1.present = LTE_BCCH_DL_SCH_MessageType_MBMS_r14__c1_PR_systemInformationBlockType1_MBMS_r14; + // memcpy(&bcch_message.message.choice.c1.choice.systemInformationBlockType1,sib1,sizeof(SystemInformationBlockType1_t)); + *sib1_MBMS = &bcch_message->message.choice.c1.choice.systemInformationBlockType1_MBMS_r14; + memset(PLMN_identity_info,0,num_plmn * sizeof(LTE_PLMN_IdentityInfo_t)); + memset(&schedulingInfo,0,sizeof(LTE_SchedulingInfo_MBMS_r14_t)); + memset(&sib_type,0,sizeof(LTE_SIB_Type_t)); + memset(&nonMBSFN_SubframeConfig_r14,0,sizeof(struct LTE_NonMBSFN_SubframeConfig_r14)); + + /* as per TS 36.311, up to 6 PLMN_identity_info are allowed in list -> add one by one */ + for (i = 0; i < configuration->num_plmn; ++i) { + PLMN_identity_info[i].plmn_Identity.mcc = CALLOC(1,sizeof(*PLMN_identity_info[i].plmn_Identity.mcc)); + memset(PLMN_identity_info[i].plmn_Identity.mcc,0,sizeof(*PLMN_identity_info[i].plmn_Identity.mcc)); + asn_set_empty(&PLMN_identity_info[i].plmn_Identity.mcc->list);//.size=0; +#if defined(ENABLE_ITTI) + dummy_mcc[i][0] = (configuration->mcc[i] / 100) % 10; + dummy_mcc[i][1] = (configuration->mcc[i] / 10) % 10; + dummy_mcc[i][2] = (configuration->mcc[i] / 1) % 10; +#else + dummy_mcc[i][0] = 0; + dummy_mcc[i][1] = 0; + dummy_mcc[i][2] = 1; +#endif + ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mcc->list,&dummy_mcc[i][0]); + ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mcc->list,&dummy_mcc[i][1]); + ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mcc->list,&dummy_mcc[i][2]); + PLMN_identity_info[i].plmn_Identity.mnc.list.size=0; + PLMN_identity_info[i].plmn_Identity.mnc.list.count=0; +#if defined(ENABLE_ITTI) + + if (configuration->mnc[i] >= 100) { + dummy_mnc[i][0] = (configuration->mnc[i] / 100) % 10; + dummy_mnc[i][1] = (configuration->mnc[i] / 10) % 10; + dummy_mnc[i][2] = (configuration->mnc[i] / 1) % 10; + } else { + if (configuration->mnc_digit_length[i] == 2) { + dummy_mnc[i][0] = (configuration->mnc[i] / 10) % 10; + dummy_mnc[i][1] = (configuration->mnc[i] / 1) % 10; + dummy_mnc[i][2] = 0xf; + } else { + dummy_mnc[i][0] = (configuration->mnc[i] / 100) % 100; + dummy_mnc[i][1] = (configuration->mnc[i] / 10) % 10; + dummy_mnc[i][2] = (configuration->mnc[i] / 1) % 10; + } + } + +#else + dummy_mnc[i][0] = 0; + dummy_mnc[i][1] = 1; + dummy_mnc[i][2] = 0xf; +#endif + ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mnc.list,&dummy_mnc[i][0]); + ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mnc.list,&dummy_mnc[i][1]); + + if (dummy_mnc[i][2] != 0xf) { + ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mnc.list,&dummy_mnc[i][2]); + } + + //assign_enum(&PLMN_identity_info.cellReservedForOperatorUse,PLMN_IdentityInfo__cellReservedForOperatorUse_notReserved); + PLMN_identity_info[i].cellReservedForOperatorUse=LTE_PLMN_IdentityInfo__cellReservedForOperatorUse_notReserved; + ASN_SEQUENCE_ADD(&(*sib1_MBMS)->cellAccessRelatedInfo_r14.plmn_IdentityList_r14.list,&PLMN_identity_info[i]); + } + + // 16 bits + (*sib1_MBMS)->cellAccessRelatedInfo_r14.trackingAreaCode_r14.buf = MALLOC(2); +#if defined(ENABLE_ITTI) + (*sib1_MBMS)->cellAccessRelatedInfo_r14.trackingAreaCode_r14.buf[0] = (configuration->tac >> 8) & 0xff; + (*sib1_MBMS)->cellAccessRelatedInfo_r14.trackingAreaCode_r14.buf[1] = (configuration->tac >> 0) & 0xff; +#else + (*sib1_MBMS)->cellAccessRelatedInfo_r14.trackingAreaCode_r14.buf[0] = 0x00; + (*sib1_MBMS)->cellAccessRelatedInfo_r14.trackingAreaCode_r14.buf[1] = 0x01; +#endif + (*sib1_MBMS)->cellAccessRelatedInfo_r14.trackingAreaCode_r14.size=2; + (*sib1_MBMS)->cellAccessRelatedInfo_r14.trackingAreaCode_r14.bits_unused=0; + // 28 bits + (*sib1_MBMS)->cellAccessRelatedInfo_r14.cellIdentity_r14.buf = MALLOC(8); +#if defined(ENABLE_ITTI) + (*sib1_MBMS)->cellAccessRelatedInfo_r14.cellIdentity_r14.buf[0] = (configuration->cell_identity >> 20) & 0xff; + (*sib1_MBMS)->cellAccessRelatedInfo_r14.cellIdentity_r14.buf[1] = (configuration->cell_identity >> 12) & 0xff; + (*sib1_MBMS)->cellAccessRelatedInfo_r14.cellIdentity_r14.buf[2] = (configuration->cell_identity >> 4) & 0xff; + (*sib1_MBMS)->cellAccessRelatedInfo_r14.cellIdentity_r14.buf[3] = (configuration->cell_identity << 4) & 0xf0; +#else + (*sib1_MBMS)->cellAccessRelatedInfo_r14.cellIdentity_r14.buf[0] = 0x00; + (*sib1_MBMS)->cellAccessRelatedInfo_r14.cellIdentity_r14.buf[1] = 0x00; + (*sib1_MBMS)->cellAccessRelatedInfo_r14.cellIdentity_r14.buf[2] = 0x00; + (*sib1_MBMS)->cellAccessRelatedInfo_r14.cellIdentity_r14.buf[3] = 0x10; +#endif + (*sib1_MBMS)->cellAccessRelatedInfo_r14.cellIdentity_r14.size=4; + (*sib1_MBMS)->cellAccessRelatedInfo_r14.cellIdentity_r14.bits_unused=4; + (*sib1_MBMS)->freqBandIndicator_r14 = +#if defined(ENABLE_ITTI) + configuration->eutra_band[CC_id]; +#else + 7; +#endif + schedulingInfo.si_Periodicity_r14=LTE_SchedulingInfo__si_Periodicity_rf16; + sib_type=LTE_SIB_Type_MBMS_r14_sibType13_v920; + ASN_SEQUENCE_ADD(&schedulingInfo.sib_MappingInfo_r14.list,&sib_type); + ASN_SEQUENCE_ADD(&(*sib1_MBMS)->schedulingInfoList_MBMS_r14.list,&schedulingInfo); + + (*sib1_MBMS)->si_WindowLength_r14=LTE_SystemInformationBlockType1_MBMS_r14__si_WindowLength_r14_ms20; + (*sib1_MBMS)->systemInfoValueTag_r14=0; + // (*sib1).nonCriticalExtension = calloc(1,sizeof(*(*sib1).nonCriticalExtension)); + + + //sib13 optional + if (1) + { + (*sib1_MBMS)->systemInformationBlockType13_r14 = CALLOC(1,sizeof(struct LTE_SystemInformationBlockType13_r9)); + memset((*sib1_MBMS)->systemInformationBlockType13_r14,0,sizeof(struct LTE_SystemInformationBlockType13_r9)); + + ((*sib1_MBMS)->systemInformationBlockType13_r14)->notificationConfig_r9.notificationRepetitionCoeff_r9= LTE_MBMS_NotificationConfig_r9__notificationRepetitionCoeff_r9_n2; + ((*sib1_MBMS)->systemInformationBlockType13_r14)->notificationConfig_r9.notificationOffset_r9= 0; + ((*sib1_MBMS)->systemInformationBlockType13_r14)->notificationConfig_r9.notificationSF_Index_r9= 1; + + //((*sib1_MBMS)->systemInformationBlockType13_r14)->mbsfn_AreaInfoList_r9= CALLOC(1,sizeof(LTE_MBSFN_AreaInfoList_r9_t)); + //memset(((*sib1_MBMS)->systemInformationBlockType13_r14)->mbsfn_AreaInfoList_r9,0,sizeof(LTE_MBSFN_AreaInfoList_r9_t)); + LTE_MBSFN_AreaInfoList_r9_t * MBSFNArea_list= &((*sib1_MBMS)->systemInformationBlockType13_r14)->mbsfn_AreaInfoList_r9; + // MBSFN-AreaInfoList + memset(MBSFNArea_list,0,sizeof(*MBSFNArea_list)); + // MBSFN Area 1 + MBSFN_Area1= CALLOC(1, sizeof(*MBSFN_Area1)); + MBSFN_Area1->mbsfn_AreaId_r9= 1; + MBSFN_Area1->non_MBSFNregionLength= LTE_MBSFN_AreaInfo_r9__non_MBSFNregionLength_s2; + MBSFN_Area1->notificationIndicator_r9= 0; + MBSFN_Area1->mcch_Config_r9.mcch_RepetitionPeriod_r9= LTE_MBSFN_AreaInfo_r9__mcch_Config_r9__mcch_RepetitionPeriod_r9_rf32; + MBSFN_Area1->mcch_Config_r9.mcch_Offset_r9= 1; // in accordance with mbsfn subframe configuration in sib2 + MBSFN_Area1->mcch_Config_r9.mcch_ModificationPeriod_r9= LTE_MBSFN_AreaInfo_r9__mcch_Config_r9__mcch_ModificationPeriod_r9_rf512; + // Subframe Allocation Info + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf= MALLOC(1); + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.size= 1; + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf[0]=0x20<<2; // FDD: SF1 + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.bits_unused= 2; + MBSFN_Area1->mcch_Config_r9.signallingMCS_r9= LTE_MBSFN_AreaInfo_r9__mcch_Config_r9__signallingMCS_r9_n7; + + + (MBSFN_Area1)->ext1 = CALLOC (1, sizeof(*(MBSFN_Area1)->ext1)); + + memset((MBSFN_Area1)->ext1,0,sizeof(*(MBSFN_Area1)->ext1)); + + MBSFN_Area1->ext1->subcarrierSpacingMBMS_r14 = CALLOC(1,sizeof(*( MBSFN_Area1->ext1)->subcarrierSpacingMBMS_r14)); + + memset(MBSFN_Area1->ext1->subcarrierSpacingMBMS_r14,0,sizeof(*((MBSFN_Area1)->ext1)->subcarrierSpacingMBMS_r14)); + + + *(MBSFN_Area1->ext1->subcarrierSpacingMBMS_r14) = LTE_MBSFN_AreaInfo_r9__ext1__subcarrierSpacingMBMS_r14_khz_1dot25; + + ASN_SEQUENCE_ADD(&MBSFNArea_list->list,MBSFN_Area1); + } + + //nonMBSFN_SubframeConfig_r14 optional + if(1){ + (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14 = CALLOC(1,sizeof(struct LTE_NonMBSFN_SubframeConfig_r14)); + memset((*sib1_MBMS)->nonMBSFN_SubframeConfig_r14,0,sizeof(struct LTE_NonMBSFN_SubframeConfig_r14)); + (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->radioFrameAllocationPeriod_r14 = LTE_NonMBSFN_SubframeConfig_r14__radioFrameAllocationPeriod_r14_rf8; + (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->radioFrameAllocationOffset_r14 = LTE_NonMBSFN_SubframeConfig_r14__radioFrameAllocationPeriod_r14_rf64; + (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.buf = MALLOC(2); + (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.buf[0] = 0x20<<0; + (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.buf[1] = 0x20<<7; + (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.size = 2; + (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.bits_unused = 7; + } + + + + //if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + //xer_fprint(stdout, &asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS, (void *)bcch_message); + //} + + enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS, + NULL, + (void *)bcch_message, + buffer, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + LOG_D(RRC,"[eNB] SystemInformationBlockType1_MBMS Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); + + if (enc_rval.encoded==-1) { + return(-1); + } + + return((enc_rval.encoded+7)/8); +} +#endif uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier, int Mod_id,int CC_id diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.h b/openair2/RRC/LTE/MESSAGES/asn1_msg.h index 819f90c336..338f868c57 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.h +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.h @@ -70,6 +70,15 @@ uint8_t do_MIB(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_t phich #endif ); +/** +\brief Generate configuration for MIB (eNB). +@param carrier pointer to Carrier information +@param N_RB_DL Number of downlink PRBs +@param additional Non MBSFN Subframes parameter +@param frame radio frame number +@return size of encoded bit stream in bytes*/ +uint8_t do_MIB_MBMS(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_t additionalNonMBSFNSubframes, uint32_t frame); + /** \brief Generate configuration for SIB1 (eNB). @param carrier pointer to Carrier information @@ -88,6 +97,17 @@ uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,int Mod_id,int CC_id #endif ); +/** +\brief Generate configuration for SIB1 MBMS (eNB). +@param carrier pointer to Carrier information +@param Mod_id Instance of eNB +@param Component carrier Component carrier to configure +@param configuration Pointer Configuration Request structure +@return size of encoded bit stream in bytes*/ +uint8_t do_SIB1_MBMS(rrc_eNB_carrier_data_t *carrier,int Mod_id,int CC_id, RrcConfigurationReq *configuration + ); + + /** \brief Generate a default configuration for SIB2/SIB3 in one System Information PDU (eNB). diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 49f9e16740..d648368b42 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -85,6 +85,13 @@ #include "openair2/LAYER2/MAC/mac_extern.h" +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + #include "LTE_BCCH-BCH-Message-MBMS.h" + #include "LTE_BCCH-DL-SCH-Message-MBMS.h" + #include "LTE_SystemInformationBlockType1-MBMS-r14.h" + #include "LTE_NonMBSFN-SubframeConfig-r14.h" +#endif + #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) #include "LTE_SL-Preconfiguration-r12.h" @@ -2597,6 +2604,109 @@ const char *SIB2nB( long value ) { } +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) +int decode_BCCH_MBMS_DLSCH_Message( + const protocol_ctxt_t *const ctxt_pP, + const uint8_t eNB_index, + uint8_t *const Sdu, + const uint8_t Sdu_len, + const uint8_t rsrq, + const uint8_t rsrp ) { + LTE_BCCH_DL_SCH_Message_MBMS_t *bcch_message = NULL; + LTE_SystemInformationBlockType1_MBMS_r14_t *sib1_mbms = UE_rrc_inst[ctxt_pP->module_id].sib1_MBMS[eNB_index]; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN ); + + /*if (((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&1) == 1) && // SIB1 received + (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt == sib1->schedulingInfoList.list.count)) { + // Avoid decoding SystemInformationBlockType1_t* sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]; + // to prevent memory bloating + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); + return 0; + }*/ + + LOG_W(PHY,"llega\n"); + rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_RECEIVING_SIB ); + + //if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + //xer_fprint(stdout, &asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS,(void *)bcch_message ); + //} + + asn_dec_rval_t dec_rval = uper_decode_complete( NULL, + &asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS, + (void **)&bcch_message, + (const void *)Sdu, + Sdu_len ); + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E( RRC, "[UE %"PRIu8"] Failed to decode BCCH_DLSCH_MBMS_MESSAGE (%zu bits)\n", + ctxt_pP->module_id, + dec_rval.consumed ); + log_dump(RRC, Sdu, Sdu_len, LOG_DUMP_CHAR," Received bytes:\n" ); + // free the memory + SEQUENCE_free( &asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS, (void *)bcch_message, 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); + return -1; + } + + //if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + // xer_fprint(stdout, &asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS,(void *)bcch_message ); + //} + + /*if (bcch_message->message.present == LTE_BCCH_DL_SCH_MessageType_PR_c1) { + switch (bcch_message->message.choice.c1.present) { + case LTE_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1: + if ((ctxt_pP->frame % 2) == 0) { + // even frame + if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&1) == 0) { + LTE_SystemInformationBlockType1_t *sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]; + memcpy( (void *)sib1, + (void *)&bcch_message->message.choice.c1.choice.systemInformationBlockType1, + sizeof(LTE_SystemInformationBlockType1_t) ); + LOG_D( RRC, "[UE %"PRIu8"] Decoding First SIB1\n", ctxt_pP->module_id ); + decode_SIB1( ctxt_pP, eNB_index, rsrq, rsrp ); + } + } + + break; + + case LTE_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: + if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&1) == 1) { + // SIB1 with schedulingInfoList is available + LTE_SystemInformation_t *si = UE_rrc_inst[ctxt_pP->module_id].si[eNB_index]; + memcpy( si, + &bcch_message->message.choice.c1.choice.systemInformation, + sizeof(LTE_SystemInformation_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Decoding SI for frameP %"PRIu32"\n", + ctxt_pP->module_id, + ctxt_pP->frame ); + decode_SI( ctxt_pP, eNB_index ); + //if (nfapi_mode == 3) + UE_mac_inst[ctxt_pP->module_id].SI_Decoded = 1; + } + + break; + + case LTE_BCCH_DL_SCH_MessageType__c1_PR_NOTHING: + default: + break; + } + }*/ + + /*if ((rrc_get_sub_state(ctxt_pP->module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE) +#if defined(ENABLE_USE_MME) + && (UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data != NULL) +#endif + ) { + rrc_ue_generate_RRCConnectionRequest(ctxt_pP, 0); + rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_CONNECTING ); + }*/ + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); + return 0; +} + +#endif + //----------------------------------------------------------------------------- @@ -4348,6 +4458,22 @@ void *rrc_ue_task( void *args_p ) { RRC_MAC_BCCH_DATA_IND (msg_p).rsrp); break; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + case RRC_MAC_BCCH_MBMS_DATA_IND: + LOG_D(RRC, "[UE %d] Received %s: frameP %d, eNB %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), + RRC_MAC_BCCH_MBMS_DATA_IND (msg_p).frame, RRC_MAC_BCCH_MBMS_DATA_IND (msg_p).enb_index); + // PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_NO, NOT_A_RNTI, RRC_MAC_BCCH_DATA_IND (msg_p).frame, 0); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, NOT_A_RNTI, RRC_MAC_BCCH_MBMS_DATA_IND (msg_p).frame, 0,RRC_MAC_BCCH_MBMS_DATA_IND (msg_p).enb_index); + decode_BCCH_MBMS_DLSCH_Message (&ctxt, + RRC_MAC_BCCH_MBMS_DATA_IND (msg_p).enb_index, + RRC_MAC_BCCH_MBMS_DATA_IND (msg_p).sdu, + RRC_MAC_BCCH_MBMS_DATA_IND (msg_p).sdu_size, + RRC_MAC_BCCH_MBMS_DATA_IND (msg_p).rsrq, + RRC_MAC_BCCH_MBMS_DATA_IND (msg_p).rsrp); + break; +#endif + + case RRC_MAC_CCCH_DATA_CNF: LOG_D(RRC, "[UE %d] Received %s: eNB %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), RRC_MAC_CCCH_DATA_CNF (msg_p).enb_index); diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index f28b34982b..4c790f2d43 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -635,6 +635,10 @@ typedef struct { uint8_t sizeof_SIB1_BR; uint8_t *SIB23_BR; uint8_t sizeof_SIB23_BR; + uint8_t *MIB_FeMBMS; + uint8_t sizeof_MIB_FeMBMS; + uint8_t *SIB1_MBMS; + uint8_t sizeof_SIB1_MBMS; #endif int physCellId; int Ncp; @@ -648,12 +652,19 @@ typedef struct { LTE_BCCH_DL_SCH_Message_t systemInformation; LTE_BCCH_DL_SCH_Message_t systemInformation_BR; // SystemInformation_t systemInformation; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + LTE_BCCH_BCH_Message_MBMS_t mib_fembms; + LTE_BCCH_DL_SCH_Message_MBMS_t siblock1_MBMS; + LTE_BCCH_DL_SCH_Message_MBMS_t systemInformation_MBMS; +#endif LTE_SystemInformationBlockType1_t *sib1; LTE_SystemInformationBlockType2_t *sib2; LTE_SystemInformationBlockType3_t *sib3; #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) LTE_SystemInformationBlockType1_t *sib1_BR; LTE_SystemInformationBlockType2_t *sib2_BR; + LTE_SystemInformationBlockType1_MBMS_r14_t *sib1_MBMS; + LTE_SystemInformationBlockType13_r9_t *sib13_MBMS; #endif #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) LTE_SystemInformationBlockType13_r9_t *sib13; @@ -743,6 +754,9 @@ typedef struct UE_RRC_INST_s { uint8_t SIB1Status[NB_CNX_UE]; uint8_t SIStatus[NB_CNX_UE]; LTE_SystemInformationBlockType1_t *sib1[NB_CNX_UE]; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + LTE_SystemInformationBlockType1_MBMS_r14_t *sib1_MBMS[NB_CNX_UE]; +#endif LTE_SystemInformation_t *si[NB_CNX_UE]; //!< Temporary storage for an SI message. Decoding happens in decode_SI(). LTE_SystemInformationBlockType2_t *sib2[NB_CNX_UE]; LTE_SystemInformationBlockType3_t *sib3[NB_CNX_UE]; @@ -785,6 +799,9 @@ typedef struct UE_RRC_INST_s { LTE_SystemInformationBlockType12_r9_t *sib12[NB_CNX_UE]; LTE_SystemInformationBlockType13_r9_t *sib13[NB_CNX_UE]; #endif +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + LTE_SystemInformationBlockType13_r9_t *sib13_MBMS[NB_CNX_UE]; +#endif #ifdef CBA uint8_t num_active_cba_groups; uint16_t cba_rnti[NUM_MAX_CBA_GROUP]; diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h index 3777f3ea26..22a583c25c 100644 --- a/openair2/RRC/LTE/rrc_proto.h +++ b/openair2/RRC/LTE/rrc_proto.h @@ -529,6 +529,16 @@ int decode_BCCH_DLSCH_Message( const uint8_t rsrq, const uint8_t rsrp ); +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) +int decode_BCCH_MBMS_DLSCH_Message( + const protocol_ctxt_t* const ctxt_pP, + const uint8_t eNB_index, + uint8_t* const Sdu, + const uint8_t Sdu_len, + const uint8_t rsrq, + const uint8_t rsrp ); +#endif + int decode_PCCH_DLSCH_Message( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index,