/* * 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 eNB_scheduler_RA.c * \brief primitives used for random access * \author Navid Nikaein and Raymond Knopp * \date 2010 - 2014 * \email: navid.nikaein@eurecom.fr * \version 1.0 * @ingroup _mac */ #include "assertions.h" #include "platform_types.h" //#include "PHY/defs.h" //#include "PHY/extern.h" #include "msc.h" //#include "SCHED/defs.h" #include "SCHED/extern.h" //#include "LAYER2/MAC/defs.h" #include "LAYER2/MAC/extern.h" #include "LAYER2/MAC/proto.h" #include "UTIL/LOG/log.h" #include "UTIL/LOG/vcd_signal_dumper.h" //#include "UTIL/OPT/opt.h" //#include "OCG.h" //#include "OCG_extern.h" //#include "RRC/LITE/extern.h" //#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" //NB-IoT #include "PHY/defs_NB_IoT.h" #include "proto_NB_IoT.h" #include "defs_NB_IoT.h" #include "math.h" //#include "openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.h" //#include "LAYER2/MAC/pre_processor.c" //#include "pdcp.h" #if defined(ENABLE_ITTI) # include "intertask_interface.h" #endif #include "SIMULATION/TOOLS/defs.h" // for taus #include "T.h" void schedule_RA_NB_IoT(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP) { int CC_id; eNB_MAC_INST_NB_IoT *eNB = &eNB_mac_inst_NB_IoT[module_idP]; RA_TEMPLATE_NB_IoT *RA_template; unsigned char i,harq_pid,round; int16_t rrc_sdu_length; int UE_id = -1; unsigned short TBsize = -1; unsigned short msg4_header; // start_meas(&eNB->schedule_ra); for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { for (i=0; i<NB_RA_PROC_MAX; i++) { RA_template = (RA_TEMPLATE_NB_IoT *)&eNB->common_channels[CC_id].RA_template[i]; if (RA_template->RA_active == TRUE) { LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d RA %d is active (generate RAR %d, generate_Msg4 %d, wait_ack_Msg4 %d, rnti %x)\n", module_idP,CC_id,i,RA_template->generate_rar,RA_template->generate_Msg4,RA_template->wait_ack_Msg4, RA_template->rnti); if (RA_template->generate_rar == 1) { LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI (proc %d), RA_active %d format 1A (%d,%d))\n", module_idP, CC_id, frameP, subframeP,i, RA_template->RA_active, RA_template->RA_dci_fmt1, RA_template->RA_dci_size_bits1); //directly fill DCI Filed base on DCI Nq for RAR ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->type=1; ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->orderIndicator=0; ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->Scheddly=1;//fixed delay approach? ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->ResAssign=0; ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0;//fixes?//fixes? base on CE levels? ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->RepNum=0;//fixes? base on CE levels? // ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->Reserved=0; ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->DCIRep=0;//fixes? } //New appoach for CCE allocaton, delete !CCE_allocation_infeasible.. else if (RA_template->generate_Msg4 == 1) { // check for Msg4 Message UE_id = find_UE_id(module_idP,RA_template->rnti); if (UE_id == -1) { printf("%s:%d:%s: FATAL ERROR\n", __FILE__, __LINE__, __FUNCTION__); abort(); } if (Is_rrc_registered == 1) {//Fixed mac_rrc_data_req // Get RRCConnectionSetup for Piggyback rrc_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, CCCH, 1, // 1 transport block &eNB->common_channels[CC_id].CCCH_pdu.payload[0], ENB_FLAG_YES, module_idP, 0); // not used in this case if (rrc_sdu_length == -1) { mac_xface->macphy_exit("[MAC][eNB Scheduler] CCCH not allocated\n"); return; // not reached } else { //msg("[MAC][eNB %d] Frame %d, subframeP %d: got %d bytes from RRC\n",module_idP,frameP, subframeP,rrc_sdu_length); } } LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: UE_id %d, Is_rrc_registered %d, rrc_sdu_length %d\n", module_idP, CC_id, frameP, subframeP,UE_id, Is_rrc_registered,rrc_sdu_length); if (rrc_sdu_length>0) { LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RA proc %d, RNTI %x)\n", module_idP, CC_id, frameP, subframeP,i,RA_template->rnti); // Compute MCS for 3 PRB msg4_header = 1+6+1; // CR header, CR CE, SDU header //need to fixed ndi & msc base on NB-IoT DCI for Msg4 ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->type=1; ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->orderIndicator=0; ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->Scheddly=1;//fixed delay approach? ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->ResAssign=5;//fixed depend on mcs/tbs to Nsf ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->RepNum=1;//fixed base on CE levels ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->HARQackRes=0;//Avoid confict multiple Msg ACk ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->DCIRep=0;//fixed base on CE levels } }else if (RA_template->wait_ack_Msg4==1) { // check HARQ status and retransmit if necessary LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \n", module_idP,CC_id,frameP,subframeP); // Get candidate harq_pid from PHY mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,openair_harq_RA); if (round>0) { //RA_template->wait_ack_Msg4++; // we have to schedule a retransmission ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; // if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,2,RA_template->rnti)) { // add_ue_spec_dci(DCI_pdu, // (void*)&RA_template->RA_alloc_pdu2[0], // RA_template->rnti, // RA_template->RA_dci_size_bytes2, // 2, // RA_template->RA_dci_size_bits2, // RA_template->RA_dci_fmt2, // 0); // printf("MAC: msg4 retransmission for rnti %x (round %d) fsf %d/%d\n", RA_template->rnti, round, frameP, subframeP); // } }else printf("MAC: msg4 retransmission for rnti %x (round %d) fsf %d/%d CCE allocation failed!\n", RA_template->rnti, round, frameP, subframeP); LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n", module_idP,CC_id,frameP,subframeP,RA_template->rnti); } else { /* msg4 not received if ((round == 0) && (RA_template->wait_ack_Msg4>1){ remove UE instance across all the layers: mac_xface->cancel_RA(); } */ printf("MAC: msg4 acknowledged for rnti %x fsf %d/%d, let's configure it\n", RA_template->rnti, frameP, subframeP); LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_id,frameP,subframeP); RA_template->wait_ack_Msg4=0; RA_template->RA_active=FALSE; UE_id = find_UE_id(module_idP,RA_template->rnti); DevAssert( UE_id != -1 ); eNB_mac_inst_NB_IoT[module_idP].UE_list.UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured=TRUE; } }// RA_active } // for i=0 .. N_RA_PROC-1 } // CC_id // stop_meas(&eNB->schedule_ra); } /*This function should loop all over the preamble index*/ void initiate_ra_proc_NB_IoT(module_id_t module_idP, int CC_id,frame_t frameP, uint16_t preamble_index,int16_t timing_offset,sub_frame_t subframeP) { uint8_t i; uint8_t carrier_id = 0;/*The index of the UL carrier associated with the NPRACH, the carrier_id of the anchor carrier is 0*/ RA_TEMPLATE_NB_IoT *RA_template = (RA_TEMPLATE_NB_IoT *)&eNB_mac_inst_NB_IoT[module_idP].common_channels[CC_id].RA_template[0]; /*preamble index will be a subcarrier index (0-47)*/ LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,0); /*May up to 48 RA Procdeure MAX at the moment*/ for (i=0; i<NB_RA_PROC_MAX; i++) { if (RA_template[i].RA_active==FALSE && RA_template[i].wait_ack_Msg4 == 0) { int loop = 0; RA_template[i].RA_active=TRUE; RA_template[i].generate_rar=1; RA_template[i].generate_Msg4=0; RA_template[i].wait_ack_Msg4=0; RA_template[i].timing_offset=timing_offset; /* TODO: find better procedure to allocate RNTI */ do { RA_template[i].rnti = taus(); loop++; } while (loop != 100 && /* TODO: this is not correct, the rnti may be in use without * being in the MAC yet. To be refined. */ !(find_UE_id(module_idP, RA_template[i].rnti) == -1 && /* 1024 and 60000 arbirarily chosen, not coming from standard */ RA_template[i].rnti >= 1024 && RA_template[i].rnti < 60000)); if (loop == 100) { printf("%s:%d:%s: FATAL ERROR! contact the authors\n", __FILE__, __LINE__, __FUNCTION__); abort(); } //RA_template[i].RA_rnti = 1+subframeP+(10*f_id); /*for NB-IoT, RA_rnti is counted in 36.321 5.1.4*/ RA_template[i].preamble_index = preamble_index; RA_template[i].RA_rnti = 1+floor(frameP/4)+256*carrier_id; LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Activating RAR generation for process %d, rnti %x, RA_active %d\n", module_idP,CC_id,frameP,i,RA_template[i].rnti, RA_template[i].RA_active); return; } } LOG_E(MAC,"[eNB %d][RAPROC] FAILURE: CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index); }