/******************************************************************************* Eurecom OpenAirInterface Copyright(c) 1999 - 2010 Eurecom This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information Openair Admin: openair_admin@eurecom.fr Openair Tech : openair_tech@eurecom.fr Forums : http://forums.eurecom.fsr/openairinterface Address : Eurecom, 2229, route des crĂȘtes, 06560 Valbonne Sophia Antipolis, France *******************************************************************************/ /*! \file eNB_scheduler.c * \brief procedures related to UE * \author Raymond Knopp, Navid Nikaein * \date 2011 * \email: navid.nikaein@eurecom.fr * \version 0.5 * @ingroup _mac */ #include "PHY/defs.h" #include "PHY/extern.h" #include "SCHED/defs.h" #include "SCHED/extern.h" #include "LAYER2/MAC/defs.h" #include "LAYER2/MAC/extern.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 "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h" #include "ARCH/CBMIMO1/DEVICE_DRIVER/defs.h" #include "ARCH/CBMIMO1/DEVICE_DRIVER/from_grlib_softregs.h" #include "RRC/LITE/extern.h" #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" //#include "LAYER2/MAC/pre_processor.c" #include "pdcp.h" #if defined(ENABLE_ITTI) # include "intertask_interface.h" #endif #define ENABLE_MAC_PAYLOAD_DEBUG #define DEBUG_eNB_SCHEDULER 1 //#define DEBUG_HEADER_PARSING 1 //#define DEBUG_PACKET_TRACE 1 /* #ifndef USER_MODE #define msg debug_msg #endif */ extern inline unsigned int taus(void); void init_ue_sched_info(void){ int i,j; for (i=0;imacphy_exit("[MAC][eNB] Max user count reached\n"); } else { LOG_I(MAC,"[eNB %d][RAPROC] Frame %d Added user with rnti %x => UE %d\n", Mod_id,frame,eNB_mac_inst[Mod_id].RA_template[i].rnti,UE_id); } if (Is_rrc_registered == 1) mac_rrc_data_ind(Mod_id,frame,CCCH,(u8 *)payload_ptr,rx_lengths[0],1,Mod_id,0); // add_user. This is needed to have the rnti for configuring UE (PHY). The UE is removed if RRC // doesn't provide a CCCH SDU } else if (num_ce >0) { // handle msg3 which is not RRCConnectionRequest // process_ra_message(msg3,num_ce,rx_lcids,rx_ces); } eNB_mac_inst[Mod_id].RA_template[i].generate_Msg4 = 1; eNB_mac_inst[Mod_id].RA_template[i].wait_ack_Msg4 = 0; return; } // if process is active } // loop on RA processes } DCI_PDU *get_dci_sdu(u8 Mod_id, u32 frame, u8 subframe) { return(&eNB_mac_inst[Mod_id].DCI_pdu); } s8 find_UE_id(unsigned char Mod_id,u16 rnti) { unsigned char i; for (i=0;iget_eNB_UE_stats(Mod_id,rnti) != NULL){ // check at the phy enb_ue state for this rnti nb_active_ue++; } else { // this ue is removed at the phy => remove it at the mac as well mac_remove_ue(Mod_id, UE_id); } } } return(nb_active_ue); } // function for determining which active ue should be granted resources in uplink based on BSR+QoS u16 find_ulgranted_UEs(unsigned char Mod_id){ // all active users should be granted return(find_active_UEs(Mod_id)); } // function for determining which active ue should be granted resources in downlink based on CQI, SI, and BSR u16 find_dlgranted_UEs(unsigned char Mod_id){ // all active users should be granted return(find_active_UEs(Mod_id)); } // get aggregatiob form phy for a give UE unsigned char process_ue_cqi (unsigned char Mod_id, unsigned char UE_id) { unsigned char aggregation=2; // check the MCS and SNR and set the aggregation accordingly return aggregation; } #ifdef CBA u8 find_num_active_UEs_in_cbagroup(unsigned char Mod_id, unsigned char group_id){ u8 UE_id; u16 rnti; unsigned char nb_ue_in_pusch=0; LTE_eNB_UE_stats* eNB_UE_stats; for (UE_id=group_id;UE_id RRC_CONNECTED)){ // && (UE_is_to_be_scheduled(Mod_id,UE_id))) // check at the phy enb_ue state for this rnti if ((eNB_UE_stats= mac_xface->get_eNB_UE_stats(Mod_id,rnti)) != NULL){ if ((eNB_UE_stats->mode == PUSCH) && (UE_is_to_be_scheduled(Mod_id,UE_id) == 0)){ nb_ue_in_pusch++; } } } } return(nb_ue_in_pusch); } #endif s8 add_new_ue(unsigned char Mod_id, u16 rnti) { unsigned char i; for (i=0;i UE_id %d\n",Mod_id,frame,rnti,UE_id); return((unsigned char *)&eNB_mac_inst[Mod_id].DLSCH_pdu[UE_id][TBindex].payload[0]); } } unsigned char *parse_ulsch_header(unsigned char *mac_header, unsigned char *num_ce, unsigned char *num_sdu, unsigned char *rx_ces, unsigned char *rx_lcids, unsigned short *rx_lengths, unsigned short tb_length) { unsigned char not_done=1,num_ces=0,num_sdus=0,lcid,num_sdu_cnt; unsigned char *mac_header_ptr = mac_header; unsigned short length, ce_len=0; while (not_done==1) { if (((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E == 0) not_done = 0; lcid = ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID; if (lcid < EXTENDED_POWER_HEADROOM) { if (not_done==0) { // last MAC SDU, length is implicit mac_header_ptr++; length = tb_length-(mac_header_ptr-mac_header)-ce_len; for (num_sdu_cnt=0; num_sdu_cnt < num_sdus ; num_sdu_cnt++) length -= rx_lengths[num_sdu_cnt]; } else { if (((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F == 0) { length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L; mac_header_ptr += 2;//sizeof(SCH_SUBHEADER_SHORT); } else { // F = 1 length = ((((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB & 0x7f ) << 8 ) | (((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB & 0xff); mac_header_ptr += 3;//sizeof(SCH_SUBHEADER_LONG); } } LOG_D(MAC,"[eNB] sdu %d lcid %d tb_length %d length %d (offset now %d)\n", num_sdus,lcid,tb_length, length,mac_header_ptr-mac_header); rx_lcids[num_sdus] = lcid; rx_lengths[num_sdus] = length; num_sdus++; } else { // This is a control element subheader POWER_HEADROOM, BSR and CRNTI if (lcid == SHORT_PADDING) { mac_header_ptr++; } else { rx_ces[num_ces] = lcid; num_ces++; mac_header_ptr++; if (lcid==LONG_BSR) ce_len+=4; else if (lcid==CRNTI) ce_len+=2; else if ((lcid==POWER_HEADROOM) || (lcid==TRUNCATED_BSR)|| (lcid== SHORT_BSR)) ce_len++; } } } *num_ce = num_ces; *num_sdu = num_sdus; return(mac_header_ptr); } void SR_indication(u8 Mod_id,u32 frame, u16 rnti, u8 subframe) { u8 UE_id = find_UE_id(Mod_id,rnti); LOG_D(MAC,"[eNB %d][SR %x] Frame %d subframe %d Signaling SR for UE %d \n",Mod_id,rnti,frame,subframe, UE_id); eNB_mac_inst[Mod_id].UE_template[UE_id].ul_SR = 1; eNB_mac_inst[Mod_id].UE_template[UE_id].ul_active = 1; } void rx_sdu(u8 Mod_id,u32 frame,u16 rnti,u8 *sdu, u16 sdu_len) { unsigned char rx_ces[MAX_NUM_CE],num_ce,num_sdu,i,*payload_ptr; unsigned char rx_lcids[NB_RB_MAX]; unsigned short rx_lengths[NB_RB_MAX]; unsigned char UE_id = find_UE_id(Mod_id,rnti); int ii,j; for(ii=0; ii> 6); LOG_D(MAC, "[eNB] MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n", rx_ces[i], lcgid, payload_ptr[0] & 0x3f); eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[lcgid] = (payload_ptr[0] & 0x3f); payload_ptr += 1;//sizeof(SHORT_BSR); // fixme } break; case LONG_BSR: eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0] = ((payload_ptr[0] & 0xFC) >> 2); eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1] = ((payload_ptr[0] & 0x03) << 4) | ((payload_ptr[1] & 0xF0) >> 4); eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2] = ((payload_ptr[1] & 0x0F) << 2) | ((payload_ptr[2] & 0xC0) >> 6); eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3] = (payload_ptr[2] & 0x3F); LOG_D(MAC, "[eNB] MAC CE_LCID %d: Received long BSR LCGID0 = %u LCGID1 = " "%u LCGID2 = %u LCGID3 = %u\n", rx_ces[i], eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0], eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1], eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2], eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3]); break; default: LOG_E(MAC, "[eNB] Received unknown MAC header (0x%02x)\n", rx_ces[i]); break; } } for (i=0;i UL-DCCH, received %d bytes form UE %d on LCID %d(%d) \n", Mod_id,frame, rx_lengths[i], UE_id, rx_lcids[i], rx_lcids[i]+(UE_id*NB_RB_MAX)); mac_rlc_data_ind(Mod_id,frame,1,RLC_MBMS_NO, rx_lcids[i]+(UE_id*NB_RB_MAX), (char *)payload_ptr, rx_lengths[i], 1, NULL);//(unsigned int*)crc_status); eNB_mac_inst[Mod_id].eNB_UE_stats[UE_id].num_pdu_rx[rx_lcids[i]]+=1; eNB_mac_inst[Mod_id].eNB_UE_stats[UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i]; } // } } else if (rx_lcids[i] >= DTCH) { // if(eNB_mac_inst[Mod_id].Dcch_lchan[UE_id].Active==1){ #if defined(ENABLE_MAC_PAYLOAD_DEBUG) LOG_T(MAC,"offset: %d\n",(unsigned char)((unsigned char*)payload_ptr-sdu)); for (j=0;j<32;j++) LOG_T(MAC,"%x ",payload_ptr[j]); LOG_T(MAC,"\n"); #endif LOG_D(MAC,"[eNB %d] Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d (%d)\n", Mod_id,frame, rx_lengths[i], UE_id,rx_lcids[i],rx_lcids[i]+(UE_id*NB_RB_MAX)); if ((rx_lengths[i] 0) ) { // MAX SIZE OF transport block mac_rlc_data_ind(Mod_id,frame,1,RLC_MBMS_NO, DTCH+(UE_id*NB_RB_MAX), (char *)payload_ptr, rx_lengths[i], 1, NULL);//(unsigned int*)crc_status); eNB_mac_inst[Mod_id].eNB_UE_stats[UE_id].num_pdu_rx[rx_lcids[i]]+=1; eNB_mac_inst[Mod_id].eNB_UE_stats[UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i]; } // } } else { eNB_mac_inst[Mod_id].eNB_UE_stats[UE_id].num_errors_rx+=1; LOG_E(MAC,"[eNB %d] received unknown LCID %d from UE %d ", rx_lcids[i], UE_id); } payload_ptr+=rx_lengths[i]; } vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU,0); } unsigned char generate_dlsch_header(unsigned char *mac_header, unsigned char num_sdus, unsigned short *sdu_lengths, unsigned char *sdu_lcids, unsigned char drx_cmd, short timing_advance_cmd, unsigned char *ue_cont_res_id, unsigned char short_padding, unsigned short post_padding) { SCH_SUBHEADER_FIXED *mac_header_ptr = (SCH_SUBHEADER_FIXED *)mac_header; u8 first_element=0,last_size=0,i; u8 mac_header_control_elements[16],*ce_ptr; ce_ptr = &mac_header_control_elements[0]; // compute header components if ((short_padding == 1) || (short_padding == 2)) { mac_header_ptr->R = 0; mac_header_ptr->E = 0; mac_header_ptr->LCID = SHORT_PADDING; first_element=1; last_size=1; } if (short_padding == 2) { mac_header_ptr->E = 1; mac_header_ptr++; mac_header_ptr->R = 0; mac_header_ptr->E = 0; mac_header_ptr->LCID = SHORT_PADDING; last_size=1; } if (drx_cmd != 255) { if (first_element>0) { mac_header_ptr->E = 1; mac_header_ptr++; } else { first_element=1; } mac_header_ptr->R = 0; mac_header_ptr->E = 0; mac_header_ptr->LCID = DRX_CMD; last_size=1; } if (timing_advance_cmd != 0) { if (first_element>0) { mac_header_ptr->E = 1; mac_header_ptr++; } else { first_element=1; } mac_header_ptr->R = 0; mac_header_ptr->E = 0; mac_header_ptr->LCID = TIMING_ADV_CMD; last_size=1; // msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr); ((TIMING_ADVANCE_CMD *)ce_ptr)->R=0; ((TIMING_ADVANCE_CMD *)ce_ptr)->TA=timing_advance_cmd&0x3f; LOG_I(MAC,"timing advance =%d (%d)\n",timing_advance_cmd,((TIMING_ADVANCE_CMD *)ce_ptr)->TA); ce_ptr+=sizeof(TIMING_ADVANCE_CMD); //msg("offset %d\n",ce_ptr-mac_header_control_elements); } if (ue_cont_res_id) { if (first_element>0) { mac_header_ptr->E = 1; /* printf("[eNB][MAC] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr, ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R, ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E, ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID); */ mac_header_ptr++; } else { first_element=1; } mac_header_ptr->R = 0; mac_header_ptr->E = 0; mac_header_ptr->LCID = UE_CONT_RES; last_size=1; LOG_T(MAC,"[eNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n", ue_cont_res_id[0], ue_cont_res_id[1], ue_cont_res_id[2], ue_cont_res_id[3], ue_cont_res_id[4], ue_cont_res_id[5]); memcpy(ce_ptr,ue_cont_res_id,6); ce_ptr+=6; // msg("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements); } //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr); for (i=0;i0) { mac_header_ptr->E = 1; /*msg("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr, ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R, ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E, ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID); */ mac_header_ptr+=last_size; //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr); } else { first_element=1; } if (sdu_lengths[i] < 128) { ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R = 0; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E = 0; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F = 0; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID = sdu_lcids[i]; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L = (unsigned char)sdu_lengths[i]; last_size=2; } else { ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R = 0; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E = 0; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F = 1; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = sdu_lcids[i]; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB = ((unsigned short) sdu_lengths[i]>>8)&0x7f; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB = (unsigned short) sdu_lengths[i]&0xff; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->padding = 0x00; last_size=3; #ifdef DEBUG_HEADER_PARSING LOG_D(MAC,"[eNB] generate long sdu, size %x (MSB %x, LSB %x)\n", sdu_lengths[i], ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB, ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB); #endif } } /* printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr); printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr, ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R, ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E, ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID); if (((SCH_SUBHEADER_FIXED*)mac_header_ptr)->LCID < UE_CONT_RES) { if (((SCH_SUBHEADER_SHORT*)mac_header_ptr)->F == 0) printf("F = 0, sdu len (L field) %d\n",(((SCH_SUBHEADER_SHORT*)mac_header_ptr)->L)); else printf("F = 1, sdu len (L field) %d\n",(((SCH_SUBHEADER_LONG*)mac_header_ptr)->L)); } */ if (post_padding>0) {// we have lots of padding at the end of the packet mac_header_ptr->E = 1; mac_header_ptr+=last_size; // add a padding element mac_header_ptr->R = 0; mac_header_ptr->E = 0; mac_header_ptr->LCID = SHORT_PADDING; mac_header_ptr++; } else { // no end of packet padding // last SDU subhead is of fixed type (sdu length implicitly to be computed at UE) mac_header_ptr++; } //msg("After subheaders %d\n",(u8*)mac_header_ptr - mac_header); if ((ce_ptr-mac_header_control_elements) > 0) { // printf("Copying %d bytes for control elements\n",ce_ptr-mac_header_control_elements); memcpy((void*)mac_header_ptr,mac_header_control_elements,ce_ptr-mac_header_control_elements); mac_header_ptr+=(unsigned char)(ce_ptr-mac_header_control_elements); } //msg("After CEs %d\n",(u8*)mac_header_ptr - mac_header); return((unsigned char*)mac_header_ptr - mac_header); } /* #ifdef Rel10 unsigned char generate_mch_header( unsigned char *mac_header, unsigned char num_sdus, unsigned short *sdu_lengths, unsigned char *sdu_lcids, unsigned char msi, unsigned char short_padding, unsigned short post_padding) { SCH_SUBHEADER_FIXED *mac_header_ptr = (SCH_SUBHEADER_FIXED *)mac_header; u8 first_element=0,last_size=0,i; u8 mac_header_control_elements[2*num_sdus],*ce_ptr; ce_ptr = &mac_header_control_elements[0]; if ((short_padding == 1) || (short_padding == 2)) { mac_header_ptr->R = 0; mac_header_ptr->E = 0; mac_header_ptr->LCID = SHORT_PADDING; first_element=1; last_size=1; } if (short_padding == 2) { mac_header_ptr->E = 1; mac_header_ptr++; mac_header_ptr->R = 0; mac_header_ptr->E = 0; mac_header_ptr->LCID = SHORT_PADDING; last_size=1; } // SUBHEADER for MSI CE if (msi != 0) {// there is MSI MAC Control Element if (first_element>0) { mac_header_ptr->E = 1; mac_header_ptr+=last_size; } else { first_element = 1; } if (num_sdus*2 < 128) { ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R = 0; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E = 0; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F = 0; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID = MCH_SCHDL_INFO; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L = num_sdus*2; last_size=2; } else { ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R = 0; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E = 0; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F = 1; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = MCH_SCHDL_INFO; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L = (num_sdus*2)&0x7fff; last_size=3; } // Create the MSI MAC Control Element here } // SUBHEADER for MAC SDU (MCCH+MTCHs) for (i=0;i0) { mac_header_ptr->E = 1; mac_header_ptr+=last_size; } else { first_element = 1; } if (sdu_lengths[i] < 128) { ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R = 0; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E = 0; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F = 0; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID = sdu_lcids[i]; ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L = (unsigned char)sdu_lengths[i]; last_size=2; } else { ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R = 0; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E = 0; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F = 1; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = sdu_lcids[i]; ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L = (unsigned short) sdu_lengths[i]&0x7fff; last_size=3; } } if (post_padding>0) {// we have lots of padding at the end of the packet mac_header_ptr->E = 1; mac_header_ptr+=last_size; // add a padding element mac_header_ptr->R = 0; mac_header_ptr->E = 0; mac_header_ptr->LCID = SHORT_PADDING; mac_header_ptr++; } else { // no end of packet padding // last SDU subhead is of fixed type (sdu length implicitly to be computed at UE) mac_header_ptr++; } // Copy MSI Control Element to the end of the MAC Header if it presents if ((ce_ptr-mac_header_control_elements) > 0) { // printf("Copying %d bytes for control elements\n",ce_ptr-mac_header_control_elements); memcpy((void*)mac_header_ptr,mac_header_control_elements,ce_ptr-mac_header_control_elements); mac_header_ptr+=(unsigned char)(ce_ptr-mac_header_control_elements); } return((unsigned char*)mac_header_ptr - mac_header); } #endif */ void add_common_dci(DCI_PDU *DCI_pdu, void *pdu, u16 rnti, unsigned char dci_size_bytes, unsigned char aggregation, unsigned char dci_size_bits, unsigned char dci_fmt, u8 ra_flag) { memcpy(&DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].dci_pdu[0],pdu,dci_size_bytes); DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].dci_length = dci_size_bits; DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].L = aggregation; DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].rnti = rnti; DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].format = dci_fmt; DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].ra_flag = ra_flag; DCI_pdu->Num_common_dci++; } void add_ue_spec_dci(DCI_PDU *DCI_pdu,void *pdu,u16 rnti,unsigned char dci_size_bytes,unsigned char aggregation,unsigned char dci_size_bits,unsigned char dci_fmt,u8 ra_flag) { memcpy(&DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].dci_pdu[0],pdu,dci_size_bytes); DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].dci_length = dci_size_bits; DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].L = aggregation; DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].rnti = rnti; DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].format = dci_fmt; DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].ra_flag = ra_flag; DCI_pdu->Num_ue_spec_dci++; } void schedule_SI(unsigned char Mod_id,u32 frame, unsigned char *nprb,unsigned int *nCCE) { unsigned char bcch_sdu_length; int mcs; void *BCCH_alloc_pdu=(void*)&eNB_mac_inst[Mod_id].BCCH_alloc_pdu; bcch_sdu_length = mac_rrc_data_req(Mod_id, frame, BCCH,1, &eNB_mac_inst[Mod_id].BCCH_pdu.payload[0], 1, Mod_id, 0); // not used in this case if (bcch_sdu_length > 0) { LOG_D(MAC,"[eNB %d] Frame %d : BCCH->DLSCH, Received %d bytes \n",Mod_id,frame,bcch_sdu_length); if (bcch_sdu_length <= (mac_xface->get_TBS_DL(0,3))) mcs=0; else if (bcch_sdu_length <= (mac_xface->get_TBS_DL(1,3))) mcs=1; else if (bcch_sdu_length <= (mac_xface->get_TBS_DL(2,3))) mcs=2; else if (bcch_sdu_length <= (mac_xface->get_TBS_DL(3,3))) mcs=3; else if (bcch_sdu_length <= (mac_xface->get_TBS_DL(4,3))) mcs=4; else if (bcch_sdu_length <= (mac_xface->get_TBS_DL(5,3))) mcs=5; else if (bcch_sdu_length <= (mac_xface->get_TBS_DL(6,3))) mcs=6; else if (bcch_sdu_length <= (mac_xface->get_TBS_DL(7,3))) mcs=7; else if (bcch_sdu_length <= (mac_xface->get_TBS_DL(8,3))) mcs=8; if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; break; case 25: ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; break; case 50: ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; break; case 100: ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; break; } } else { switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; break; case 25: ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; break; case 50: ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; break; case 100: ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; break; } } #if defined(USER_MODE) && defined(OAI_EMU) if (oai_emulation.info.opt_enabled) trace_pdu(1, &eNB_mac_inst[Mod_id].BCCH_pdu.payload[0], bcch_sdu_length, 0xffff, 4, 0xffff, eNB_mac_inst[Mod_id].subframe, 0, 0); LOG_D(OPT,"[eNB %d][BCH] Frame %d trace pdu for rnti %x with size %d\n", Mod_id, frame, 0xffff, bcch_sdu_length); #endif if (mac_xface->lte_frame_parms->frame_type == TDD) { LOG_D(MAC,"[eNB] Frame %d : Scheduling BCCH->DLSCH (TDD) for SI %d bytes (mcs %d, rb 3, TBS %d)\n", frame, bcch_sdu_length, mcs, mac_xface->get_TBS_DL(mcs,3)); } else { LOG_D(MAC,"[eNB] Frame %d : Scheduling BCCH->DLSCH (FDD) for SI %d bytes (mcs %d, rb 3, TBS %d)\n", frame, bcch_sdu_length, mcs, mac_xface->get_TBS_DL(mcs,3)); } eNB_mac_inst[Mod_id].bcch_active=1; *nprb=3; *nCCE=4; return; } eNB_mac_inst[Mod_id].bcch_active=0; *nprb=0; *nCCE=0; //LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame); } #ifdef Rel10 s8 get_mbsfn_sf_alloction (unsigned char Mod_id, u8 mbsfn_sync_area){ // currently there is one-to-one mapping between sf allocation pattern and sync area if (mbsfn_sync_area > MAX_MBSFN_AREA){ LOG_W(MAC,"[eNB %d] MBSFN synchronization area %d out of range\n ", Mod_id, mbsfn_sync_area); return -1; } else if (eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[mbsfn_sync_area] != NULL) return mbsfn_sync_area; else { LOG_W(MAC,"[eNB %d] MBSFN Subframe Config pattern %d not found \n ", Mod_id, mbsfn_sync_area); return -1; } } int schedule_MBMS(unsigned char Mod_id,u32 frame, u8 subframe) { int mcch_flag=0,mtch_flag=0, msi_flag=0; int mbsfn_period =0;// 1<<(eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[0]->radioframeAllocationPeriod); int mcch_period = 0;//32<<(eNB_mac_inst[Mod_id].mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9); int mch_scheduling_period = 8<<(eNB_mac_inst[Mod_id].pmch_Config[0]->mch_SchedulingPeriod_r9); unsigned char mcch_sdu_length; unsigned char header_len_mcch=0,header_len_msi=0,header_len_mtch=0, header_len_mtch_temp=0, header_len_mcch_temp=0, header_len_msi_temp=0; int ii=0, msi_pos=0; int mcch_mcs; u16 TBS,j,padding=0,post_padding=0; mac_rlc_status_resp_t rlc_status; int num_mtch; int msi_length,i,k; unsigned char sdu_lcids[11], num_sdus=0, offset=0; u16 sdu_lengths[11], sdu_length_total=0; unsigned char mch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; // check the max value, this is for dlsch only eNB_mac_inst[Mod_id].MCH_pdu.Pdu_size=0; for (i=0; i< eNB_mac_inst[Mod_id].num_active_mbsfn_area; i++ ){ // assume, that there is always a mapping if ((j=get_mbsfn_sf_alloction(Mod_id,i)) == -1) return 0; mbsfn_period = 1<<(eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->radioframeAllocationPeriod); mcch_period = 32<<(eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_RepetitionPeriod_r9); msi_pos=0; ii=0; LOG_D(MAC,"[eNB %d] Frame %d subframe %d : Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d)\n", Mod_id,frame, subframe,i,eNB_mac_inst[Mod_id].num_active_mbsfn_area, j,eNB_mac_inst[Mod_id].num_sf_allocation_pattern,mbsfn_period,mcch_period); switch (eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.signallingMCS_r9) { case 0: mcch_mcs = 2; break; case 1: mcch_mcs = 7; break; case 2: mcch_mcs = 13; break; case 3: mcch_mcs = 19; break; } // 1st: Check the MBSFN subframes from SIB2 info (SF allocation pattern i, max 8 non-overlapping patterns exist) if (frame % mbsfn_period == eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->radioframeAllocationOffset){ // MBSFN frame if (eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame){// one-frame format // Find the first subframe in this MCH to transmit MSI if (frame % mch_scheduling_period == eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->radioframeAllocationOffset ) { while (ii == 0) { ii = eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & (0x80>>msi_pos); msi_pos++; } //LOG_D(MAC,"[eNB %d] Frame %d subframe %d : sync area %d sf allocation pattern %d sf alloc %x msi pos is %d \n", Mod_id,frame, subframe,i,j,eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0], msi_pos); } // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1 switch (subframe) { case 1: if (mac_xface->lte_frame_parms->frame_type == FDD) { if ((eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) { if (msi_pos == 1) msi_flag = 1; if ( (frame % mcch_period == eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && ((eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) ) mcch_flag = 1; mtch_flag = 1; } } break; case 2: if (mac_xface->lte_frame_parms->frame_type == FDD){ if ((eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) { if (msi_pos == 2) msi_flag = 1; if ( (frame % mcch_period == eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && ((eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) ) mcch_flag = 1; mtch_flag = 1; } } break; case 3: if (mac_xface->lte_frame_parms->frame_type == TDD){// TDD if ((eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) { if (msi_pos == 1) msi_flag = 1; if ( (frame % mcch_period == eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && ((eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) ) mcch_flag = 1; mtch_flag = 1; } } else {// FDD if ((eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) { if (msi_pos == 3) msi_flag = 1; if ( (frame % mcch_period == eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && ((eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) ) mcch_flag = 1; mtch_flag = 1; } } break; case 4: if (mac_xface->lte_frame_parms->frame_type == TDD){ if ((eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) { if (msi_pos == 2) msi_flag = 1; if ( (frame % mcch_period == eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && ((eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) ) mcch_flag = 1; mtch_flag = 1; } } break; case 6: if (mac_xface->lte_frame_parms->frame_type == FDD){ if ((eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) { if (msi_pos == 4) msi_flag = 1; if ( (frame % mcch_period == eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && ((eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) ) mcch_flag = 1; mtch_flag = 1; } } break; case 7: if (mac_xface->lte_frame_parms->frame_type == TDD){ // TDD if ((eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) { if (msi_pos == 3) msi_flag = 1; if ( (frame % mcch_period == eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && ((eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) ) mcch_flag = 1; mtch_flag = 1; } } else {// FDD if ((eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) { if (msi_pos == 5) msi_flag = 1; if ( (frame % mcch_period == eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && ((eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) ) mcch_flag = 1; mtch_flag = 1; } } break; case 8: if (mac_xface->lte_frame_parms->frame_type == TDD){ //TDD if ((eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) { if (msi_pos == 4) msi_flag = 1; if ( (frame % mcch_period == eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && ((eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) ) mcch_flag = 1; mtch_flag = 1; } } else{ // FDD if ((eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) { if (msi_pos == 6) msi_flag = 1; if ( (frame % mcch_period == eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && ((eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) ) mcch_flag = 1; mtch_flag = 1; } } break; case 9: if (mac_xface->lte_frame_parms->frame_type == TDD){ if ((eNB_mac_inst[Mod_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) { if (msi_pos == 5) msi_flag = 1; if ( (frame % mcch_period == eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && ((eNB_mac_inst[Mod_id].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) ) mcch_flag = 1; mtch_flag = 1; } } break; }// end switch // sf allocation is non-overlapping if ((msi_flag==1) || (mcch_flag==1) || (mtch_flag==1)){ LOG_D(MAC,"[eNB %d] Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n", Mod_id, frame, subframe,i,j,msi_flag,mcch_flag,mtch_flag); break; } } else {// four-frame format } } } // end of for loop eNB_mac_inst[Mod_id].msi_active=0; eNB_mac_inst[Mod_id].mcch_active=0; eNB_mac_inst[Mod_id].mtch_active=0; // Calculate the mcs if ((msi_flag==1) || (mcch_flag==1)) { eNB_mac_inst[Mod_id].MCH_pdu.mcs = mcch_mcs; } else if (mtch_flag == 1) { // only MTCH in this subframe eNB_mac_inst[Mod_id].MCH_pdu.mcs = eNB_mac_inst[Mod_id].pmch_Config[0]->dataMCS_r9; } // 2nd: Create MSI, get MCCH from RRC and MTCHs from RLC // there is MSI (MCH Scheduling Info) if (msi_flag == 1) { // Create MSI here u16 msi_control_element[29], *msi_ptr; msi_ptr = &msi_control_element[0]; ((MSI_ELEMENT *) msi_ptr)->lcid = MCCH_LCHANID; //MCCH if (mcch_flag==1) { ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0; ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0; } else { // no mcch for this MSP ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0x7;// stop value is 2047 ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xff; } msi_ptr+= sizeof(MSI_ELEMENT); //Header for MTCHs num_mtch = eNB_mac_inst[Mod_id].mbms_SessionList[0]->list.count; for (k=0;klcid = eNB_mac_inst[Mod_id].mbms_SessionList[0]->list.array[k]->logicalChannelIdentity_r9;//mtch_lcid; ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0; // last subframe of this mtch (only one mtch now) ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xB; msi_ptr+=sizeof(MSI_ELEMENT); } msi_length = msi_ptr-msi_control_element; if (msi_length<128) header_len_msi = 2; else header_len_msi = 3; LOG_D(MAC,"[eNB %d] Frame %d : MSI->MCH, length of MSI is %d bytes \n",Mod_id,frame,msi_length); //LOG_D(MAC,"Scheduler: MSI is transmitted in this subframe \n" ); // LOG_D(MAC,"Scheduler: MSI length is %d bytes\n",msi_length); // Store MSI data to mch_buffer[0] memcpy((char *)&mch_buffer[sdu_length_total], msi_control_element, msi_length); sdu_lcids[num_sdus] = MCH_SCHDL_INFO; sdu_lengths[num_sdus] = msi_length; sdu_length_total += sdu_lengths[num_sdus]; LOG_I(MAC,"[eNB %d] Create %d bytes for MSI\n",Mod_id,sdu_lengths[num_sdus]); num_sdus++; eNB_mac_inst[Mod_id].msi_active=1; } // there is MCCH if (mcch_flag == 1) { LOG_D(MAC,"[eNB %d] Frame %d Subframe %d: Schedule MCCH MESSAGE (area %d, sfAlloc %d)\n", Mod_id,frame, subframe, i, j); mcch_sdu_length = mac_rrc_data_req(Mod_id, frame, MCCH,1, &eNB_mac_inst[Mod_id].MCCH_pdu.payload[0], 1,// this is eNB Mod_id, // index i); // this is the mbsfn sync area index if (mcch_sdu_length > 0) { LOG_D(MAC,"[eNB %d] Frame %d subframe %d : MCCH->MCH, Received %d bytes from RRC \n",Mod_id,frame,subframe,mcch_sdu_length); header_len_mcch = 2; if (mac_xface->lte_frame_parms->frame_type == TDD) { LOG_D(MAC,"[eNB %d] Frame %d subframe %d: Scheduling MCCH->MCH (TDD) for MCCH message %d bytes (mcs %d )\n", Mod_id, frame,subframe, mcch_sdu_length, mcch_mcs); } else { LOG_I(MAC,"[eNB %d] Frame %d subframe %d: Scheduling MCCH->MCH (FDD) for MCCH message %d bytes (mcs %d)\n", Mod_id, frame, subframe, mcch_sdu_length, mcch_mcs); } eNB_mac_inst[Mod_id].mcch_active=1; memcpy((char *)&mch_buffer[sdu_length_total], &eNB_mac_inst[Mod_id].MCCH_pdu.payload[0], mcch_sdu_length); sdu_lcids[num_sdus] = MCCH_LCHANID; sdu_lengths[num_sdus] = mcch_sdu_length; if (sdu_lengths[num_sdus]>128) header_len_mcch = 3; sdu_length_total += sdu_lengths[num_sdus]; LOG_D(MAC,"[eNB %d] Got %d bytes for MCCH from RRC \n",Mod_id,sdu_lengths[num_sdus]); num_sdus++; } } TBS = mac_xface->get_TBS_DL(eNB_mac_inst[Mod_id].MCH_pdu.mcs, mac_xface->lte_frame_parms->N_RB_DL); #ifdef Rel10 // do not let mcch and mtch multiplexing when relaying is active // for sync area 1, so not transmit data //if ((i == 0) && ((eNB_mac_inst[Mod_id].MBMS_flag != multicast_relay) || (eNB_mac_inst[Mod_id].mcch_active==0))) { #endif // there is MTCHs, loop if there are more than 1 if (mtch_flag == 1) { // Calculate TBS /* if ((msi_flag==1) || (mcch_flag==1)) { TBS = mac_xface->get_TBS(mcch_mcs, mac_xface->lte_frame_parms->N_RB_DL); } else { // only MTCH in this subframe TBS = mac_xface->get_TBS(eNB_mac_inst[Mod_id].pmch_Config[0]->dataMCS_r9, mac_xface->lte_frame_parms->N_RB_DL); } */ // get MTCH data from RLC (like for DTCH) LOG_D(MAC,"[eNB %d] Frame %d subframe %d: Schedule MTCH (area %d, sfAlloc %d)\n",Mod_id,frame,subframe,i,j); header_len_mtch = 3; LOG_D(MAC,"[eNB %d], Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n", Mod_id,frame,MTCH,TBS, TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch); rlc_status = mac_rlc_status_ind(Mod_id,frame,1,RLC_MBMS_YES,MTCH+ (maxDRB + 3) * MAX_MOBILES_PER_RG, TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch); //printf("frame %d, subframe %d, rlc_status.bytes_in_buffer is %d\n",frame,subframe, rlc_status.bytes_in_buffer); if (rlc_status.bytes_in_buffer >0) { LOG_I(MAC,"[eNB %d][MBMS USER-PLANE], Frame %d, MTCH->MCH, Requesting %d bytes from RLC (header len mtch %d)\n", Mod_id,frame,TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch,header_len_mtch); sdu_lengths[num_sdus] = mac_rlc_data_req(Mod_id,frame, RLC_MBMS_YES, MTCH + (maxDRB + 3) * MAX_MOBILES_PER_RG, (char*)&mch_buffer[sdu_length_total]); //sdu_lengths[num_sdus] = mac_rlc_data_req(Mod_id,frame, RLC_MBMS_NO, MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)), (char*)&mch_buffer[sdu_length_total]); LOG_I(MAC,"[eNB %d][MBMS USER-PLANE] Got %d bytes for MTCH %d\n",Mod_id,sdu_lengths[num_sdus],MTCH); eNB_mac_inst[Mod_id].mtch_active=1; sdu_lcids[num_sdus] = MTCH; sdu_length_total += sdu_lengths[num_sdus]; if (sdu_lengths[num_sdus] < 128) header_len_mtch = 2; num_sdus++; } else { header_len_mtch = 0; } } #ifdef Rel10 // } #endif // FINAL STEP: Prepare and multiplexe MSI, MCCH and MTCHs if ((sdu_length_total + header_len_msi + header_len_mcch + header_len_mtch) >0) { // Adjust the last subheader /* if ((msi_flag==1) || (mcch_flag==1)) { eNB_mac_inst[Mod_id].MCH_pdu.mcs = mcch_mcs; } else if (mtch_flag == 1) { // only MTCH in this subframe eNB_mac_inst[Mod_id].MCH_pdu.mcs = eNB_mac_inst[Mod_id].pmch_Config[0]->dataMCS_r9; } */ header_len_mtch_temp = header_len_mtch; header_len_mcch_temp = header_len_mcch; header_len_msi_temp = header_len_msi; if (header_len_mtch>0) header_len_mtch=1; // remove Length field in the subheader for the last PDU else if (header_len_mcch>0) header_len_mcch=1; else header_len_msi=1; // Calculate the padding if ((TBS - header_len_mtch - header_len_mcch - header_len_msi - sdu_length_total) <= 2) { padding = (TBS - header_len_mtch - header_len_mcch - header_len_msi - sdu_length_total); post_padding = 0; } else {// using post_padding, give back the Length field of subheader for the last PDU padding = 0; if (header_len_mtch>0) header_len_mtch = header_len_mtch_temp; else if (header_len_mcch>0) header_len_mcch = header_len_mcch_temp; else header_len_msi = header_len_msi_temp; post_padding = TBS - sdu_length_total - header_len_msi - header_len_mcch - header_len_mtch; } // Generate the MAC Header for MCH // here we use the function for DLSCH because DLSCH & MCH have the same Header structure offset = generate_dlsch_header((unsigned char*)eNB_mac_inst[Mod_id].MCH_pdu.payload, num_sdus, sdu_lengths, sdu_lcids, 255, // no drx 0, // no timing advance NULL, // no contention res id padding, post_padding); eNB_mac_inst[Mod_id].MCH_pdu.Pdu_size=TBS; eNB_mac_inst[Mod_id].MCH_pdu.sync_area=i; eNB_mac_inst[Mod_id].MCH_pdu.msi_active= eNB_mac_inst[Mod_id].msi_active; eNB_mac_inst[Mod_id].MCH_pdu.mcch_active= eNB_mac_inst[Mod_id].mcch_active; eNB_mac_inst[Mod_id].MCH_pdu.mtch_active= eNB_mac_inst[Mod_id].mtch_active; LOG_D(MAC," MCS for this sf is %d (mcch active %d, mtch active %d)\n", eNB_mac_inst[Mod_id].MCH_pdu.mcs, eNB_mac_inst[Mod_id].MCH_pdu.mcch_active,eNB_mac_inst[Mod_id].MCH_pdu.mtch_active ); LOG_I(MAC,"[eNB %d][MBMS USER-PLANE ] Generate header : sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,padding %d,post_padding %d (mcs %d, TBS %d), header MTCH %d, header MCCH %d, header MSI %d\n", Mod_id,sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],offset,padding,post_padding,eNB_mac_inst[Mod_id].MCH_pdu.mcs,TBS,header_len_mtch, header_len_mcch, header_len_msi); // copy SDU to mch_pdu after the MAC Header memcpy(&eNB_mac_inst[Mod_id].MCH_pdu.payload[offset],mch_buffer,sdu_length_total); // filling remainder of MCH with random data if necessery for (j=0;j<(TBS-sdu_length_total-offset);j++) eNB_mac_inst[Mod_id].MCH_pdu.payload[offset+sdu_length_total+j] = (char)(taus()&0xff); #if defined(USER_MODE) && defined(OAI_EMU) /* Tracing of PDU is done on UE side */ if (oai_emulation.info.opt_enabled) trace_pdu(1, (uint8_t *)eNB_mac_inst[Mod_id].MCH_pdu.payload, TBS, Mod_id, 6, 0xffff, // M_RNTI = 6 in wirehsark eNB_mac_inst[Mod_id].subframe,0,0); LOG_D(OPT,"[eNB %d][MCH] Frame %d : MAC PDU with size %d\n", Mod_id, frame, TBS); #endif /* for (j=0;jmacphy_exit("[MAC][eNB Scheduler] CCCH not allocated\n"); else { //msg("[MAC][eNB %d] Frame %d, subframe %d: got %d bytes from RRC\n",Mod_id,frame, subframe,rrc_sdu_length); } } LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, subframe %d: UE_id %d, Is_rrc_registered %d, rrc_sdu_length %d\n", Mod_id,frame, subframe,UE_id, Is_rrc_registered,rrc_sdu_length); if (rrc_sdu_length>0) { LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, subframe %d: Generating Msg4 with RRC Piggyback (RA proc %d, RNTI %x)\n", Mod_id,frame, subframe,i,RA_template[i].rnti); //msg("[MAC][eNB %d][RAPROC] Frame %d, subframe %d: Received %d bytes for Msg4: \n",Mod_id,frame,subframe,rrc_sdu_length); // for (j=0;jlte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } break; case 25: ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } break; case 50: ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } break; case 100: ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } break; } } else { // FDD DCI switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } break; case 25: ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } break; case 50: ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } break; case 100: ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } break; } } RA_template[i].generate_Msg4=0; RA_template[i].generate_Msg4_dci=1; RA_template[i].wait_ack_Msg4=1; RA_template[i].RA_active = 0; lcid=0; if ((TBsize - rrc_sdu_length - msg4_header) <= 2) { msg4_padding = TBsize - rrc_sdu_length - msg4_header; msg4_post_padding = 0; } else { msg4_padding = 0; msg4_post_padding = TBsize - rrc_sdu_length - msg4_header -1; } LOG_I(MAC,"[eNB %d][RAPROC] Frame %d subframe %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", Mod_id,frame,subframe,TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding); offset = generate_dlsch_header((unsigned char*)eNB_mac_inst[Mod_id].DLSCH_pdu[(unsigned char)UE_id][0].payload[0], 1, //num_sdus &rrc_sdu_length, // &lcid, // sdu_lcid 255, // no drx 0, // no timing advance RA_template[i].cont_res_id, // contention res id msg4_padding, // no padding msg4_post_padding); memcpy((void*)&eNB_mac_inst[Mod_id].DLSCH_pdu[(unsigned char)UE_id][0].payload[0][(unsigned char)offset], &eNB_mac_inst[Mod_id].CCCH_pdu.payload[0], rrc_sdu_length); #if defined(USER_MODE) && defined(OAI_EMU) if (oai_emulation.info.opt_enabled){ trace_pdu(1, (uint8_t *)eNB_mac_inst[Mod_id].DLSCH_pdu[(unsigned char)UE_id][0].payload[0], rrc_sdu_length, UE_id, 3, find_UE_RNTI(Mod_id, UE_id), eNB_mac_inst[Mod_id].subframe,0,0); LOG_D(OPT,"[eNB %d][DLSCH] Frame %d trace pdu for rnti %x with size %d\n", Mod_id, frame, find_UE_RNTI(Mod_id,UE_id), rrc_sdu_length); } #endif *nprb= (*nprb) + 3; *nCCE = (*nCCE) + 4; } //try here } /* else if (eNB_mac_inst[Mod_id].RA_template[i].wait_ack_Msg4==1) { // check HARQ status and retransmit if necessary LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, subframe %d: Checking if Msg4 was acknowledged :\n",Mod_id,frame,subframe); // Get candidate harq_pid from PHY mac_xface->get_ue_active_harq_pid(Mod_id,eNB_mac_inst[Mod_id].RA_template[i].rnti,subframe,&harq_pid,&round,0); if (round>0) { *nprb= (*nprb) + 3; *nCCE = (*nCCE) + 4; } } */ } } } // This has to be updated to include BSR information u8 UE_is_to_be_scheduled(u8 Mod_id,u8 UE_id) { // LOG_D(MAC,"[eNB %d][PUSCH] Frame %d subframe %d Scheduling UE %d\n",Mod_id,rnti,frame,subframe, // UE_id); if ((eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0]>0) || (eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1]>0) || (eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2]>0) || (eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3]>0) || (eNB_mac_inst[Mod_id].UE_template[UE_id].ul_SR>0)) // uplink scheduling request return(1); else return(0); } u32 bytes_to_bsr_index(s32 nbytes) { u32 i=0; if (nbytes<0) return(0); while ((iget_nCCE_max(Mod_id) - *nCCE; // UE data info; // check which UE has data to transmit // function to decide the scheduling // e.g. scheduling_rslt = Greedy(granted_UEs, nb_RB) // default function for default scheduling // // output of scheduling, the UE numbers in RBs, where it is in the code??? // check if RA (Msg3) is active in this subframe, if so skip the PRBs used for Msg3 // Msg3 is using 1 PRB so we need to increase first_rb accordingly // not sure about the break (can there be more than 1 active RA procedure?) for (i=0;i 0) && (*nCCE == 0)) schedule_ulsch_cba_rnti(Mod_id, cooperation_flag, frame, subframe, sched_subframe, granted_UEs, nCCE, &nCCE_available, &first_rb); #endif } #ifdef CBA void schedule_ulsch_cba_rnti(u8 Mod_id, unsigned char cooperation_flag, u32 frame, unsigned char subframe, unsigned char sched_subframe, u8 granted_UEs, unsigned int *nCCE, unsigned int *nCCE_available, u16 *first_rb){ DCI0_5MHz_TDD_1_6_t *ULSCH_dci_tdd16; DCI0_5MHz_FDD_t *ULSCH_dci_fdd; DCI_PDU *DCI_pdu= &eNB_mac_inst[Mod_id].DCI_pdu; u8 rb_table_index=0, aggregation=2; u32 rballoc; u8 cba_group, cba_resources; u8 required_rbs[NUM_MAX_CBA_GROUP], weight[NUM_MAX_CBA_GROUP], num_cba_resources[NUM_MAX_CBA_GROUP]; u8 available_rbs= ceil(mac_xface->lte_frame_parms->N_RB_UL-1-*first_rb); u8 remaining_rbs= available_rbs; u8 allocated_rbs; // We compute the weight of each group and initialize some variables for (cba_group=0;cba_group (1< 0) && eNB_mac_inst[Mod_id].cba_rnti[cba_group] != 0){ // to be refined in case of : granted_UEs >> weight[cba_group]*available_rbs required_rbs[cba_group] = (u8)ceil((weight[cba_group]*available_rbs)/granted_UEs); while (remaining_rbs < required_rbs[cba_group] ) required_rbs[cba_group]--; /* while (rb_table[rb_table_index] < required_rbs[cba_group]) rb_table_index++; while (rb_table[rb_table_index] > remaining_rbs ) rb_table_index--; remaining_rbs-=rb_table[rb_table_index]; required_rbs[cba_group]=rb_table[rb_table_index]; */ // to be refined if (weight[cba_group] < required_rbs[cba_group]) num_cba_resources[cba_group]=(u8)ceil(weight[cba_group]/2.0); else num_cba_resources[cba_group]=(u8)ceil(required_rbs[cba_group]/2.0); while ((*nCCE) + (1< *nCCE_available) num_cba_resources[cba_group]--; LOG_N(MAC,"[eNB %d] Frame %d, subframe %d: cba group %d weight/granted_ues %d/%d available/required rb (%d/%d), num resources %d->1 (*scaled down*) \n", Mod_id, frame, subframe, cba_group, weight[cba_group], granted_UEs, available_rbs,required_rbs[cba_group], num_cba_resources[cba_group]); num_cba_resources[cba_group]=1; } } // phase 2 for (cba_group=0;cba_group remaining_rbs ) rb_table_index--; remaining_rbs-=rb_table[rb_table_index]; allocated_rbs=rb_table[rb_table_index]; rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_UL, *first_rb, rb_table[rb_table_index]); *first_rb+=rb_table[rb_table_index]; LOG_D(MAC,"[eNB %d] Frame %d, subframe %d: CBA %d rnti %x, total/required/allocated/remaining rbs (%d/%d/%d/%d), rballoc %d, nCCE (%d/%d)\n", Mod_id, frame, subframe, cba_group,eNB_mac_inst[Mod_id].cba_rnti[cba_group], available_rbs, required_rbs[cba_group], allocated_rbs, remaining_rbs,rballoc, *nCCE_available,*nCCE); if (mac_xface->lte_frame_parms->frame_type == TDD) { ULSCH_dci_tdd16 = (DCI0_5MHz_TDD_1_6_t *)eNB_mac_inst[Mod_id].UE_template[cba_group].ULSCH_DCI[0]; ULSCH_dci_tdd16->type = 0; ULSCH_dci_tdd16->hopping = 0; ULSCH_dci_tdd16->rballoc = rballoc; ULSCH_dci_tdd16->mcs = 2; ULSCH_dci_tdd16->ndi = 1; ULSCH_dci_tdd16->TPC = 1; ULSCH_dci_tdd16->cshift = cba_group; ULSCH_dci_tdd16->dai = eNB_mac_inst[Mod_id].UE_template[cba_group].DAI_ul[sched_subframe]; ULSCH_dci_tdd16->cqi_req = 1; //add_ue_spec_dci add_common_dci(DCI_pdu, ULSCH_dci_tdd16, eNB_mac_inst[Mod_id].cba_rnti[cba_group], sizeof(DCI0_5MHz_TDD_1_6_t), aggregation, sizeof_DCI0_5MHz_TDD_1_6_t, format0, 0); } else { ULSCH_dci_fdd = (DCI0_5MHz_FDD_t *)eNB_mac_inst[Mod_id].UE_template[cba_group].ULSCH_DCI[0]; ULSCH_dci_fdd->type = 0; ULSCH_dci_fdd->hopping = 0; ULSCH_dci_fdd->rballoc = rballoc; ULSCH_dci_fdd->mcs = 2; ULSCH_dci_fdd->ndi = 1; ULSCH_dci_fdd->TPC = 1; ULSCH_dci_fdd->cshift = 0; ULSCH_dci_fdd->cqi_req = 1; //add_ue_spec_dci add_common_dci(DCI_pdu, ULSCH_dci_fdd, eNB_mac_inst[Mod_id].cba_rnti[cba_group], sizeof(DCI0_5MHz_FDD_t), aggregation, sizeof_DCI0_5MHz_FDD_t, format0, 0); } *nCCE = (*nCCE) + (1<get_nCCE_max(Mod_id) - *nCCE; // break;// for the moment only schedule one } } } #endif void schedule_ulsch_rnti(u8 Mod_id, unsigned char cooperation_flag, u32 frame, unsigned char subframe, unsigned char sched_subframe, u8 granted_UEs, unsigned int *nCCE, unsigned int *nCCE_available, u16 *first_rb){ unsigned char UE_id; unsigned char next_ue; unsigned char aggregation=2; u16 rnti; u8 round = 0; u8 harq_pid = 0; void *ULSCH_dci; LTE_eNB_UE_stats* eNB_UE_stats; DCI_PDU *DCI_pdu= &eNB_mac_inst[Mod_id].DCI_pdu; u8 status=0;//,status0 = 0,status1 = 0; // u8 k=0; u8 rb_table_index; u16 TBS,i; u32 buffer_occupancy; u32 tmp_bsr; u32 cqi_req,cshift,ndi,mcs,rballoc; for (UE_id=0;UE_id (1<get_eNB_UE_stats(Mod_id,rnti); if (eNB_UE_stats==NULL) mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n"); LOG_D(MAC,"[eNB %d] Scheduler Frame %d, subframe %d, nCCE %d: Checking ULSCH next UE_id %d mode id %d (rnti %x,mode %s), format 0\n",Mod_id,frame,subframe,*nCCE,next_ue,Mod_id, rnti,mode_string[eNB_UE_stats->mode]); if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel s8 ret; // Get candidate harq_pid from PHY ret = mac_xface->get_ue_active_harq_pid(Mod_id,rnti,subframe,&harq_pid,&round,1); // printf("Got harq_pid %d, round %d, next_ue %d\n",harq_pid,round,next_ue); /* [SR] 01/07/13: Don't schedule UE if we cannot get harq pid */ if ((((UE_is_to_be_scheduled(Mod_id,UE_id)>0)) || (round>0) || ((frame%10)==0)) && (ret == 0)) { // if there is information on bsr of DCCH, DTCH or if there is UL_SR, or if there is a packet to retransmit, or we want to schedule a periodic feedback every 10 frames LOG_D(MAC,"[eNB %d][PUSCH %x] Frame %d subframe %d Scheduling UE %d (SR %d)\n", Mod_id,rnti,frame,subframe,UE_id, eNB_mac_inst[Mod_id].UE_template[UE_id].ul_SR); // reset the scheduling request eNB_mac_inst[Mod_id].UE_template[UE_id].ul_SR = 0; aggregation = process_ue_cqi(Mod_id,next_ue); // =2 by default!! // msg("[MAC][eNB] subframe %d: aggregation %d\n",subframe,aggregation); status = mac_get_rrc_status(Mod_id,1,next_ue); if (status < RRC_CONNECTED) cqi_req = 0; else cqi_req = 1; if (round > 0) { ndi = 0; // if round != 0, it means the data is not new. ndi:new data indicator } else { ndi = 1; } //if ((frame&1)==0) { // choose this later based on Power Headroom if (ndi == 1) {// set mcs for first round mcs = openair_daq_vars.target_ue_ul_mcs; } else { // increment RV if ((round&3)==0) mcs = openair_daq_vars.target_ue_ul_mcs; // same as inital transmission else mcs = (round&3) + 28; //not correct for round==4! } LOG_D(MAC,"[eNB %d] ULSCH scheduler: Ndi %d, mcs %d\n",Mod_id,ndi,mcs); if((cooperation_flag > 0) && (next_ue == 1)) { // Allocation on same set of RBs // RIV:resource indication value // function in openair1/PHY/LTE_TRANSPORT/dci_tools.c rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_UL, ((next_ue-1)*4),//openair_daq_vars.ue_ul_nb_rb), 4);//openair_daq_vars.ue_ul_nb_rb); } else if ((ndi==1) && (mcs < 29)) { rb_table_index = 1; TBS = mac_xface->get_TBS_UL(mcs,rb_table[rb_table_index]); buffer_occupancy = ((eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0] == 0) && (eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1] == 0) && (eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2] == 0) && (eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3] == 0))? BSR_TABLE[1] : // This is when we've received SR and buffers are fully served BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0]]+ BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1]]+ BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2]]+ BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3]]; // This is when remaining data in UE buffers (even if SR is triggered) LOG_D(MAC,"[eNB %d][PUSCH %d/%x] Frame %d subframe %d Scheduled UE, BSR for LCGID0 %d, LCGID1 %d, LCGID2 %d LCGID3 %d, BO %d\n", Mod_id,UE_id,rnti,frame,subframe, eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0], eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1], eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2], eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3], buffer_occupancy); while ((TBS < buffer_occupancy) && rb_table[rb_table_index]<(mac_xface->lte_frame_parms->N_RB_UL-1-*first_rb)){ // continue until we've exhauster the UEs request or the total number of available PRBs /* LOG_I(MAC,"[eNB %d][PUSCH %x] Frame %d subframe %d Scheduled UE (rb_table_index %d => TBS %d)\n", Mod_id,rnti,frame,subframe, rb_table_index,TBS); */ rb_table_index++; TBS = mac_xface->get_TBS_UL(mcs,rb_table[rb_table_index]); } if (rb_table[rb_table_index]>(mac_xface->lte_frame_parms->N_RB_UL-1-*first_rb)) { rb_table_index--; TBS = mac_xface->get_TBS_UL(mcs,rb_table[rb_table_index]); } //rb_table_index = 8; LOG_I(MAC,"[eNB %d][PUSCH %d/%x] Frame %d subframe %d Scheduled UE (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n", Mod_id,UE_id,rnti,frame,subframe,mcs, *first_rb,rb_table[rb_table_index], rb_table_index,mac_xface->get_TBS_UL(mcs,rb_table[rb_table_index]), harq_pid); rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_UL, *first_rb, rb_table[rb_table_index]);//openair_daq_vars.ue_ul_nb_rb); *first_rb+=rb_table[rb_table_index]; // increment for next UE allocation eNB_mac_inst[Mod_id].UE_template[UE_id].nb_rb_ul[harq_pid] = rb_table[rb_table_index]; //store for possible retransmission buffer_occupancy -= mac_xface->get_TBS_UL(mcs,rb_table[rb_table_index]); i = bytes_to_bsr_index((s32)buffer_occupancy); // Adjust BSR entries for LCGIDs if (i>0) { if (eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0] <= i) { tmp_bsr = BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0]]; eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0] = 0; if (BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1]] <= (buffer_occupancy-tmp_bsr)) { tmp_bsr += BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1]]; eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1] = 0; if (BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2]] <= (buffer_occupancy-tmp_bsr)) { tmp_bsr += BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2]]; eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2] = 0; if (BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3]] <= (buffer_occupancy-tmp_bsr)) { tmp_bsr += BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3]]; eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3] = 0; } else { eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3] = bytes_to_bsr_index((s32)BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3]] - ((s32)buffer_occupancy - (s32)tmp_bsr)); } } else { eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2] = bytes_to_bsr_index((s32)BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2]] - ((s32)buffer_occupancy -(s32)tmp_bsr)); } } else { eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1] = bytes_to_bsr_index((s32)BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1]] - (s32)buffer_occupancy); } } else { eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0] = bytes_to_bsr_index((s32)BSR_TABLE[eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0]] - (s32)buffer_occupancy); } } else { // we have flushed all buffers so clear bsr eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID0] = 0; eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID1] = 0; eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID2] = 0; eNB_mac_inst[Mod_id].UE_template[UE_id].bsr_info[LCGID3] = 0; } } // ndi==1 else { //we schedule a retransmission LOG_I(MAC,"[eNB %d][PUSCH %d/%x] Frame %d subframe %d Scheduled UE retransmission (mcs %d, first rb %d, nb_rb %d, TBS %d, harq_pid %d)\n", Mod_id,UE_id,rnti,frame,subframe,mcs, *first_rb,eNB_mac_inst[Mod_id].UE_template[UE_id].nb_rb_ul[harq_pid], mac_xface->get_TBS_UL(mcs,eNB_mac_inst[Mod_id].UE_template[UE_id].nb_rb_ul[harq_pid]), harq_pid); rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_UL, *first_rb, eNB_mac_inst[Mod_id].UE_template[UE_id].nb_rb_ul[harq_pid]); *first_rb+=eNB_mac_inst[Mod_id].UE_template[UE_id].nb_rb_ul[harq_pid]; // increment for next UE allocation } // Cyclic shift for DM RS if(cooperation_flag == 2) { if(next_ue == 1)// For Distriibuted Alamouti, cyclic shift applied to 2nd UE cshift = 1; else cshift = 0; } else cshift = 0;// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1) if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->N_RB_UL) { case 6: ULSCH_dci = eNB_mac_inst[Mod_id].UE_template[next_ue].ULSCH_DCI[harq_pid]; ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->type = 0; ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->hopping = 0; ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->rballoc = rballoc; ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->mcs = mcs; ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->ndi = ndi; ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->TPC = 1; ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->cshift = cshift; ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->dai = eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul[sched_subframe]; ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req = cqi_req; add_ue_spec_dci(DCI_pdu, ULSCH_dci, rnti, sizeof(DCI0_1_5MHz_TDD_1_6_t), aggregation, sizeof_DCI0_1_5MHz_TDD_1_6_t, format0, 0); break; default: case 25: ULSCH_dci = eNB_mac_inst[Mod_id].UE_template[next_ue].ULSCH_DCI[harq_pid]; ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->type = 0; ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->hopping = 0; ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->rballoc = rballoc; ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->mcs = mcs; ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->ndi = ndi; ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->TPC = 1; ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->cshift = cshift; ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->dai = eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul[sched_subframe]; ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req = cqi_req; add_ue_spec_dci(DCI_pdu, ULSCH_dci, rnti, sizeof(DCI0_5MHz_TDD_1_6_t), aggregation, sizeof_DCI0_5MHz_TDD_1_6_t, format0, 0); break; case 50: ULSCH_dci = eNB_mac_inst[Mod_id].UE_template[next_ue].ULSCH_DCI[harq_pid]; ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->type = 0; ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->hopping = 0; ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->rballoc = rballoc; ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->mcs = mcs; ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->ndi = ndi; ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->TPC = 1; ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->cshift = cshift; ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->dai = eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul[sched_subframe]; ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req = cqi_req; add_ue_spec_dci(DCI_pdu, ULSCH_dci, rnti, sizeof(DCI0_10MHz_TDD_1_6_t), aggregation, sizeof_DCI0_10MHz_TDD_1_6_t, format0, 0); break; case 100: ULSCH_dci = eNB_mac_inst[Mod_id].UE_template[next_ue].ULSCH_DCI[harq_pid]; ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->type = 0; ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->hopping = 0; ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->rballoc = rballoc; ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->mcs = mcs; ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->ndi = ndi; ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->TPC = 1; ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->cshift = cshift; ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->dai = eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul[sched_subframe]; ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req = cqi_req; add_ue_spec_dci(DCI_pdu, ULSCH_dci, rnti, sizeof(DCI0_20MHz_TDD_1_6_t), aggregation, sizeof_DCI0_20MHz_TDD_1_6_t, format0, 0); break; } } else { //FDD switch (mac_xface->lte_frame_parms->N_RB_UL) { case 25: default: ULSCH_dci = eNB_mac_inst[Mod_id].UE_template[next_ue].ULSCH_DCI[harq_pid]; ((DCI0_5MHz_FDD_t *)ULSCH_dci)->type = 0; ((DCI0_5MHz_FDD_t *)ULSCH_dci)->hopping = 0; ((DCI0_5MHz_FDD_t *)ULSCH_dci)->rballoc = rballoc; ((DCI0_5MHz_FDD_t *)ULSCH_dci)->mcs = mcs; ((DCI0_5MHz_FDD_t *)ULSCH_dci)->ndi = ndi; ((DCI0_5MHz_FDD_t *)ULSCH_dci)->TPC = 1; ((DCI0_5MHz_FDD_t *)ULSCH_dci)->cshift = cshift; ((DCI0_5MHz_FDD_t *)ULSCH_dci)->cqi_req = cqi_req; add_ue_spec_dci(DCI_pdu, ULSCH_dci, rnti, sizeof(DCI0_5MHz_FDD_t), aggregation, sizeof_DCI0_5MHz_FDD_t, format0, 0); break; case 6: ULSCH_dci = eNB_mac_inst[Mod_id].UE_template[next_ue].ULSCH_DCI[harq_pid]; ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->type = 0; ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->hopping = 0; ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->rballoc = rballoc; ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->mcs = mcs; ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->ndi = ndi; ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->TPC = 1; ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->cshift = cshift; ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->cqi_req = cqi_req; add_ue_spec_dci(DCI_pdu, ULSCH_dci, rnti, sizeof(DCI0_1_5MHz_FDD_t), aggregation, sizeof_DCI0_1_5MHz_FDD_t, format0, 0); break; case 50: ULSCH_dci = eNB_mac_inst[Mod_id].UE_template[next_ue].ULSCH_DCI[harq_pid]; ((DCI0_10MHz_FDD_t *)ULSCH_dci)->type = 0; ((DCI0_10MHz_FDD_t *)ULSCH_dci)->hopping = 0; ((DCI0_10MHz_FDD_t *)ULSCH_dci)->rballoc = rballoc; ((DCI0_10MHz_FDD_t *)ULSCH_dci)->mcs = mcs; ((DCI0_10MHz_FDD_t *)ULSCH_dci)->ndi = ndi; ((DCI0_10MHz_FDD_t *)ULSCH_dci)->TPC = 1; ((DCI0_10MHz_FDD_t *)ULSCH_dci)->cshift = cshift; ((DCI0_10MHz_FDD_t *)ULSCH_dci)->cqi_req = cqi_req; add_ue_spec_dci(DCI_pdu, ULSCH_dci, rnti, sizeof(DCI0_10MHz_FDD_t), aggregation, sizeof_DCI0_10MHz_FDD_t, format0, 0); break; case 100: ULSCH_dci = eNB_mac_inst[Mod_id].UE_template[next_ue].ULSCH_DCI[harq_pid]; ((DCI0_20MHz_FDD_t *)ULSCH_dci)->type = 0; ((DCI0_20MHz_FDD_t *)ULSCH_dci)->hopping = 0; ((DCI0_20MHz_FDD_t *)ULSCH_dci)->rballoc = rballoc; ((DCI0_20MHz_FDD_t *)ULSCH_dci)->mcs = mcs; ((DCI0_20MHz_FDD_t *)ULSCH_dci)->ndi = ndi; ((DCI0_20MHz_FDD_t *)ULSCH_dci)->TPC = 1; ((DCI0_20MHz_FDD_t *)ULSCH_dci)->cshift = cshift; ((DCI0_20MHz_FDD_t *)ULSCH_dci)->cqi_req = cqi_req; add_ue_spec_dci(DCI_pdu, ULSCH_dci, rnti, sizeof(DCI0_20MHz_FDD_t), aggregation, sizeof_DCI0_20MHz_FDD_t, format0, 0); break; } } //#ifdef DEBUG_eNB_SCHEDULER // dump_dci(mac_xface->lte_frame_parms, // &DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci-1]); //#endif add_ue_ulsch_info(Mod_id, next_ue, subframe, S_UL_SCHEDULED); *nCCE = (*nCCE) + (1<get_nCCE_max(Mod_id) - *nCCE; //msg("[MAC][eNB %d][ULSCH Scheduler] Frame %d, subframe %d: Generated ULSCH DCI for next UE_id %d, format 0\n", Mod_id,frame,subframe,next_ue); //break; // leave loop after first UE is schedule (avoids m } // UE_is_to_be_scheduled } // UE is in PUSCH } // loop over UE_id } u32 allocate_prbs(unsigned char UE_id,unsigned char nb_rb, u32 *rballoc) { int i; u32 rballoc_dci=0; unsigned char nb_rb_alloc=0; for (i=0;i<(mac_xface->lte_frame_parms->N_RB_DL-2);i+=2) { if (((*rballoc>>i)&3)==0) { *rballoc |= (3<>1)); nb_rb_alloc+=2; } if (nb_rb_alloc==nb_rb) return(rballoc_dci); } if ((mac_xface->lte_frame_parms->N_RB_DL&1)==1) { if ((*rballoc>>(mac_xface->lte_frame_parms->N_RB_DL-1)&1)==0) { *rballoc |= (1<<(mac_xface->lte_frame_parms->N_RB_DL-1)); rballoc_dci |= 1;//(1<<(mac_xface->lte_frame_parms->N_RB_DL>>1)); } } return(rballoc_dci); } u32 allocate_prbs_sub(int nb_rb, u8 *rballoc) { int check=0;//check1=0,check2=0; uint32_t rballoc_dci=0; //u8 number_of_subbands=13; LOG_D(MAC,"*****Check1RBALLOC****: %d%d%d%d (nb_rb %d,N_RBGS %d)\n", rballoc[3],rballoc[2],rballoc[1],rballoc[0],nb_rb,mac_xface->lte_frame_parms->N_RBGS); while((nb_rb >0) && (check < mac_xface->lte_frame_parms->N_RBGS)){ //printf("rballoc[%d] %d\n",check,rballoc[check]); if(rballoc[check] == 1){ rballoc_dci |= (1<<((mac_xface->lte_frame_parms->N_RBGS-1)-check)); switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: nb_rb--; case 25: if ((check == mac_xface->lte_frame_parms->N_RBGS-1)) nb_rb--; else nb_rb-=2; break; case 50: if ((check == mac_xface->lte_frame_parms->N_RBGS-1)) nb_rb-=2; else nb_rb-=3; break; case 100: nb_rb-=4; break; } } //printf("rb_alloc %x\n",rballoc_dci); check = check+1; // check1 = check1+2; } // rballoc_dci = (rballoc_dci)&(0x1fff); LOG_D(MAC,"*********RBALLOC : %x\n",rballoc_dci); // exit(-1); return (rballoc_dci); } void fill_DLSCH_dci(unsigned char Mod_id,u32 frame, unsigned char subframe,u32 RBalloc,u8 RA_scheduled,int mbsfn_flag) { // loop over all allocated UEs and compute frequency allocations for PDSCH unsigned char UE_id,first_rb,nb_rb=3; u16 rnti; unsigned char vrb_map[100]; u8 rballoc_sub[mac_xface->lte_frame_parms->N_RBGS]; //u8 number_of_subbands=13; u32 rballoc=RBalloc; // u32 test=0; unsigned char round; unsigned char harq_pid; void *DLSCH_dci=NULL; DCI_PDU *DCI_pdu= &eNB_mac_inst[Mod_id].DCI_pdu; int i; // u8 status=0; void *BCCH_alloc_pdu=(void*)&eNB_mac_inst[Mod_id].BCCH_alloc_pdu; int size_bits,size_bytes; if (mbsfn_flag>0) return; // clear vrb_map memset(vrb_map,0,100); // SI DLSCH // printf("BCCH check\n"); if (eNB_mac_inst[Mod_id].bcch_active == 1) { eNB_mac_inst[Mod_id].bcch_active = 0; LOG_D(MAC,"[eNB %d] Frame %d subframe %d: BCCH active\n", Mod_id, frame, subframe); // randomize frequency allocation for SI first_rb = (unsigned char)(taus()%(mac_xface->lte_frame_parms->N_RB_DL-4)); if (mac_xface->lte_frame_parms->frame_type == TDD) { } else { BCCH_alloc_pdu_fdd.rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(BCCH_alloc_pdu_fdd.vrb_type,BCCH_alloc_pdu_fdd.rballoc); } vrb_map[first_rb] = 1; vrb_map[first_rb+1] = 1; vrb_map[first_rb+2] = 1; vrb_map[first_rb+3] = 1; if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; rballoc |= mac_xface->get_rballoc(0,((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); add_common_dci(DCI_pdu, BCCH_alloc_pdu, SI_RNTI, sizeof(DCI1A_1_5MHz_TDD_1_6_t), 2, sizeof_DCI1A_1_5MHz_TDD_1_6_t, format1A,0); break; case 25: ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; rballoc |= mac_xface->get_rballoc(0,((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); add_common_dci(DCI_pdu, BCCH_alloc_pdu, SI_RNTI, sizeof(DCI1A_5MHz_TDD_1_6_t), 2, sizeof_DCI1A_5MHz_TDD_1_6_t, format1A,0); break; case 50: ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; rballoc |= mac_xface->get_rballoc(0,((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); add_common_dci(DCI_pdu, BCCH_alloc_pdu, SI_RNTI, sizeof(DCI1A_10MHz_TDD_1_6_t), 2, sizeof_DCI1A_10MHz_TDD_1_6_t, format1A,0); break; case 100: ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; rballoc |= mac_xface->get_rballoc(0,((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); add_common_dci(DCI_pdu, BCCH_alloc_pdu, SI_RNTI, sizeof(DCI1A_20MHz_TDD_1_6_t), 2, sizeof_DCI1A_20MHz_TDD_1_6_t, format1A,0); break; } } else { switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; rballoc |= mac_xface->get_rballoc(0,((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); add_common_dci(DCI_pdu, BCCH_alloc_pdu, SI_RNTI, sizeof(DCI1A_1_5MHz_FDD_t), 2, sizeof_DCI1A_1_5MHz_FDD_t, format1A,0); break; case 25: ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; rballoc |= mac_xface->get_rballoc(0,((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); add_common_dci(DCI_pdu, BCCH_alloc_pdu, SI_RNTI, sizeof(DCI1A_5MHz_FDD_t), 2, sizeof_DCI1A_5MHz_FDD_t, format1A,0); break; case 50: ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; rballoc |= mac_xface->get_rballoc(0,((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); add_common_dci(DCI_pdu, BCCH_alloc_pdu, SI_RNTI, sizeof(DCI1A_10MHz_FDD_t), 2, sizeof_DCI1A_10MHz_FDD_t, format1A,0); break; case 100: ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; rballoc |= mac_xface->get_rballoc(0,((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); add_common_dci(DCI_pdu, BCCH_alloc_pdu, SI_RNTI, sizeof(DCI1A_20MHz_FDD_t), 2, sizeof_DCI1A_20MHz_FDD_t, format1A,0); break; } } } if (RA_scheduled == 1) { for (i=0;ilte_frame_parms->N_RB_DL-4)); if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) break; } vrb_map[first_rb] = 1; vrb_map[first_rb+1] = 1; vrb_map[first_rb+2] = 1; vrb_map[first_rb+3] = 1; if (mac_xface->lte_frame_parms->frame_type == TDD) { switch(mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->type=1; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type=0; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->ndi=1; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rv=0; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->mcs=0; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->TPC=1; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type, ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc); break; case 25: ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->type=1; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->ndi=1; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rv=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->mcs=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->TPC=1; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type, ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc); break; case 50: ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->type=1; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type=0; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->ndi=1; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rv=0; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->mcs=0; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->TPC=1; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type, ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc); break; case 100: ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->type=1; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type=0; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->ndi=1; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rv=0; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->mcs=0; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->TPC=1; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type, ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc); break; default: ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->type=1; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->ndi=1; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rv=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->mcs=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->TPC=1; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type, ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc); break; } } else { switch(mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->type=1; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type=0; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->ndi=1; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rv=0; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->mcs=0; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->TPC=1; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type, ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc); break; case 25: ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->type=1; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type=0; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->ndi=1; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rv=0; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->mcs=0; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->TPC=1; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_UL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type, ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc); break; case 50: ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->type=1; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type=0; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->ndi=1; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rv=0; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->mcs=0; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->TPC=1; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type, ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc); break; case 100: ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->type=1; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type=0; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->ndi=1; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rv=0; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->mcs=0; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->TPC=1; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->vrb_type, ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0])->rballoc); break; default: break; } } add_common_dci(DCI_pdu, (void*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu1[0], eNB_mac_inst[Mod_id].RA_template[i].RA_rnti, eNB_mac_inst[Mod_id].RA_template[i].RA_dci_size_bytes1, 2, eNB_mac_inst[Mod_id].RA_template[i].RA_dci_size_bits1, eNB_mac_inst[Mod_id].RA_template[i].RA_dci_fmt1, 1); LOG_D(MAC,"[eNB %d] Frame %d: Adding common dci for RA%d (RAR) RA_active %d\n",Mod_id,frame,i, eNB_mac_inst[Mod_id].RA_template[i].RA_active); } if (eNB_mac_inst[Mod_id].RA_template[i].generate_Msg4_dci == 1) { // randomize frequency allocation for RA while (1) { first_rb = (unsigned char)(taus()%(mac_xface->lte_frame_parms->N_RB_DL-4)); if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) break; } vrb_map[first_rb] = 1; vrb_map[first_rb+1] = 1; vrb_map[first_rb+2] = 1; vrb_map[first_rb+3] = 1; if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->type=1; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type=0; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rv=0; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->TPC=1; ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_1_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); break; case 25: ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->type=1; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rv=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->TPC=1; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); break; case 50: ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->type=1; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type=0; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rv=0; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->TPC=1; ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_10MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); break; case 100: ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->type=1; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type=0; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rv=0; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->TPC=1; ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_20MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); break; default: ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->type=1; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rv=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->TPC=1; ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); break; } } else { switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->type=1; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type=0; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rv=0; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->TPC=1; ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_1_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); break; case 25: ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->type=1; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type=0; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rv=0; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->TPC=1; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); break; case 50: ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->type=1; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type=0; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rv=0; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->TPC=1; ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_10MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); break; case 100: ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->type=1; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type=0; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rv=0; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->TPC=1; ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_20MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); break; default: ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->type=1; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type=0; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rv=0; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->TPC=1; ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_DL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); break; } } add_ue_spec_dci(DCI_pdu, (void*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0], eNB_mac_inst[Mod_id].RA_template[i].rnti, eNB_mac_inst[Mod_id].RA_template[i].RA_dci_size_bytes2, 1, eNB_mac_inst[Mod_id].RA_template[i].RA_dci_size_bits2, eNB_mac_inst[Mod_id].RA_template[i].RA_dci_fmt2, 0); LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, subframe %d: Adding ue specific dci (rnti %x) for Msg4\n", Mod_id,frame,subframe,eNB_mac_inst[Mod_id].RA_template[i].rnti); eNB_mac_inst[Mod_id].RA_template[i].generate_Msg4_dci=0; } else if (eNB_mac_inst[Mod_id].RA_template[i].wait_ack_Msg4==1) { // check HARQ status and retransmit if necessary LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, subframe %d: Checking if Msg4 was acknowledged: \n", Mod_id,frame,subframe); // Get candidate harq_pid from PHY mac_xface->get_ue_active_harq_pid(Mod_id,eNB_mac_inst[Mod_id].RA_template[i].rnti,subframe,&harq_pid,&round,0); if (round>0) { // we have to schedule a retransmission if (mac_xface->lte_frame_parms->frame_type == TDD) ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->ndi=0; else ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->ndi=0; // randomize frequency allocation for RA while (1) { first_rb = (unsigned char)(taus()%(mac_xface->lte_frame_parms->N_RB_DL-4)); if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) break; } vrb_map[first_rb] = 1; vrb_map[first_rb+1] = 1; vrb_map[first_rb+2] = 1; vrb_map[first_rb+3] = 1; if (mac_xface->lte_frame_parms->frame_type == TDD) { ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_UL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_5MHz_TDD_1_6_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); } else { ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_UL,first_rb,4); rballoc |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->vrb_type, ((DCI1A_5MHz_FDD_t*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0])->rballoc); } add_ue_spec_dci(DCI_pdu, (void*)&eNB_mac_inst[Mod_id].RA_template[i].RA_alloc_pdu2[0], eNB_mac_inst[Mod_id].RA_template[i].rnti, eNB_mac_inst[Mod_id].RA_template[i].RA_dci_size_bytes2, 2, eNB_mac_inst[Mod_id].RA_template[i].RA_dci_size_bits2, eNB_mac_inst[Mod_id].RA_template[i].RA_dci_fmt2, 0); LOG_W(MAC,"[eNB %d][RAPROC] Frame %d, subframe %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n", Mod_id,frame,subframe,eNB_mac_inst[Mod_id].RA_template[i].rnti); } else { LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, subframe %d : Msg4 acknowledged\n",Mod_id,frame,subframe); eNB_mac_inst[Mod_id].RA_template[i].wait_ack_Msg4=0; eNB_mac_inst[Mod_id].RA_template[i].RA_active=0; } } } } // RA is scheduled in this subframe // UE specific DCIs for (UE_id=0;UE_id status %d\n",UE_id,eNB_dlsch_info[Mod_id][UE_id].status); if (eNB_dlsch_info[Mod_id][UE_id].status == S_DL_SCHEDULED) { // clear scheduling flag eNB_dlsch_info[Mod_id][UE_id].status = S_DL_WAITING; rnti = find_UE_RNTI(Mod_id,UE_id); mac_xface->get_ue_active_harq_pid(Mod_id,rnti,subframe,&harq_pid,&round,0); nb_rb = eNB_mac_inst[Mod_id].UE_template[UE_id].nb_rb[harq_pid]; DLSCH_dci = (void *)eNB_mac_inst[Mod_id].UE_template[UE_id].DLSCH_DCI[harq_pid]; /// Synchronizing rballoc with rballoc_sub for(i=0;ilte_frame_parms->N_RBGS;i++){ rballoc_sub[i] = eNB_mac_inst[Mod_id].UE_template[UE_id].rballoc_subband[harq_pid][i]; if(rballoc_sub[i] == 1) rballoc |= (0x0001<get_transmission_mode(Mod_id,rnti)) { default: case 1: case 2: LOG_D(MAC,"[USER-PLANE DEFAULT DRB] Adding UE spec DCI for %d PRBS (%x) => ",nb_rb,rballoc); if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->rah = 0; size_bytes = sizeof(DCI1_1_5MHz_TDD_t); size_bits = sizeof_DCI1_1_5MHz_TDD_t; break; case 25: ((DCI1_5MHz_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_5MHz_TDD_t*)DLSCH_dci)->rah = 0; size_bytes = sizeof(DCI1_5MHz_TDD_t); size_bits = sizeof_DCI1_5MHz_TDD_t; break; case 50: ((DCI1_10MHz_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_10MHz_TDD_t*)DLSCH_dci)->rah = 0; size_bytes = sizeof(DCI1_10MHz_TDD_t); size_bits = sizeof_DCI1_10MHz_TDD_t; break; case 100: ((DCI1_20MHz_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_20MHz_TDD_t*)DLSCH_dci)->rah = 0; size_bytes = sizeof(DCI1_20MHz_TDD_t); size_bits = sizeof_DCI1_20MHz_TDD_t; break; default: ((DCI1_5MHz_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_5MHz_TDD_t*)DLSCH_dci)->rah = 0; size_bytes = sizeof(DCI1_5MHz_TDD_t); size_bits = sizeof_DCI1_5MHz_TDD_t; break; } } else { switch(mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->rah = 0; size_bytes=sizeof(DCI1_1_5MHz_FDD_t); size_bits=sizeof_DCI1_1_5MHz_FDD_t; break; case 25: ((DCI1_5MHz_FDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_5MHz_FDD_t*)DLSCH_dci)->rah = 0; size_bytes=sizeof(DCI1_5MHz_FDD_t); size_bits=sizeof_DCI1_5MHz_FDD_t; break; case 50: ((DCI1_10MHz_FDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_10MHz_FDD_t*)DLSCH_dci)->rah = 0; size_bytes=sizeof(DCI1_10MHz_FDD_t); size_bits=sizeof_DCI1_10MHz_FDD_t; break; case 100: ((DCI1_20MHz_FDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_20MHz_FDD_t*)DLSCH_dci)->rah = 0; size_bytes=sizeof(DCI1_20MHz_FDD_t); size_bits=sizeof_DCI1_20MHz_FDD_t; break; default: ((DCI1_5MHz_FDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_5MHz_FDD_t*)DLSCH_dci)->rah = 0; size_bytes=sizeof(DCI1_5MHz_FDD_t); size_bits=sizeof_DCI1_5MHz_FDD_t; break; } } add_ue_spec_dci(DCI_pdu, DLSCH_dci, rnti, size_bytes, process_ue_cqi (Mod_id,UE_id),//aggregation, size_bits, format1, 0); break; case 4: //if (nb_rb>10) { // DCI format 2_2A_M10PRB can also be used for less than 10 PRB (it refers to the system bandwidth) ((DCI2_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI2_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rah = 0; add_ue_spec_dci(DCI_pdu, DLSCH_dci, rnti, sizeof(DCI2_5MHz_2A_M10PRB_TDD_t), process_ue_cqi (Mod_id,UE_id),//aggregation, sizeof_DCI2_5MHz_2A_M10PRB_TDD_t, format2_2A_M10PRB, 0); /*} else { ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); add_ue_spec_dci(DCI_pdu, DLSCH_dci, rnti, sizeof(DCI2_5MHz_2A_L10PRB_TDD_t), 2,//aggregation, sizeof_DCI2_5MHz_2A_L10PRB_TDD_t, format2_2A_L10PRB); }*/ break; case 5: ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rah = 0; add_ue_spec_dci(DCI_pdu, DLSCH_dci, rnti, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), process_ue_cqi (Mod_id,UE_id),//aggregation, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, format1E_2A_M10PRB, 0); break; case 6: ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rah = 0; add_ue_spec_dci(DCI_pdu, DLSCH_dci, rnti, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), process_ue_cqi (Mod_id,UE_id),//aggregation sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, format1E_2A_M10PRB, 0); break; } } } } void update_ul_dci(u8 Mod_id,u16 rnti,u8 dai) { DCI_PDU *DCI_pdu= &eNB_mac_inst[Mod_id].DCI_pdu; int i; DCI0_5MHz_TDD_1_6_t *ULSCH_dci; if (mac_xface->lte_frame_parms->frame_type == TDD) { for (i=0;iNum_common_dci+DCI_pdu->Num_ue_spec_dci;i++) { ULSCH_dci = (DCI0_5MHz_TDD_1_6_t *)DCI_pdu->dci_alloc[i].dci_pdu; if ((DCI_pdu->dci_alloc[i].format == format0) && (DCI_pdu->dci_alloc[i].rnti == rnti)) ULSCH_dci->dai = (dai-1)&3; } } // printf("Update UL DCI: DAI %d\n",dai); } void schedule_ue_spec(unsigned char Mod_id, u32 frame, unsigned char subframe, u16 nb_rb_used0, unsigned int *nCCE_used, int mbsfn_flag) { unsigned char UE_id; unsigned char next_ue; unsigned char granted_UEs; u16 nCCE; unsigned char aggregation; mac_rlc_status_resp_t rlc_status; unsigned char header_len_dcch=0, header_len_dcch_tmp=0,header_len_dtch=0,header_len_dtch_tmp=0, ta_len=0; unsigned char sdu_lcids[11],offset,num_sdus=0; u16 nb_rb,nb_rb_temp,nb_available_rb,TBS,j,sdu_lengths[11],rnti,padding=0,post_padding=0; unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; unsigned char round=0; unsigned char harq_pid=0; void *DLSCH_dci; LTE_eNB_UE_stats* eNB_UE_stats; u16 sdu_length_total=0; // unsigned char loop_count; unsigned char DAI; u16 i=0; u8 dl_pow_off[NUMBER_OF_UE_MAX]; unsigned char rballoc_sub_UE[NUMBER_OF_UE_MAX][N_RBGS_MAX]; // unsigned char rballoc_sub[N_RBGS_MAX]; u16 pre_nb_available_rbs[NUMBER_OF_UE_MAX]; int mcs; //u8 number_of_subbands=13; u16 min_rb_unit; switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: min_rb_unit=1; break; case 25: min_rb_unit=2; break; case 50: min_rb_unit=3; break; case 100: min_rb_unit=4; break; default: min_rb_unit=2; break; } if (mbsfn_flag>0) return; //int **rballoc_sub = (int **)malloc(1792*sizeof(int *)); granted_UEs = find_dlgranted_UEs(Mod_id); //weight = get_ue_weight(Mod_id,UE_id); aggregation = 1; // set to the maximum aggregation level /// Initialization for pre-processor for(i=0;ilte_frame_parms->N_RBGS;j++){ // rballoc_sub[j] = 0; rballoc_sub_UE[i][j] = 0; } } for (i = 0; i < NUMBER_OF_UE_MAX; i++) { PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[i].pre_nb_available_rbs = 0; for (j = 0; j < mac_xface->lte_frame_parms->N_RBGS; j++) { PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[i].rballoc_sub[j] = 0; } } // set current available nb_rb and nCCE to maximum nb_available_rb = mac_xface->lte_frame_parms->N_RB_DL - nb_rb_used0; nCCE = mac_xface->get_nCCE_max(Mod_id) - *nCCE_used; // store the goloabl enb stats eNB_mac_inst[Mod_id].eNB_stats.num_dlactive_UEs = granted_UEs; eNB_mac_inst[Mod_id].eNB_stats.available_prbs = nb_available_rb; eNB_mac_inst[Mod_id].eNB_stats.total_available_prbs += nb_available_rb; eNB_mac_inst[Mod_id].eNB_stats.available_ncces = nCCE; eNB_mac_inst[Mod_id].eNB_stats.dlsch_bytes_tx=0; eNB_mac_inst[Mod_id].eNB_stats.dlsch_pdus_tx=0; /// CALLING Pre_Processor for downlink scheduling (Returns estimation of RBs required by each UE and the allocation on sub-band) dlsch_scheduler_pre_processor(Mod_id, frame, subframe, dl_pow_off, pre_nb_available_rbs, mac_xface->lte_frame_parms->N_RBGS, rballoc_sub_UE); for (UE_id=0;UE_idmacphy_exit("");//continue; } eNB_UE_stats = mac_xface->get_eNB_UE_stats(Mod_id,rnti); if (eNB_UE_stats==NULL) mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n"); // Get candidate harq_pid from PHY mac_xface->get_ue_active_harq_pid(Mod_id,rnti,subframe,&harq_pid,&round,0); // printf("Got harq_pid %d, round %d\n",harq_pid,round); nb_available_rb = pre_nb_available_rbs[UE_id]; if ((nb_available_rb == 0) || (nCCE < (1<get_transmission_mode(Mod_id,rnti)==5) continue; //to next user (there might be rbs availiable for other UEs in TM5 // else // break; } sdu_length_total=0; num_sdus=0; // get Round-Robin allocation next_ue = UE_id;//schedule_next_dlue(Mod_id,subframe); // next scheduled user // If nobody is left, exit while loop and go to next step if (next_ue == 255) break; if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->tdd_config) { case 0: if ((subframe==0)||(subframe==1)||(subframe==3)||(subframe==5)||(subframe==6)||(subframe==8)) eNB_mac_inst[Mod_id].UE_template[next_ue].DAI = 0; case 1: if ((subframe==0)||(subframe==4)||(subframe==5)||(subframe==9)) eNB_mac_inst[Mod_id].UE_template[next_ue].DAI = 0; break; case 2: if ((subframe==4)||(subframe==5)) eNB_mac_inst[Mod_id].UE_template[next_ue].DAI = 0; break; case 3: if ((subframe==5)||(subframe==7)||(subframe==9)) eNB_mac_inst[Mod_id].UE_template[next_ue].DAI = 0; break; case 4: if ((subframe==0)||(subframe==6)) eNB_mac_inst[Mod_id].UE_template[next_ue].DAI = 0; break; case 5: if (subframe==9) eNB_mac_inst[Mod_id].UE_template[next_ue].DAI = 0; break; case 6: if ((subframe==0)||(subframe==1)||(subframe==5)||(subframe==6)||(subframe==9)) eNB_mac_inst[Mod_id].UE_template[next_ue].DAI = 0; default: break; } } // This is an allocated UE_id rnti = find_UE_RNTI(Mod_id,next_ue); if (rnti==0) continue; eNB_UE_stats = mac_xface->get_eNB_UE_stats(Mod_id,rnti); if (eNB_UE_stats==NULL) mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n"); //eNB_UE_stats->dlsch_mcs1 = openair_daq_vars.target_ue_dl_mcs; // int flag_LA=0; //printf("CQI %d\n",eNB_UE_stats->DL_cqi[0]); eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->DL_cqi[0]]; if(eNB_UE_stats->dlsch_mcs1>22) eNB_UE_stats->dlsch_mcs1=22; // for TM5, limit the MCS to 16QAM // for EXMIMO, limit the MCS to 16QAM as well #ifdef EXMIMO eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1,16); #endif // Get candidate harq_pid from PHY mac_xface->get_ue_active_harq_pid(Mod_id,rnti,subframe,&harq_pid,&round,0); eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].harq_pid = harq_pid; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].harq_round = round; // Note this code is for a specific DCI format DLSCH_dci = (void *)eNB_mac_inst[Mod_id].UE_template[next_ue].DLSCH_DCI[harq_pid]; for(j=0;jlte_frame_parms->N_RBGS;j++){ // initializing the rb allocation indicator for each UE eNB_mac_inst[Mod_id].UE_template[next_ue].rballoc_subband[harq_pid][j] = 0; } // store stats eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].dl_cqi= eNB_UE_stats->DL_cqi[0]; if (round > 0) { if (mac_xface->lte_frame_parms->frame_type == TDD) { eNB_mac_inst[Mod_id].UE_template[next_ue].DAI++; LOG_D(MAC,"DAI update: subframe %d: UE %d, DAI %d\n",subframe,next_ue,eNB_mac_inst[Mod_id].UE_template[next_ue].DAI); update_ul_dci(Mod_id,rnti,eNB_mac_inst[Mod_id].UE_template[next_ue].DAI); } // get freq_allocation nb_rb = eNB_mac_inst[Mod_id].UE_template[next_ue].nb_rb[harq_pid]; if (nb_rb <= nb_available_rb) { if(nb_rb == pre_nb_available_rbs[next_ue]){ for(j=0;jlte_frame_parms->N_RBGS;j++) // for indicating the rballoc for each sub-band eNB_mac_inst[Mod_id].UE_template[next_ue].rballoc_subband[harq_pid][j] = rballoc_sub_UE[next_ue][j];} else { nb_rb_temp = nb_rb; j = 0; while((nb_rb_temp > 0) && (jlte_frame_parms->N_RBGS)){ if(rballoc_sub_UE[next_ue][j] == 1){ eNB_mac_inst[Mod_id].UE_template[next_ue].rballoc_subband[harq_pid][j] = rballoc_sub_UE[next_ue][j]; if((j == mac_xface->lte_frame_parms->N_RBGS-1) && ((mac_xface->lte_frame_parms->N_RB_DL == 25)|| (mac_xface->lte_frame_parms->N_RB_DL == 50))) nb_rb_temp = nb_rb_temp - min_rb_unit+1; else nb_rb_temp = nb_rb_temp - min_rb_unit; } j = j+1; } } nb_available_rb -= nb_rb; aggregation = process_ue_cqi(Mod_id,next_ue); nCCE-=(1<mu_mimo_mode[next_ue].pre_nb_available_rbs = nb_rb; PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[next_ue].dl_pow_off = dl_pow_off[next_ue]; for(j=0;jlte_frame_parms->N_RBGS;j++) PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[next_ue].rballoc_sub[j] = eNB_mac_inst[Mod_id].UE_template[next_ue].rballoc_subband[harq_pid][j]; switch (mac_xface->get_transmission_mode(Mod_id,rnti)) { case 1: case 2: default: switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: if (mac_xface->lte_frame_parms->frame_type == TDD) { ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->ndi = 0; ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->rv = round&3; ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; LOG_D(MAC,"[eNB %d] Retransmission : harq_pid %d, round %d, dai %d, mcs %d\n",Mod_id,harq_pid,round,(eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1),((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->mcs); } else { ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->ndi = 0; ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->rv = round&3; LOG_D(MAC,"[eNB %d] Retransmission : harq_pid %d, round %d, mcs %d\n",Mod_id,harq_pid,round,((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->mcs); } break; case 25: if (mac_xface->lte_frame_parms->frame_type == TDD) { ((DCI1_5MHz_TDD_t*)DLSCH_dci)->ndi = 0; ((DCI1_5MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_5MHz_TDD_t*)DLSCH_dci)->rv = round&3; ((DCI1_5MHz_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; LOG_D(MAC,"[eNB %d] Retransmission : harq_pid %d, round %d, dai %d, mcs %d\n",Mod_id,harq_pid,round,(eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1),((DCI1_5MHz_TDD_t*)DLSCH_dci)->mcs); } else { ((DCI1_5MHz_FDD_t*)DLSCH_dci)->ndi = 0; ((DCI1_5MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_5MHz_FDD_t*)DLSCH_dci)->rv = round&3; LOG_D(MAC,"[eNB %d] Retransmission : harq_pid %d, round %d, mcs %d\n",Mod_id,harq_pid,round,((DCI1_5MHz_FDD_t*)DLSCH_dci)->mcs); } break; case 50: if (mac_xface->lte_frame_parms->frame_type == TDD) { ((DCI1_10MHz_TDD_t*)DLSCH_dci)->ndi = 0; ((DCI1_10MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_10MHz_TDD_t*)DLSCH_dci)->rv = round&3; ((DCI1_10MHz_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; LOG_D(MAC,"[eNB %d] Retransmission : harq_pid %d, round %d, dai %d, mcs %d\n",Mod_id,harq_pid,round,(eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1),((DCI1_10MHz_TDD_t*)DLSCH_dci)->mcs); } else { ((DCI1_10MHz_FDD_t*)DLSCH_dci)->ndi = 0; ((DCI1_10MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_10MHz_FDD_t*)DLSCH_dci)->rv = round&3; LOG_D(MAC,"[eNB %d] Retransmission : harq_pid %d, round %d, mcs %d\n",Mod_id,harq_pid,round,((DCI1_10MHz_FDD_t*)DLSCH_dci)->mcs); } break; case 100: if (mac_xface->lte_frame_parms->frame_type == TDD) { ((DCI1_20MHz_TDD_t*)DLSCH_dci)->ndi = 0; ((DCI1_20MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_20MHz_TDD_t*)DLSCH_dci)->rv = round&3; ((DCI1_20MHz_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; LOG_D(MAC,"[eNB %d] Retransmission : harq_pid %d, round %d, dai %d, mcs %d\n",Mod_id,harq_pid,round,(eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1),((DCI1_20MHz_TDD_t*)DLSCH_dci)->mcs); } else { ((DCI1_20MHz_FDD_t*)DLSCH_dci)->ndi = 0; ((DCI1_20MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_20MHz_FDD_t*)DLSCH_dci)->rv = round&3; LOG_D(MAC,"[eNB %d] Retransmission : harq_pid %d, round %d, mcs %d\n",Mod_id,harq_pid,round,((DCI1_20MHz_FDD_t*)DLSCH_dci)->mcs); } break; } break; case 4: // if (nb_rb>10) { ((DCI2_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->ndi1 = 0; ((DCI2_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI2_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; // } //else { // ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->ndi1 = 0; // ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; // ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->rv1 = round&3; // ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; // } break; case 5: // if(nb_rb>10){ //((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->mcs = eNB_UE_stats->DL_cqi[0]<<1; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->ndi = 0; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rv = round&3; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; if(dl_pow_off[next_ue] == 2) dl_pow_off[next_ue] = 1; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dl_power_off = dl_pow_off[next_ue]; // } break; case 6: ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->ndi = 0; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rv = round&3; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dl_power_off = 1;//dl_pow_off[next_ue]; break; } add_ue_dlsch_info(Mod_id, next_ue, subframe, S_DL_SCHEDULED); //eNB_UE_stats->dlsch_trials[round]++; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].num_retransmission+=1; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].rbs_used_retx=nb_rb; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].total_rbs_used_retx+=nb_rb; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].ncce_used_retx=nCCE; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].dlsch_mcs2=eNB_UE_stats->dlsch_mcs1; } else { // don't schedule this UE, its retransmission takes more resources than we have } } else { // This is a potentially new SDU opportunity // calculate mcs rlc_status.bytes_in_buffer = 0; // Now check RLC information to compute number of required RBs // get maximum TBS size for RLC request //TBS = mac_xface->get_TBS(eNB_UE_stats->DL_cqi[0]<<1,nb_available_rb); TBS = mac_xface->get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_available_rb); // check first for RLC data on DCCH // add the length for all the control elements (timing adv, drx, etc) : header + payload ta_len = ((eNB_UE_stats->timing_advance_update/4)!=0) ? 2 : 0; header_len_dcch = 2; // 2 bytes DCCH SDU subheader rlc_status = mac_rlc_status_ind(Mod_id,frame,1,RLC_MBMS_NO, DCCH+(NB_RB_MAX*next_ue), (TBS-ta_len-header_len_dcch)); // transport block set size sdu_lengths[0]=0; if (rlc_status.bytes_in_buffer > 0) { // There is DCCH to transmit LOG_D(MAC,"[eNB %d] Frame %d, DL-DCCH->DLSCH, Requesting %d bytes from RLC (RRC message)\n",Mod_id,frame,TBS-header_len_dcch); sdu_lengths[0] += mac_rlc_data_req(Mod_id,frame,RLC_MBMS_NO, DCCH+(NB_RB_MAX*next_ue), (char *)&dlsch_buffer[sdu_lengths[0]]); LOG_D(MAC,"[eNB %d][DCCH] Got %d bytes from RLC\n",Mod_id,sdu_lengths[0]); sdu_length_total = sdu_lengths[0]; sdu_lcids[0] = DCCH; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].num_pdu_tx[DCCH]+=1; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].num_bytes_tx[DCCH]+=sdu_lengths[0]; num_sdus = 1; #ifdef DEBUG_eNB_SCHEDULER LOG_T(MAC,"[eNB %d][DCCH] Got %d bytes :",Mod_id,sdu_lengths[0]); for (j=0;j 0) { LOG_D(MAC,"[eNB %d], Frame %d, DCCH1->DLSCH, Requesting %d bytes from RLC (RRC message)\n", Mod_id,frame,TBS-header_len_dcch-sdu_length_total); sdu_lengths[num_sdus] += mac_rlc_data_req(Mod_id,frame,RLC_MBMS_NO, DCCH+1+(NB_RB_MAX*next_ue), (char *)&dlsch_buffer[sdu_lengths[0]]); sdu_lcids[num_sdus] = DCCH1; sdu_length_total += sdu_lengths[num_sdus]; header_len_dcch += 2; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].num_pdu_tx[DCCH1]+=1; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].num_bytes_tx[DCCH1]+=sdu_lengths[num_sdus]; num_sdus++; LOG_D(MAC,"[eNB %d] Got %d bytes for DCCH from RLC\n",Mod_id,sdu_lengths[0]); } // check for DTCH and update header information // here we should loop over all possible DTCH header_len_dtch = 3; // 3 bytes DTCH SDU subheader LOG_D(MAC,"[eNB %d], Frame %d, DTCH->DLSCH, Checking RLC status (rab %d, tbs %d, len %d)\n", Mod_id,frame,DTCH+(NB_RB_MAX*next_ue),TBS, TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch); rlc_status = mac_rlc_status_ind(Mod_id,frame,1,RLC_MBMS_NO, DTCH+(NB_RB_MAX*next_ue), TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch); if (rlc_status.bytes_in_buffer > 0) { LOG_I(MAC,"[eNB %d][USER-PLANE DEFAULT DRB], Frame %d, DTCH->DLSCH, Requesting %d bytes from RLC (hdr len dtch %d)\n", Mod_id,frame,TBS-header_len_dcch-sdu_length_total-header_len_dtch,header_len_dtch); sdu_lengths[num_sdus] = mac_rlc_data_req(Mod_id,frame,RLC_MBMS_NO, DTCH+(NB_RB_MAX*next_ue), (char*)&dlsch_buffer[sdu_length_total]); LOG_I(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n",Mod_id,sdu_lengths[num_sdus],DTCH+(NB_RB_MAX*next_ue)); sdu_lcids[num_sdus] = DTCH; sdu_length_total += sdu_lengths[num_sdus]; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].num_pdu_tx[DTCH]+=1; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].num_bytes_tx[DTCH]+=sdu_lengths[num_sdus]; if (sdu_lengths[num_sdus] < 128) header_len_dtch=2; num_sdus++; } else { header_len_dtch = 0; } // there is a payload if (((sdu_length_total + header_len_dcch + header_len_dtch )> 0)) { // Now compute number of required RBs for total sdu length // Assume RAH format 2 // adjust header lengths header_len_dcch_tmp = header_len_dcch; header_len_dtch_tmp = header_len_dtch; if (header_len_dtch==0) header_len_dcch = (header_len_dcch >0) ? 1 : header_len_dcch; // remove length field else header_len_dtch = (header_len_dtch > 0) ? 1 :header_len_dtch; // remove length field for the last SDU mcs = eNB_UE_stats->dlsch_mcs1; if (mcs==0) nb_rb = 4; // don't let the TBS get too small else nb_rb=min_rb_unit; TBS = mac_xface->get_TBS_DL(mcs,nb_rb); while (TBS < (sdu_length_total + header_len_dcch + header_len_dtch + ta_len)) { nb_rb += min_rb_unit; // if (nb_rb>nb_available_rb) { // if we've gone beyond the maximum number of RBs // (can happen if N_RB_DL is odd) TBS = mac_xface->get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_available_rb); nb_rb = nb_available_rb; break; } TBS = mac_xface->get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rb); } if(nb_rb == pre_nb_available_rbs[next_ue]) for(j=0;jlte_frame_parms->N_RBGS;j++) // for indicating the rballoc for each sub-band eNB_mac_inst[Mod_id].UE_template[next_ue].rballoc_subband[harq_pid][j] = rballoc_sub_UE[next_ue][j]; else { nb_rb_temp = nb_rb; j = 0; while((nb_rb_temp > 0) && (jlte_frame_parms->N_RBGS)){ if(rballoc_sub_UE[next_ue][j] == 1){ eNB_mac_inst[Mod_id].UE_template[next_ue].rballoc_subband[harq_pid][j] = rballoc_sub_UE[next_ue][j]; if ((j == mac_xface->lte_frame_parms->N_RBGS-1) && ((mac_xface->lte_frame_parms->N_RB_DL == 25)|| (mac_xface->lte_frame_parms->N_RB_DL == 50))) nb_rb_temp = nb_rb_temp - min_rb_unit+1; else nb_rb_temp = nb_rb_temp - min_rb_unit; } j = j+1; } } PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[next_ue].pre_nb_available_rbs = nb_rb; PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[next_ue].dl_pow_off = dl_pow_off[next_ue]; for(j=0;jlte_frame_parms->N_RBGS;j++) PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[next_ue].rballoc_sub[j] = eNB_mac_inst[Mod_id].UE_template[next_ue].rballoc_subband[harq_pid][j]; // decrease mcs until TBS falls below required length while ((TBS > (sdu_length_total + header_len_dcch + header_len_dtch + ta_len)) && (mcs>0)) { mcs--; TBS = mac_xface->get_TBS_DL(mcs,nb_rb); } // if we have decreased too much or we don't have enough RBs, increase MCS while ((TBS < (sdu_length_total + header_len_dcch + header_len_dtch + ta_len)) && ((( dl_pow_off[next_ue]>0) && (mcs<28)) || ( (dl_pow_off[next_ue]==0) && (mcs<=15)))) { mcs++; TBS = mac_xface->get_TBS_DL(mcs,nb_rb); } LOG_D(MAC,"dlsch_mcs before and after the rate matching = (%d, %d)\n",eNB_UE_stats->dlsch_mcs1, mcs); #ifdef DEBUG_eNB_SCHEDULER LOG_D(MAC,"[eNB %d] Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)\n", Mod_id,mcs,TBS,nb_rb); // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n", // TBS, sdu_length_total, offset, TBS-sdu_length_total-offset); #endif if ((TBS - header_len_dcch - header_len_dtch - sdu_length_total - ta_len) <= 2) { padding = (TBS - header_len_dcch - header_len_dtch - sdu_length_total - ta_len); post_padding = 0; } else { padding = 0; // adjust the header len if (header_len_dtch==0) header_len_dcch = header_len_dcch_tmp; else //if (( header_len_dcch==0)&&((header_len_dtch==1)||(header_len_dtch==2))) header_len_dtch = header_len_dtch_tmp; post_padding = TBS - sdu_length_total - header_len_dcch - header_len_dtch - ta_len ; // 1 is for the postpadding header } offset = generate_dlsch_header((unsigned char*)eNB_mac_inst[Mod_id].DLSCH_pdu[(unsigned char)next_ue][0].payload[0], // offset = generate_dlsch_header((unsigned char*)eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0], num_sdus, //num_sdus sdu_lengths, // sdu_lcids, 255, // no drx eNB_UE_stats->timing_advance_update/4, // timing advance NULL, // contention res id padding, post_padding); //#ifdef DEBUG_eNB_SCHEDULER LOG_I(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] Generate header : sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, next_ue %d,padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_dcch %d, header_dtch %d\n", Mod_id,sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],offset, ta_len,next_ue,padding,post_padding,mcs,TBS,nb_rb,header_len_dcch,header_len_dtch); //#endif LOG_T(MAC,"[eNB %d] First 16 bytes of DLSCH : \n"); for (i=0;i<16;i++) LOG_T(MAC,"%x.",dlsch_buffer[i]); LOG_T(MAC,"\n"); // cycle through SDUs and place in dlsch_buffer memcpy(&eNB_mac_inst[Mod_id].DLSCH_pdu[(unsigned char)next_ue][0].payload[0][offset],dlsch_buffer,sdu_length_total); // memcpy(&eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]); // fill remainder of DLSCH with random data for (j=0;j<(TBS-sdu_length_total-offset);j++) eNB_mac_inst[Mod_id].DLSCH_pdu[(unsigned char)next_ue][0].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff); //eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset+sdu_lengths[0]+j] = (char)(taus()&0xff); #if defined(USER_MODE) && defined(OAI_EMU) /* Tracing of PDU is done on UE side */ if (oai_emulation.info.opt_enabled) trace_pdu(1, (uint8_t *)eNB_mac_inst[Mod_id].DLSCH_pdu[(unsigned char)next_ue][0].payload[0], TBS, Mod_id, 3, find_UE_RNTI(Mod_id,next_ue), eNB_mac_inst[Mod_id].subframe,0,0); LOG_D(OPT,"[eNB %d][DLSCH] Frame %d rnti %x with size %d\n", Mod_id, frame, find_UE_RNTI(Mod_id,next_ue), TBS); #endif aggregation = process_ue_cqi(Mod_id,next_ue); nCCE-=(1<dlsch_mcs1; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].dlsch_mcs2=mcs; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].TBS = TBS; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].overhead_bytes= TBS- sdu_length_total; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].total_sdu_bytes+= sdu_length_total; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].total_pdu_bytes+= TBS; eNB_mac_inst[Mod_id].eNB_UE_stats[next_ue].total_num_pdus+=1; if (mac_xface->lte_frame_parms->frame_type == TDD) { eNB_mac_inst[Mod_id].UE_template[next_ue].DAI++; // printf("DAI update: subframe %d: UE %d, DAI %d\n",subframe,next_ue,eNB_mac_inst[Mod_id].UE_template[next_ue].DAI); update_ul_dci(Mod_id,rnti,eNB_mac_inst[Mod_id].UE_template[next_ue].DAI); } switch (mac_xface->get_transmission_mode(Mod_id,rnti)) { case 1: case 2: default: if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->ndi = 1; ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->rv = 0; ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; break; case 25: ((DCI1_5MHz_TDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1_5MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_5MHz_TDD_t*)DLSCH_dci)->ndi = 1; ((DCI1_5MHz_TDD_t*)DLSCH_dci)->rv = 0; ((DCI1_5MHz_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; break; case 50: ((DCI1_10MHz_TDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1_10MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_10MHz_TDD_t*)DLSCH_dci)->ndi = 1; ((DCI1_10MHz_TDD_t*)DLSCH_dci)->rv = 0; ((DCI1_10MHz_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; break; case 100: ((DCI1_20MHz_TDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1_20MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_20MHz_TDD_t*)DLSCH_dci)->ndi = 1; ((DCI1_20MHz_TDD_t*)DLSCH_dci)->rv = 0; ((DCI1_20MHz_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; break; default: ((DCI1_5MHz_TDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1_5MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_5MHz_TDD_t*)DLSCH_dci)->ndi = 1; ((DCI1_5MHz_TDD_t*)DLSCH_dci)->rv = 0; ((DCI1_5MHz_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; break; } } else { switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->ndi = 1; ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->rv = 0; break; case 25: ((DCI1_5MHz_FDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1_5MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_5MHz_FDD_t*)DLSCH_dci)->ndi = 1; ((DCI1_5MHz_FDD_t*)DLSCH_dci)->rv = 0; break; case 50: ((DCI1_10MHz_FDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1_10MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_10MHz_FDD_t*)DLSCH_dci)->ndi = 1; ((DCI1_10MHz_FDD_t*)DLSCH_dci)->rv = 0; break; case 100: ((DCI1_20MHz_FDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1_20MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_20MHz_FDD_t*)DLSCH_dci)->ndi = 1; ((DCI1_20MHz_FDD_t*)DLSCH_dci)->rv = 0; break; default: ((DCI1_5MHz_FDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1_5MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1_5MHz_FDD_t*)DLSCH_dci)->ndi = 1; ((DCI1_5MHz_FDD_t*)DLSCH_dci)->rv = 0; break; } } break; case 4: // if (nb_rb>10) { ((DCI2_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->mcs1 = mcs; ((DCI2_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI2_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->ndi1 = 1; ((DCI2_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rv1 = round&3; ((DCI2_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; //} /* else { ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->mcs1 = eNB_UE_stats->DL_cqi[0]; ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->ndi1 = 1; ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->rv1 = round&3; ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->tpmi = 5; ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; }*/ break; case 5: ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->ndi = 1; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rv = round&3; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; if(dl_pow_off[next_ue] == 2) dl_pow_off[next_ue] = 1; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dl_power_off = dl_pow_off[next_ue]; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->tpmi = 5; break; case 6: ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->mcs = mcs; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->ndi = 1; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rv = round&3; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dai = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dl_power_off = 1; ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->tpmi = 5; break; } } else { // There is no data from RLC or MAC header, so don't schedule } } if (mac_xface->lte_frame_parms->frame_type == TDD) { DAI = (eNB_mac_inst[Mod_id].UE_template[next_ue].DAI-1)&3; LOG_D(MAC,"[eNB %d] Frame %d: DAI %d for UE %d\n",Mod_id,frame,DAI,next_ue); // Save DAI for Format 0 DCI switch (mac_xface->lte_frame_parms->tdd_config) { case 0: // if ((subframe==0)||(subframe==1)||(subframe==5)||(subframe==6)) break; case 1: switch (subframe) { case 1: eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul[7] = DAI; break; case 4: eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul[8] = DAI; break; case 6: eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul[2] = DAI; break; case 9: eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul[3] = DAI; break; } case 2: // if ((subframe==3)||(subframe==8)) // eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul = DAI; break; case 3: if ((subframe==6)||(subframe==8)||(subframe==0)) { LOG_D(MAC,"schedule_ue_spec: setting UL DAI to %d for subframe %d => %d\n",DAI,subframe, ((subframe+8)%10)>>1); eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul[((subframe+8)%10)>>1] = DAI; } break; case 4: // if ((subframe==8)||(subframe==9)) // eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul = DAI; break; case 5: // if (subframe==8) // eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul = DAI; break; case 6: // if ((subframe==1)||(subframe==4)||(subframe==6)||(subframe==9)) // eNB_mac_inst[Mod_id].UE_template[next_ue].DAI_ul = DAI; break; default: break; } } //printf("MAC nCCE : %d\n",*nCCE_used); } } void eNB_dlsch_ulsch_scheduler(u8 Mod_id,u8 cooperation_flag, u32 frame, u8 subframe) {//, int calibration_flag) { unsigned char nprb=0; unsigned int nCCE=0; int mbsfn_status=0; u32 RBalloc=0; #ifdef EXMIMO int ret; #endif #if defined(ENABLE_ITTI) MessageDef *msg_p; const char *msg_name; instance_t instance; #endif DCI_PDU *DCI_pdu= &eNB_mac_inst[Mod_id].DCI_pdu; // LOG_D(MAC,"[eNB %d] Frame %d, Subframe %d, entering MAC scheduler\n",Mod_id, frame, subframe); vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,1); #if defined(ENABLE_ITTI) do { // Checks if a message has been sent to MAC sub-task itti_poll_msg (TASK_MAC_ENB, &msg_p); if (msg_p != NULL) { msg_name = ITTI_MSG_NAME (msg_p); instance = ITTI_MSG_INSTANCE (msg_p); switch (ITTI_MSG_ID(msg_p)) { case RRC_MAC_BCCH_DATA_REQ: LOG_D(MAC, "Received %s from %s: instance %d, frame %d, eNB_index %d\n", msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance, RRC_MAC_BCCH_DATA_REQ (msg_p).frame, RRC_MAC_BCCH_DATA_REQ (msg_p).enb_index); // TODO process BCCH data req. break; case RRC_MAC_CCCH_DATA_REQ: LOG_D(MAC, "Received %s from %s: instance %d, frame %d, eNB_index %d\n", msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance, RRC_MAC_CCCH_DATA_REQ (msg_p).frame, RRC_MAC_CCCH_DATA_REQ (msg_p).enb_index); // TODO process CCCH data req. break; #ifdef Rel10 case RRC_MAC_MCCH_DATA_REQ: LOG_D(MAC, "Received %s from %s: instance %d, frame %d, eNB_index %d, mbsfn_sync_area %d\n", msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance, RRC_MAC_MCCH_DATA_REQ (msg_p).frame, RRC_MAC_MCCH_DATA_REQ (msg_p).enb_index, RRC_MAC_MCCH_DATA_REQ (msg_p).mbsfn_sync_area); // TODO process MCCH data req. break; #endif default: LOG_E(MAC, "Received unexpected message %s\n", msg_name); break; } free (msg_p); } } while(msg_p != NULL); #endif // clear DCI and BCCH contents before scheduling DCI_pdu->Num_common_dci = 0; DCI_pdu->Num_ue_spec_dci = 0; eNB_mac_inst[Mod_id].bcch_active = 0; #ifdef Rel10 eNB_mac_inst[Mod_id].mcch_active =0; #endif eNB_mac_inst[Mod_id].frame = frame; eNB_mac_inst[Mod_id].subframe = subframe; //if (subframe%5 == 0) #ifdef EXMIMO //pdcp_run(frame, 1, 0, Mod_id); ret = pthread_mutex_trylock (&pdcp_mutex); if (ret != 0) { if (ret==EBUSY) LOG_E(PDCP,"Mutex busy\n"); else LOG_E(PDCP,"Cannot lock mutex\n"); //return(-1); } else { pdcp_instance_cnt++; pthread_mutex_unlock(&pdcp_mutex); if (pdcp_instance_cnt == 0) { if (pthread_cond_signal(&pdcp_cond) != 0) { LOG_E(PDCP,"pthread_cond_signal unsuccessfull\n"); //return(-1); } } else { LOG_W(PDCP,"PDCP thread busy!!! inst_cnt=%d\n",pdcp_instance_cnt); } } #endif #ifdef CELLULAR rrc_rx_tx(Mod_id, frame, 0, 0); #else // check HO rrc_rx_tx(Mod_id, frame, 1, Mod_id); #endif #ifdef Rel10 if (eNB_mac_inst[Mod_id].MBMS_flag >0) { mbsfn_status = schedule_MBMS(Mod_id,frame,subframe); } #endif switch (subframe) { case 0: // FDD/TDD Schedule Downlink RA transmissions (RA response, Msg4 Contention resolution) // Schedule ULSCH for FDD or subframe 4 (TDD config 0,3,6) // Schedule Normal DLSCH schedule_RA(Mod_id,frame,subframe,2,&nprb,&nCCE); if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD // schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,4,&nCCE);//,calibration_flag); } else if ((mac_xface->lte_frame_parms->tdd_config == TDD) || //TDD (mac_xface->lte_frame_parms->tdd_config == 3) || (mac_xface->lte_frame_parms->tdd_config == 6)) //schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,4,&nCCE);//,calibration_flag); // schedule_ue_spec(Mod_id,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,1,mbsfn_status); break; case 1: // TDD, schedule UL for subframe 7 (TDD config 0,1) / subframe 8 (TDD Config 6) // FDD, schedule normal UL/DLSCH if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD switch (mac_xface->lte_frame_parms->tdd_config) { case 0: case 1: schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,7,&nCCE); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); break; case 6: schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,8,&nCCE); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); break; default: break; } } else { //FDD //schedule_ulsch(Mod_id,cooperation_flag,subframe,&nCCE); // schedule_ue_spec(Mod_id,subframe,nprb,&nCCE,mbsfn_status); // fill_DLSCH_dci(Mod_id,subframe,RBalloc,0,mbsfn_status); } break; case 2: // TDD, nothing // FDD, normal UL/DLSCH if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD // schedule_ulsch(Mod_id,cooperation_flag,subframe,&nCCE); // schedule_ue_spec(Mod_id,subframe,nprb,&nCCE,mbsfn_status); // fill_DLSCH_dci(Mod_id,subframe,RBalloc,0,mbsfn_status); } break; case 3: // TDD Config 2, ULSCH for subframe 7 // TDD Config 2/5 normal DLSCH // FDD, normal UL/DLSCH if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->tdd_config) { case 2: schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,7,&nCCE); case 5: schedule_ue_spec(Mod_id,frame,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); break; default: break; } } else { //FDD // schedule_ulsch(Mod_id,cooperation_flag,subframe,&nCCE,calibration_flag); // schedule_ue_spec(Mod_id,subframe,0,0,mbsfn_status); // fill_DLSCH_dci(Mod_id,subframe,RBalloc,0,mbsfn_status); } break; case 4: // TDD Config 1, ULSCH for subframe 8 // TDD Config 1/2/4/5 DLSCH // FDD UL/DLSCH if (mac_xface->lte_frame_parms->frame_type == 1) { // TDD switch (mac_xface->lte_frame_parms->tdd_config) { case 1: // schedule_RA(Mod_id,frame,subframe,&nprb,&nCCE); schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,8,&nCCE); case 2: case 4: case 5: schedule_ue_spec(Mod_id,frame,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,1,mbsfn_status); break; default: break; } } else { if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD // schedule_ulsch(Mod_id,cooperation_flag,subframe,&nCCE,calibration_flag); // schedule_ue_spec(Mod_id,subframe,nprb,&nCCE,mbsfn_status); // fill_DLSCH_dci(Mod_id,subframe,RBalloc,0,mbsfn_status); } } break; case 5: // TDD/FDD Schedule SI // TDD Config 0,6 ULSCH for subframes 9,3 resp. // TDD normal DLSCH // FDD normal UL/DLSCH schedule_SI(Mod_id,frame,&nprb,&nCCE); //schedule_RA(Mod_id,frame,subframe,5,&nprb,&nCCE); if ((mac_xface->lte_frame_parms->frame_type == FDD) ) { schedule_RA(Mod_id,frame,subframe,1,&nprb,&nCCE); //schedule_ulsch(Mod_id,cooperation_flag,subframe,&nCCE); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,1,mbsfn_status); } else if ((mac_xface->lte_frame_parms->tdd_config == 0) || // TDD Config 0 (mac_xface->lte_frame_parms->tdd_config == 6)) { // TDD Config 6 //schedule_ulsch(Mod_id,cooperation_flag,subframe,&nCCE); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); } else { //schedule_ue_spec(Mod_id,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); } break; case 6: // TDD Config 0,1,6 ULSCH for subframes 2,3 // TDD Config 3,4,5 Normal DLSCH // FDD normal ULSCH/DLSCH if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD switch (mac_xface->lte_frame_parms->tdd_config) { case 0: break; case 1: schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,2,&nCCE); // schedule_ue_spec(Mod_id,frame,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); break; case 6: schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,3,&nCCE); // schedule_ue_spec(Mod_id,frame,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); break; case 5: schedule_RA(Mod_id,frame,subframe,2,&nprb,&nCCE); schedule_ue_spec(Mod_id,frame,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,1,mbsfn_status); break; case 3: case 4: schedule_ue_spec(Mod_id,frame,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); break; default: break; } } else { //FDD // schedule_ulsch(Mod_id,cooperation_flag,subframe,&nCCE,calibration_flag); schedule_ue_spec(Mod_id,frame,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); } break; case 7: // TDD Config 3,4,5 Normal DLSCH // FDD Normal UL/DLSCH if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD switch (mac_xface->lte_frame_parms->tdd_config) { case 3: case 4: // schedule_RA(Mod_id,frame,subframe,3,&nprb,&nCCE); // 3 = Msg3 subframe, not schedule_ue_spec(Mod_id,frame,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); //1,mbsfn_status); break; case 5: schedule_ue_spec(Mod_id,frame,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); break; default: break; } } else { //FDD // schedule_ulsch(Mod_id,cooperation_flag,subframe,&nCCE,calibration_flag); schedule_ue_spec(Mod_id,frame,subframe,nprb,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); } break; case 8: // TDD Config 2,3,4,5 ULSCH for subframe 2 // // FDD Normal UL/DLSCH if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD switch (mac_xface->lte_frame_parms->tdd_config) { case 2: case 3: case 4: case 5: // schedule_RA(Mod_id,subframe,&nprb,&nCCE); schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,2,&nCCE); schedule_ue_spec(Mod_id,frame,subframe,0,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); break; default: break; } } else { //FDD schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,2,&nCCE); schedule_ue_spec(Mod_id,frame,subframe,0,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); } break; case 9: // TDD Config 1,3,4,6 ULSCH for subframes 3,3,3,4 if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->tdd_config) { case 1: schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,3,&nCCE); schedule_RA(Mod_id,frame,subframe,7,&nprb,&nCCE); // 7 = Msg3 subframe, not schedule_ue_spec(Mod_id,frame,subframe,0,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,1,mbsfn_status); break; case 3: case 4: schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,3,&nCCE); schedule_ue_spec(Mod_id,frame,subframe,0,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); break; case 6: schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,4,&nCCE); //schedule_RA(Mod_id,frame,subframe,&nprb,&nCCE); schedule_ue_spec(Mod_id,frame,subframe,0,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); break; case 2: case 5: //schedule_RA(Mod_id,frame,subframe,&nprb,&nCCE); schedule_ue_spec(Mod_id,frame,subframe,0,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); break; default: break; } } else { //FDD schedule_ulsch(Mod_id,frame,cooperation_flag,subframe,3,&nCCE); schedule_ue_spec(Mod_id,frame,subframe,0,&nCCE,mbsfn_status); fill_DLSCH_dci(Mod_id,frame,subframe,RBalloc,0,mbsfn_status); } break; } DCI_pdu->nCCE = nCCE; LOG_D(MAC,"frame %d, subframe %d nCCE %d\n",frame,subframe,nCCE); vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,0); }